From a63809d378bf41535f5459799c594200992356d3 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 20 Dec 2009 19:48:39 +0000 Subject: [PATCH] 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 --- src/apps/debuganalyzer/model/Model.cpp | 22 +- src/apps/debuganalyzer/model/Model.h | 27 +- .../model_loader/ModelLoader.cpp | 264 +++++++++++++++--- .../debuganalyzer/model_loader/ModelLoader.h | 10 +- .../model_loader/ThreadModelLoader.cpp | 38 +-- 5 files changed, 294 insertions(+), 67 deletions(-) diff --git a/src/apps/debuganalyzer/model/Model.cpp b/src/apps/debuganalyzer/model/Model.cpp index 07467c30f0..33b904386d 100644 --- a/src/apps/debuganalyzer/model/Model.cpp +++ b/src/apps/debuganalyzer/model/Model.cpp @@ -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); } diff --git a/src/apps/debuganalyzer/model/Model.h b/src/apps/debuganalyzer/model/Model.h index fe26d53dee..523d85dc0c 100644 --- a/src/apps/debuganalyzer/model/Model.h +++ b/src/apps/debuganalyzer/model/Model.h @@ -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 { diff --git a/src/apps/debuganalyzer/model_loader/ModelLoader.cpp b/src/apps/debuganalyzer/model_loader/ModelLoader.cpp index ea31231452..d8e9bd353d 100644 --- a/src/apps/debuganalyzer/model_loader/ModelLoader.cpp +++ b/src/apps/debuganalyzer/model_loader/ModelLoader.cpp @@ -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(thread) : NULL; + } + + +protected: + virtual void DeleteThread(Model::ThreadSchedulingState* thread) + { + delete static_cast(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 diff --git a/src/apps/debuganalyzer/model_loader/ModelLoader.h b/src/apps/debuganalyzer/model_loader/ModelLoader.h index 313f8963d8..442ac692c1 100644 --- a/src/apps/debuganalyzer/model_loader/ModelLoader.h +++ b/src/apps/debuganalyzer/model_loader/ModelLoader.h @@ -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; }; diff --git a/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp index e3e90e437b..192abfdb8e 100644 --- a/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp +++ b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp @@ -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) {