ModelLoader does now also create an event array per thread with all the events

for that thread.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34728 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-12-20 19:48:39 +00:00
parent 82baa90811
commit a63809d378
5 changed files with 294 additions and 67 deletions

View File

@ -239,6 +239,8 @@ Model::Team::AddThread(Thread* thread)
Model::Thread::Thread(Team* team, const system_profiler_thread_added* event,
nanotime_t time)
:
fEvents(NULL),
fEventCount(0),
fTeam(team),
fCreationEvent(event),
fCreationTime(time),
@ -267,6 +269,16 @@ Model::Thread::Thread(Team* team, const system_profiler_thread_added* event,
Model::Thread::~Thread()
{
delete[] fEvents;
}
void
Model::Thread::SetEvents(system_profiler_event_header** events,
size_t eventCount)
{
fEvents = events;
fEventCount = eventCount;
}
@ -434,13 +446,19 @@ Model::SchedulingState::Clear()
ThreadSchedulingState* state = fThreadStates.Clear(true);
while (state != NULL) {
ThreadSchedulingState* next = state->next;
delete state;
DeleteThread(state);
state = next;
}
fLastEventTime = -1;
}
void
Model::SchedulingState::DeleteThread(ThreadSchedulingState* thread)
{
delete thread;
}
// #pragma mark - CompactSchedulingState
@ -529,6 +547,8 @@ Model::~Model()
state->Delete();
}
delete[] fEvents;
free(fEventData);
}

View File

