* Added team and thread management to Model.

* ModelLoader does now at least evaluation team and thread added/removed events.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30301 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-04-21 20:33:15 +00:00
parent c3053cacff
commit 08e34e27d4
8 changed files with 488 additions and 23 deletions

View File

@ -25,6 +25,7 @@ MainWindow::MainWindow(DataSource* dataSource)
BWindow(BRect(50, 50, 599, 499), "DebugAnalyzer", B_DOCUMENT_WINDOW,
B_ASYNCHRONOUS_CONTROLS),
fMainTabView(NULL),
fThreadsPage(new ThreadsPage),
fModel(NULL),
fModelLoader(NULL)
{
@ -117,4 +118,6 @@ MainWindow::_SetModel(Model* model)
{
delete fModel;
fModel = model;
fThreadsPage->SetModel(fModel);
}

View File

@ -12,6 +12,7 @@ class BTabView;
class DataSource;
class ModelLoader;
class Model;
class ThreadsPage;
class MainWindow : public BWindow {
@ -30,6 +31,7 @@ private:
private:
BTabView* fMainTabView;
ThreadsPage* fThreadsPage;
Model* fModel;
ModelLoader* fModelLoader;
};

View File

@ -5,12 +5,174 @@
#include "Model.h"
#include <new>
Model::Model()
#include <stdio.h>
#include <stdlib.h>
#include <AutoDeleter.h>
// #pragma mark - Team
Model::Team::Team(const system_profiler_team_added* event, bigtime_t time)
:
fCreationEvent(event),
fCreationTime(time),
fDeletionTime(-1),
fThreads(10)
{
}
Model::Team::~Team()
{
}
bool
Model::Team::AddThread(Thread* thread)
{
return fThreads.BinaryInsert(thread, &Thread::CompareByCreationTimeID);
}
// #pragma mark - Thread
Model::Thread::Thread(Team* team, const system_profiler_thread_added* event,
bigtime_t time)
:
fTeam(team),
fCreationEvent(event),
fCreationTime(time),
fDeletionTime(-1)
{
}
Model::Thread::~Thread()
{
}
// #pragma mark - Model
Model::Model(void* eventData, size_t eventDataSize)
:
fEventData(eventData),
fEventDataSize(eventDataSize),
fTeams(20, true),
fThreads(20, true)
{
}
Model::~Model()
{
free(fEventData);
}
int32
Model::CountTeams() const
{
return fTeams.CountItems();
}
Model::Team*
Model::TeamAt(int32 index) const
{
return fTeams.ItemAt(index);
}
Model::Team*
Model::TeamByID(team_id id) const
{
return fTeams.BinarySearchByKey(id, &Team::CompareWithID);
}
Model::Team*
Model::AddTeam(const system_profiler_team_added* event, bigtime_t time)
{
Team* team = TeamByID(event->team);
if (team != NULL) {
fprintf(stderr, "Duplicate team: %ld\n", event->team);
// TODO: User feedback!
return team;
}
team = new(std::nothrow) Team(event, time);
if (team == NULL)
return NULL;
if (!fTeams.BinaryInsert(team, &Team::CompareByID)) {
delete team;
return NULL;
}
return team;
}
int32
Model::CountThreads() const
{
return fThreads.CountItems();
}
Model::Thread*
Model::ThreadAt(int32 index) const
{
return fThreads.ItemAt(index);
}
Model::Thread*
Model::ThreadByID(thread_id id) const
{
return fThreads.BinarySearchByKey(id, &Thread::CompareWithID);
}
Model::Thread*
Model::AddThread(const system_profiler_thread_added* event, bigtime_t time)
{
// check whether we do already know the thread
Thread* thread = ThreadByID(event->thread);
if (thread != NULL) {
fprintf(stderr, "Duplicate thread: %ld\n", event->thread);
// TODO: User feedback!
return thread;
}
// get its team
Team* team = TeamByID(event->team);
if (team == NULL) {
fprintf(stderr, "No team for thread: %ld\n", event->thread);
return NULL;
}
// create the thread and add it
thread = new(std::nothrow) Thread(team, event, time);
if (thread == NULL)
return NULL;
ObjectDeleter<Thread> threadDeleter(thread);
if (!fThreads.BinaryInsert(thread, &Thread::CompareByID))
return NULL;
if (!team->AddThread(thread)) {
fThreads.RemoveItem(thread);
return NULL;
}
threadDeleter.Detach();
return thread;
}

View File

@ -5,15 +5,185 @@
#ifndef MODEL_H
#define MODEL_H
#include <ObjectList.h>
#include <OS.h>
#include <system_profiler_defs.h>
class Model {
public:
Model();
struct creation_time_id;
class Team;
class Thread;
public:
Model(void* eventData, size_t eventDataSize);
~Model();
int32 CountTeams() const;
Team* TeamAt(int32 index) const;
Team* TeamByID(team_id id) const;
Team* AddTeam(
const system_profiler_team_added* event,
bigtime_t time);
int32 CountThreads() const;
Thread* ThreadAt(int32 index) const;
Thread* ThreadByID(thread_id id) const;
Thread* AddThread(
const system_profiler_thread_added* event,
bigtime_t time);
private:
typedef BObjectList<Team> TeamList;
typedef BObjectList<Thread> ThreadList;
private:
void* fEventData;
size_t fEventDataSize;
TeamList fTeams; // sorted by ID
ThreadList fThreads; // sorted by ID
};
struct Model::creation_time_id {
bigtime_t time;
thread_id id;
};
class Model::Team {
public:
Team(const system_profiler_team_added* event,
bigtime_t time);
~Team();
inline team_id ID() const;
bool AddThread(Thread* thread);
inline void SetDeletionTime(bigtime_t time);
static inline int CompareByID(const Team* a, const Team* b);
static inline int CompareWithID(const team_id* id,
const Team* team);
private:
typedef BObjectList<Thread> ThreadList;
private:
const system_profiler_team_added* fCreationEvent;
bigtime_t fCreationTime;
bigtime_t fDeletionTime;
ThreadList fThreads; // sorted by creation time, ID
};
class Model::Thread {
public:
Thread(Team* team,
const system_profiler_thread_added* event,
bigtime_t time);
~Thread();
inline thread_id ID() const;
inline void SetDeletionTime(bigtime_t time);
static inline int CompareByID(const Thread* a, const Thread* b);
static inline int CompareWithID(const thread_id* id,
const Thread* thread);
static inline int CompareByCreationTimeID(const Thread* a,
const Thread* b);
static inline int CompareWithCreationTimeID(
const creation_time_id* key,
const Thread* thread);
private:
Team* fTeam;
const system_profiler_thread_added* fCreationEvent;
bigtime_t fCreationTime;
bigtime_t fDeletionTime;
};
team_id
Model::Team::ID() const
{
return fCreationEvent->team;
}
void
Model::Team::SetDeletionTime(bigtime_t time)
{
fDeletionTime = time;
}
/*static*/ int
Model::Team::CompareByID(const Team* a, const Team* b)
{
return a->ID() - b->ID();
}
/*static*/ int
Model::Team::CompareWithID(const team_id* id, const Team* team)
{
return *id - team->ID();
}
thread_id
Model::Thread::ID() const
{
return fCreationEvent->thread;
}
void
Model::Thread::SetDeletionTime(bigtime_t time)
{
fDeletionTime = time;
}
/*static*/ int
Model::Thread::CompareByID(const Thread* a, const Thread* b)
{
return a->ID() - b->ID();
}
/*static*/ int
Model::Thread::CompareWithID(const thread_id* id, const Thread* thread)
{
return *id - thread->ID();
}
/*static*/ int
Model::Thread::CompareByCreationTimeID(const Thread* a, const Thread* b)
{
creation_time_id key;
key.time = a->fCreationTime;
key.id = a->ID();
return CompareWithCreationTimeID(&key, b);
}
/*static*/ int
Model::Thread::CompareWithCreationTimeID(const creation_time_id* key,
const Thread* thread)
{
bigtime_t cmp = key->time - thread->fCreationTime;
if (cmp == 0)
return key->id - thread->ID();
return cmp < 0 ? -1 : 1;
}
#endif // MODEL_H

View File

@ -61,21 +61,12 @@ ModelLoader::StartLoading()
if (fModel != NULL || fLoading || fDataSource == NULL)
return B_BAD_VALUE;
// create a model
Model* model = new(std::nothrow) Model;
if (model == NULL)
return B_NO_MEMORY;
ObjectDeleter<Model> modelDeleter(model);
// spawn the loader thread
fLoaderThread = spawn_thread(&_LoaderEntry, "main model loader",
B_NORMAL_PRIORITY, this);
if (fLoaderThread < 0)
return fLoaderThread;
modelDeleter.Detach();
fModel = model;
fLoading = true;
fAborted = false;
@ -156,12 +147,19 @@ ModelLoader::_Loader()
status_t
ModelLoader::_Load()
{
// get a BDataIO from the data source
BDataIO* io;
status_t error = fDataSource->CreateDataIO(&io);
// read the complete data into memory
void* eventData;
size_t eventDataSize;
status_t error = _ReadDebugEvents(&eventData, &eventDataSize);
if (error != B_OK)
return error;
ObjectDeleter<BDataIO> dataIOtDeleter(io);
// create a model
fModel = new(std::nothrow) Model(eventData, eventDataSize);
if (fModel == NULL) {
free(eventData);
return B_NO_MEMORY;
}
// create a debug input stream
BDebugEventInputStream* input = new(std::nothrow) BDebugEventInputStream;
@ -169,11 +167,12 @@ ModelLoader::_Load()
return B_NO_MEMORY;
ObjectDeleter<BDebugEventInputStream> inputDeleter(input);
error = input->SetTo(io);
error = input->SetTo(eventData, eventDataSize, false);
if (error != B_OK)
return error;
// process the events
fLastEventTime = -1;
uint32 count = 0;
while (true) {
@ -202,26 +201,143 @@ ModelLoader::_Load()
}
status_t
ModelLoader::_ReadDebugEvents(void** _eventData, size_t* _size)
{
// get a BDataIO from the data source
BDataIO* io;
status_t error = fDataSource->CreateDataIO(&io);
if (error != B_OK)
return error;
ObjectDeleter<BDataIO> dataIOtDeleter(io);
// First we need to find out how large a buffer to allocate.
size_t size;
if (BPositionIO* positionIO = dynamic_cast<BPositionIO*>(io)) {
// it's a BPositionIO -- this makes things easier, since we know how
// many bytes to read
off_t currentPos = positionIO->Position();
if (currentPos < 0)
return currentPos;
off_t fileSize;
error = positionIO->GetSize(&fileSize);
if (error != B_OK)
return error;
size = fileSize - currentPos;
} else {
// no BPositionIO -- we need to determine the total size by iteratively
// reading the whole data one time
// allocate a dummy buffer for reading
const size_t kBufferSize = 1024 * 1024;
void* buffer = malloc(kBufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter bufferDeleter(buffer);
size = 0;
while (true) {
ssize_t bytesRead = io->Read(buffer, kBufferSize);
if (bytesRead < 0)
return bytesRead;
if (bytesRead == 0)
break;
size += bytesRead;
}
// we've got the size -- recreate the BDataIO
dataIOtDeleter.Delete();
error = fDataSource->CreateDataIO(&io);
if (error != B_OK)
return error;
dataIOtDeleter.SetTo(io);
}
// allocate the data buffer
void* data = malloc(size);
if (data == NULL)
return B_NO_MEMORY;
MemoryDeleter dataDeleter(data);
// read the data
ssize_t bytesRead = io->Read(data, size);
if (bytesRead < 0)
return bytesRead;
if ((size_t)bytesRead != size)
return B_FILE_ERROR;
dataDeleter.Detach();
*_eventData = data;
*_size = size;
return B_OK;
}
status_t
ModelLoader::_ProcessEvent(uint32 event, uint32 cpu, const void* buffer,
size_t size)
{
switch (event) {
case B_SYSTEM_PROFILER_TEAM_ADDED:
printf("B_SYSTEM_PROFILER_TEAM_ADDED: %lu\n", size);
break;
{
//printf("B_SYSTEM_PROFILER_TEAM_ADDED: %lu\n", size);
system_profiler_team_added* event
= (system_profiler_team_added*)buffer;
if (fModel->AddTeam(event, fLastEventTime) == NULL)
return B_NO_MEMORY;
return B_OK;
}
case B_SYSTEM_PROFILER_TEAM_REMOVED:
printf("B_SYSTEM_PROFILER_TEAM_REMOVED: %lu\n", size);
{
//printf("B_SYSTEM_PROFILER_TEAM_REMOVED: %lu\n", size);
system_profiler_team_removed* event
= (system_profiler_team_removed*)buffer;
if (Model::Team* team = fModel->TeamByID(event->team)) {
team->SetDeletionTime(fLastEventTime);
} else {
printf("Removed event for unknown team: %ld\n", event->team);
}
break;
}
case B_SYSTEM_PROFILER_TEAM_EXEC:
printf("B_SYSTEM_PROFILER_TEAM_EXEC: %lu\n", size);
break;
case B_SYSTEM_PROFILER_THREAD_ADDED:
printf("B_SYSTEM_PROFILER_THREAD_ADDED: %lu\n", size);
{
//printf("B_SYSTEM_PROFILER_THREAD_ADDED: %lu\n", size);
system_profiler_thread_added* event
= (system_profiler_thread_added*)buffer;
if (fModel->AddThread(event, fLastEventTime) == NULL)
return B_NO_MEMORY;
return B_OK;
break;
}
case B_SYSTEM_PROFILER_THREAD_REMOVED:
printf("B_SYSTEM_PROFILER_THREAD_REMOVED: %lu\n", size);
//printf("B_SYSTEM_PROFILER_THREAD_REMOVED: %lu\n", size);
{
system_profiler_thread_removed* event
= (system_profiler_thread_removed*)buffer;
if (Model::Thread* thread = fModel->ThreadByID(event->thread)) {
thread->SetDeletionTime(fLastEventTime);
} else {
printf("Removed event for unknown team: %ld\n", event->thread);
}
break;
}
case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
printf("B_SYSTEM_PROFILER_THREAD_SCHEDULED: %lu\n", size);
break;
@ -240,7 +356,5 @@ return B_BAD_DATA;
break;
}
// TODO: Implement!
return B_OK;
}

View File

@ -32,6 +32,8 @@ private:
static status_t _LoaderEntry(void* data);
status_t _Loader();
status_t _Load();
status_t _ReadDebugEvents(void** _eventData,
size_t* _size);
status_t _ProcessEvent(uint32 event, uint32 cpu,
const void* buffer, size_t size);
@ -44,6 +46,7 @@ private:
thread_id fLoaderThread;
bool fLoading;
bool fAborted;
bigtime_t fLastEventTime;
};

View File

@ -36,3 +36,10 @@ ThreadsPage::ThreadsPage()
ThreadsPage::~ThreadsPage()
{
}
void
ThreadsPage::SetModel(Model* model)
{
fModel = model;
}

View File

@ -9,6 +9,7 @@
class BColumnListView;
class Model;
class ThreadsPage : public BGroupView {
@ -16,8 +17,11 @@ public:
ThreadsPage();
virtual ~ThreadsPage();
void SetModel(Model* model);
private:
BColumnListView* fThreadsListView;
Model* fModel;
};