@ -349,6 +349,11 @@ public:
inline int32 Index() const;
inline void SetIndex(int32 index);
inline system_profiler_event_header** Events() const;
inline size_t CountEvents() const;
void SetEvents(system_profiler_event_header** events,
size_t eventCount);
inline nanotime_t CreationTime() const;
inline nanotime_t DeletionTime() const;
@ -396,6 +401,9 @@ private:
ThreadWaitObjectGroupList;
private:
system_profiler_event_header** fEvents;
size_t fEventCount;
Team* fTeam;
const system_profiler_thread_added* fCreationEvent;
nanotime_t fCreationTime;
@ -474,7 +482,7 @@ struct Model::ThreadSchedulingStateDefinition {
class Model::SchedulingState {
public:
inline SchedulingState();
~SchedulingState();
virtual ~SchedulingState();
status_t Init();
status_t Init(const CompactSchedulingState* state);
@ -488,6 +496,9 @@ public:
inline void RemoveThread(ThreadSchedulingState* thread);
inline const ThreadSchedulingStateTable& ThreadStates() const;
protected:
virtual void DeleteThread(ThreadSchedulingState* thread);
private:
nanotime_t fLastEventTime;
ThreadSchedulingStateTable fThreadStates;
@ -966,6 +977,20 @@ Model::Thread::SetIndex(int32 index)
}
system_profiler_event_header**
Model::Thread::Events() const
{
return fEvents;
}
size_t
Model::Thread::CountEvents() const
{
return fEventCount;
}
int64
Model::Thread::Runs() const
{

View File

@ -46,6 +46,9 @@ static const SimpleWaitObjectInfo kSignalWaitObjectInfo(
THREAD_BLOCK_TYPE_SIGNAL);
// #pragma mark - CPUInfo
struct ModelLoader::CPUInfo {
nanotime_t idleTime;
@ -57,7 +60,94 @@ struct ModelLoader::CPUInfo {
};
// #pragma mark -
// #pragma mark - ExtendedThreadSchedulingState
struct ModelLoader::ExtendedThreadSchedulingState
: Model::ThreadSchedulingState {
ExtendedThreadSchedulingState(Model::Thread* thread)
:
Model::ThreadSchedulingState(thread),
fEvents(NULL),
fEventIndex(0),
fEventCount(0)
{
}
~ExtendedThreadSchedulingState()
{
delete[] fEvents;
}
system_profiler_event_header** Events() const
{
return fEvents;
}
size_t CountEvents() const
{
return fEventCount;
}
system_profiler_event_header** DetachEvents()
{
system_profiler_event_header** events = fEvents;
fEvents = NULL;
return events;
}
void IncrementEventCount()
{
fEventCount++;
}
void AddEvent(system_profiler_event_header* event)
{
fEvents[fEventIndex++] = event;
}
bool AllocateEventArray()
{
if (fEventCount == 0)
return true;
fEvents = new(std::nothrow) system_profiler_event_header*[fEventCount];
if (fEvents == NULL)
return false;
return true;
}
private:
system_profiler_event_header** fEvents;
size_t fEventIndex;
size_t fEventCount;
};
// #pragma mark - ExtendedSchedulingState
struct ModelLoader::ExtendedSchedulingState : Model::SchedulingState {
inline ExtendedThreadSchedulingState* LookupThread(thread_id threadID) const
{
Model::ThreadSchedulingState* thread
= Model::SchedulingState::LookupThread(threadID);
return thread != NULL
? static_cast<ExtendedThreadSchedulingState*>(thread) : NULL;
}
protected:
virtual void DeleteThread(Model::ThreadSchedulingState* thread)
{
delete static_cast<ExtendedThreadSchedulingState*>(thread);
}
};
// #pragma mark - ModelLoader
inline void
@ -68,7 +158,7 @@ ModelLoader::_UpdateLastEventTime(nanotime_t time)
fModel->SetBaseTime(time);
}
fState.SetLastEventTime(time - fBaseTime);
fState->SetLastEventTime(time - fBaseTime);
}
@ -112,8 +202,12 @@ ModelLoader::PrepareForLoading()
if (fModel != NULL || fDataSource == NULL)
return B_BAD_VALUE;
// init the state
status_t error = fState.Init();
// create and init the state
fState = new(std::nothrow) ExtendedSchedulingState;
if (fState == NULL)
return B_NO_MEMORY;
status_t error = fState->Init();
if (error != B_OK)
return error;
@ -139,7 +233,8 @@ ModelLoader::Load()
void
ModelLoader::FinishLoading(bool success)
{
fState.Clear();
delete fState;
fState = NULL;
if (!success) {
delete fModel;
@ -197,7 +292,7 @@ ModelLoader::_Load()
// process the events
fMaxCPUIndex = 0;
fState.Clear();
fState->Clear();
fBaseTime = -1;
uint64 count = 0;
@ -234,7 +329,7 @@ ModelLoader::_Load()
// periodically add scheduling snapshots
if (count % kSchedulingSnapshotInterval == 0)
fModel->AddSchedulingStateSnapshot(fState, offset);
fModel->AddSchedulingStateSnapshot(*fState, offset);
}
if (!fModel->SetCPUCount(fMaxCPUIndex + 1))
@ -243,7 +338,11 @@ ModelLoader::_Load()
for (uint32 i = 0; i <= fMaxCPUIndex; i++)
fModel->CPUAt(i)->SetIdleTime(fCPUInfos[i].idleTime);
fModel->SetLastEventTime(fState.LastEventTime());
fModel->SetLastEventTime(fState->LastEventTime());
if (!_SetThreadEvents())
return B_NO_MEMORY;
fModel->LoadingFinished();
return B_OK;
@ -447,10 +546,92 @@ return B_BAD_DATA;
}
bool
ModelLoader::_SetThreadEvents()
{
// allocate the threads' events arrays
for (int32 i = 0; Model::Thread* thread = fModel->ThreadAt(i); i++) {
ExtendedThreadSchedulingState* state
= fState->LookupThread(thread->ID());
if (!state->AllocateEventArray())
return false;
}
// fill the threads' event arrays
system_profiler_event_header** events = fModel->Events();
size_t eventCount = fModel->CountEvents();
for (size_t i = 0; i < eventCount; i++) {
system_profiler_event_header* header = events[i];
void* buffer = header + 1;
switch (header->event) {
case B_SYSTEM_PROFILER_THREAD_ADDED:
{
system_profiler_thread_added* event
= (system_profiler_thread_added*)buffer;
fState->LookupThread(event->thread)->AddEvent(header);
break;
}
case B_SYSTEM_PROFILER_THREAD_REMOVED:
{
system_profiler_thread_removed* event
= (system_profiler_thread_removed*)buffer;
fState->LookupThread(event->thread)->AddEvent(header);
break;
}
case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
{
system_profiler_thread_scheduled* event
= (system_profiler_thread_scheduled*)buffer;
fState->LookupThread(event->thread)->AddEvent(header);
if (event->thread != event->previous_thread) {
fState->LookupThread(event->previous_thread)
->AddEvent(header);
}
break;
}
case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
{
thread_enqueued_in_run_queue* event
= (thread_enqueued_in_run_queue*)buffer;
fState->LookupThread(event->thread)->AddEvent(header);
break;
}
case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
{
thread_removed_from_run_queue* event
= (thread_removed_from_run_queue*)buffer;
fState->LookupThread(event->thread)->AddEvent(header);
break;
}
default:
break;
}
}
// transfer the events arrays from the scheduling states to the thread
// objects
for (int32 i = 0; Model::Thread* thread = fModel->ThreadAt(i); i++) {
ExtendedThreadSchedulingState* state
= fState->LookupThread(thread->ID());
thread->SetEvents(state->Events(), state->CountEvents());
state->DetachEvents();
}
return true;
}
void
ModelLoader::_HandleTeamAdded(system_profiler_team_added* event)
{
if (fModel->AddTeam(event, fState.LastEventTime()) == NULL)
if (fModel->AddTeam(event, fState->LastEventTime()) == NULL)
throw std::bad_alloc();
}
@ -459,7 +640,7 @@ void
ModelLoader::_HandleTeamRemoved(system_profiler_team_removed* event)
{
if (Model::Team* team = fModel->TeamByID(event->team))
team->SetDeletionTime(fState.LastEventTime());
team->SetDeletionTime(fState->LastEventTime());
else
printf("Removed event for unknown team: %ld\n", event->team);
}
@ -475,17 +656,22 @@ ModelLoader::_HandleTeamExec(system_profiler_team_exec* event)
void
ModelLoader::_HandleThreadAdded(system_profiler_thread_added* event)
{
if (_AddThread(event) == NULL)
ExtendedThreadSchedulingState* thread = _AddThread(event);
if (thread == NULL)
throw std::bad_alloc();
thread->IncrementEventCount();
}
void
ModelLoader::_HandleThreadRemoved(system_profiler_thread_removed* event)
{
if (Model::Thread* thread = fModel->ThreadByID(event->thread))
thread->SetDeletionTime(fState.LastEventTime());
else
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
if (thread != NULL) {
thread->thread->SetDeletionTime(fState->LastEventTime());
thread->IncrementEventCount();
} else
printf("Removed event for unknown team: %ld\n", event->thread);
}
@ -496,13 +682,13 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu,
{
_UpdateLastEventTime(event->time);
Model::ThreadSchedulingState* thread = fState.LookupThread(event->thread);
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
if (thread == NULL) {
printf("Schedule event for unknown thread: %ld\n", event->thread);
return;
}
nanotime_t diffTime = fState.LastEventTime() - thread->lastTime;
nanotime_t diffTime = fState->LastEventTime() - thread->lastTime;
if (thread->state == READY) {
// thread scheduled after having been woken up
@ -518,23 +704,25 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu,
}
if (thread->state != RUNNING) {
thread->lastTime = fState.LastEventTime();
thread->lastTime = fState->LastEventTime();
thread->state = RUNNING;
}
thread->IncrementEventCount();
// unscheduled thread
if (event->thread == event->previous_thread)
return;
thread = fState.LookupThread(event->previous_thread);
thread = fState->LookupThread(event->previous_thread);
if (thread == NULL) {
printf("Schedule event for unknown previous thread: %ld\n",
event->previous_thread);
return;
}
diffTime = fState.LastEventTime() - thread->lastTime;
diffTime = fState->LastEventTime() - thread->lastTime;
if (thread->state == STILL_RUNNING) {
// thread preempted
@ -543,7 +731,7 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu,
if (thread->priority == 0)
_AddIdleTime(cpu, diffTime);
thread->lastTime = fState.LastEventTime();
thread->lastTime = fState->LastEventTime();
thread->state = PREEMPTED;
} else if (thread->state == RUNNING) {
// thread starts waiting (it hadn't been added to the run
@ -572,19 +760,21 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu,
event->previous_thread_wait_object_type, waitObject);
}
thread->lastTime = fState.LastEventTime();
thread->lastTime = fState->LastEventTime();
thread->state = WAITING;
} else if (thread->state == UNKNOWN) {
uint32 threadState = event->previous_thread_state;
if (threadState == B_THREAD_WAITING
|| threadState == B_THREAD_SUSPENDED) {
thread->lastTime = fState.LastEventTime();
thread->lastTime = fState->LastEventTime();
thread->state = WAITING;
} else if (threadState == B_THREAD_READY) {
thread->lastTime = fState.LastEventTime();
thread->lastTime = fState->LastEventTime();
thread->state = PREEMPTED;
}
}
thread->IncrementEventCount();
}
@ -594,7 +784,7 @@ ModelLoader::_HandleThreadEnqueuedInRunQueue(
{
_UpdateLastEventTime(event->time);
Model::ThreadSchedulingState* thread = fState.LookupThread(event->thread);
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
if (thread == NULL) {
printf("Enqueued in run queue event for unknown thread: %ld\n",
event->thread);
@ -607,7 +797,7 @@ ModelLoader::_HandleThreadEnqueuedInRunQueue(
thread->state = STILL_RUNNING;
} else {
// Thread was waiting and is ready now.
nanotime_t diffTime = fState.LastEventTime() - thread->lastTime;
nanotime_t diffTime = fState->LastEventTime() - thread->lastTime;
if (thread->waitObject != NULL) {
thread->waitObject->AddWait(diffTime);
thread->waitObject = NULL;
@ -615,11 +805,13 @@ ModelLoader::_HandleThreadEnqueuedInRunQueue(
} else if (thread->state != UNKNOWN)
thread->thread->AddUnspecifiedWait(diffTime);
thread->lastTime = fState.LastEventTime();
thread->lastTime = fState->LastEventTime();
thread->state = READY;
}
thread->priority = event->priority;
thread->IncrementEventCount();
}
@ -629,7 +821,7 @@ ModelLoader::_HandleThreadRemovedFromRunQueue(uint32 cpu,
{
_UpdateLastEventTime(event->time);
Model::ThreadSchedulingState* thread = fState.LookupThread(event->thread);
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
if (thread == NULL) {
printf("Removed from run queue event for unknown thread: %ld\n",
event->thread);
@ -639,7 +831,7 @@ ModelLoader::_HandleThreadRemovedFromRunQueue(uint32 cpu,
// This really only happens when the thread priority is changed
// while the thread is ready.
nanotime_t diffTime = fState.LastEventTime() - thread->lastTime;
nanotime_t diffTime = fState->LastEventTime() - thread->lastTime;
if (thread->state == RUNNING) {
// This should never happen.
thread->thread->AddRun(diffTime);
@ -651,8 +843,10 @@ ModelLoader::_HandleThreadRemovedFromRunQueue(uint32 cpu,
thread->thread->AddUnspecifiedWait(diffTime);
}
thread->lastTime = fState.LastEventTime();
thread->lastTime = fState->LastEventTime();
thread->state = WAITING;
thread->IncrementEventCount();
}
@ -664,23 +858,23 @@ ModelLoader::_HandleWaitObjectInfo(system_profiler_wait_object_info* event)
}
Model::ThreadSchedulingState*
ModelLoader::ExtendedThreadSchedulingState*
ModelLoader::_AddThread(system_profiler_thread_added* event)
{
// do we know the thread already?
Model::ThreadSchedulingState* info = fState.LookupThread(event->thread);
ExtendedThreadSchedulingState* info = fState->LookupThread(event->thread);
if (info != NULL) {
// TODO: ?
return info;
}
// add the thread to the model
Model::Thread* thread = fModel->AddThread(event, fState.LastEventTime());
Model::Thread* thread = fModel->AddThread(event, fState->LastEventTime());
if (thread == NULL)
return NULL;
// create and add a ThreadSchedulingState
info = new(std::nothrow) Model::ThreadSchedulingState(thread);
info = new(std::nothrow) ExtendedThreadSchedulingState(thread);
if (info == NULL)
return NULL;
@ -691,14 +885,14 @@ ModelLoader::_AddThread(system_profiler_thread_added* event)
else
info->priority = B_NORMAL_PRIORITY;
fState.InsertThread(info);
fState->InsertThread(info);
return info;
}
void
ModelLoader::_AddThreadWaitObject(Model::ThreadSchedulingState* thread,
ModelLoader::_AddThreadWaitObject(ExtendedThreadSchedulingState* thread,
uint32 type, addr_t object)
{
Model::WaitObjectGroup* waitObjectGroup

View File

@ -41,6 +41,8 @@ private:
thread_removed_from_run_queue;
struct CPUInfo;
struct ExtendedThreadSchedulingState;
struct ExtendedSchedulingState;
private:
status_t _Load();
@ -52,6 +54,7 @@ private:
size_t& _eventCount);
status_t _ProcessEvent(uint32 event, uint32 cpu,
const void* buffer, size_t size);
bool _SetThreadEvents();
inline void _UpdateLastEventTime(nanotime_t time);
@ -74,9 +77,10 @@ private:
void _HandleWaitObjectInfo(
system_profiler_wait_object_info* event);
Model::ThreadSchedulingState* _AddThread(
ExtendedThreadSchedulingState* _AddThread(
system_profiler_thread_added* event);
void _AddThreadWaitObject(Model::ThreadSchedulingState* thread,
void _AddThreadWaitObject(
ExtendedThreadSchedulingState* thread,
uint32 type, addr_t object);
void _AddIdleTime(uint32 cpu, nanotime_t time);
@ -86,7 +90,7 @@ private:
DataSource* fDataSource;
CPUInfo* fCPUInfos;
nanotime_t fBaseTime;
Model::SchedulingState fState;
ExtendedSchedulingState* fState;
uint32 fMaxCPUIndex;
};

View File

@ -133,35 +133,21 @@ printf("new wait object group at %ld\n", i);
i = k;
}
// create a debug input stream
BDebugEventInputStream input;
uint8* eventData = (uint8*)fModel->EventData();
status_t error = input.SetTo(eventData, fModel->EventDataSize(), false);
if (error != B_OK)
return error;
// process the events
// filter the events
thread_id threadID = fThread->ID();
bool done = false;
uint32 count = 0;
while (!done) {
// get next event
uint32 eventType;
uint32 cpu;
const void* buffer;
off_t streamOffset;
ssize_t bufferSize = input.ReadNextEvent(&eventType, &cpu, &buffer,
&streamOffset);
if (bufferSize < 0)
return bufferSize;
if (buffer == NULL)
break;
system_profiler_event_header** events = fModel->Events();
size_t eventCount = fModel->CountEvents();
for (size_t i = 0; i < eventCount; i++) {
system_profiler_event_header* header = events[i];
void* buffer = header + 1;
// process the event
bool keepEvent = false;
switch (eventType) {
switch (header->event) {
case B_SYSTEM_PROFILER_THREAD_REMOVED:
{
system_profiler_thread_removed* event
@ -179,7 +165,7 @@ printf("new wait object group at %ld\n", i);
|| event->previous_thread == threadID ;
break;
}
case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
{
thread_enqueued_in_run_queue* event
@ -187,7 +173,7 @@ printf("new wait object group at %ld\n", i);
keepEvent = event->thread == threadID;
break;
}
case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
{
thread_removed_from_run_queue* event
@ -200,10 +186,8 @@ printf("new wait object group at %ld\n", i);
break;
}
if (keepEvent) {
fThreadModel->AddSchedulingEvent(
(system_profiler_event_header*)(eventData + streamOffset));
}
if (keepEvent)
fThreadModel->AddSchedulingEvent(header);
// periodically check whether we're supposed to abort
if (++count % 32 == 0) {