Author: bonefish Date: 2009-12-20 20:48:39 +0100 (Sun, 20 Dec 2009) New Revision: 34728 Changeset: http://dev.haiku-os.org/changeset/34728/haiku Modified: haiku/trunk/src/apps/debuganalyzer/model/Model.cpp haiku/trunk/src/apps/debuganalyzer/model/Model.h haiku/trunk/src/apps/debuganalyzer/model_loader/ModelLoader.cpp haiku/trunk/src/apps/debuganalyzer/model_loader/ModelLoader.h haiku/trunk/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp Log: ModelLoader does now also create an event array per thread with all the events for that thread. Modified: haiku/trunk/src/apps/debuganalyzer/model/Model.cpp =================================================================== --- haiku/trunk/src/apps/debuganalyzer/model/Model.cpp 2009-12-20 18:04:20 UTC (rev 34727) +++ haiku/trunk/src/apps/debuganalyzer/model/Model.cpp 2009-12-20 19:48:39 UTC (rev 34728) @@ -239,6 +239,8 @@ 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,9 +269,19 @@ Model::Thread::~Thread() { + delete[] fEvents; } +void +Model::Thread::SetEvents(system_profiler_event_header** events, + size_t eventCount) +{ + fEvents = events; + fEventCount = eventCount; +} + + Model::ThreadWaitObjectGroup* Model::Thread::ThreadWaitObjectGroupFor(uint32 type, addr_t object) const { @@ -434,14 +446,20 @@ 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 @@ state->Delete(); } + delete[] fEvents; + free(fEventData); } Modified: haiku/trunk/src/apps/debuganalyzer/model/Model.h =================================================================== --- haiku/trunk/src/apps/debuganalyzer/model/Model.h 2009-12-20 18:04:20 UTC (rev 34727) +++ haiku/trunk/src/apps/debuganalyzer/model/Model.h 2009-12-20 19:48:39 UTC (rev 34728) @@ -349,6 +349,11 @@ 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 @@ 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 @@ class Model::SchedulingState { public: inline SchedulingState(); - ~SchedulingState(); + virtual ~SchedulingState(); status_t Init(); status_t Init(const CompactSchedulingState* state); @@ -488,6 +496,9 @@ 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 @@ } +system_profiler_event_header** +Model::Thread::Events() const +{ + return fEvents; +} + + +size_t +Model::Thread::CountEvents() const +{ + return fEventCount; +} + + int64 Model::Thread::Runs() const { Modified: haiku/trunk/src/apps/debuganalyzer/model_loader/ModelLoader.cpp =================================================================== --- haiku/trunk/src/apps/debuganalyzer/model_loader/ModelLoader.cpp 2009-12-20 18:04:20 UTC (rev 34727) +++ haiku/trunk/src/apps/debuganalyzer/model_loader/ModelLoader.cpp 2009-12-20 19:48:39 UTC (rev 34728) @@ -46,6 +46,9 @@ THREAD_BLOCK_TYPE_SIGNAL); +// #pragma mark - CPUInfo + + struct ModelLoader::CPUInfo { nanotime_t idleTime; @@ -57,9 +60,96 @@ }; -// #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 ModelLoader::_UpdateLastEventTime(nanotime_t time) { @@ -68,7 +158,7 @@ fModel->SetBaseTime(time); } - fState.SetLastEventTime(time - fBaseTime); + fState->SetLastEventTime(time - fBaseTime); } @@ -112,8 +202,12 @@ 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 @@ void ModelLoader::FinishLoading(bool success) { - fState.Clear(); + delete fState; + fState = NULL; if (!success) { delete fModel; @@ -197,7 +292,7 @@ // process the events fMaxCPUIndex = 0; - fState.Clear(); + fState->Clear(); fBaseTime = -1; uint64 count = 0; @@ -234,7 +329,7 @@ // 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 @@ 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 @@ } +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 @@ 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 @@ 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 @@ { _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 @@ } 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 @@ 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 @@ 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 @@ { _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 @@ 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 @@ } 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 @@ { _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 @@ // 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 @@ thread->thread->AddUnspecifiedWait(diffTime); } - thread->lastTime = fState.LastEventTime(); + thread->lastTime = fState->LastEventTime(); thread->state = WAITING; + + thread->IncrementEventCount(); } @@ -664,23 +858,23 @@ } -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 @@ 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 Modified: haiku/trunk/src/apps/debuganalyzer/model_loader/ModelLoader.h =================================================================== --- haiku/trunk/src/apps/debuganalyzer/model_loader/ModelLoader.h 2009-12-20 18:04:20 UTC (rev 34727) +++ haiku/trunk/src/apps/debuganalyzer/model_loader/ModelLoader.h 2009-12-20 19:48:39 UTC (rev 34728) @@ -41,6 +41,8 @@ thread_removed_from_run_queue; struct CPUInfo; + struct ExtendedThreadSchedulingState; + struct ExtendedSchedulingState; private: status_t _Load(); @@ -52,6 +54,7 @@ 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 @@ 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 @@ DataSource* fDataSource; CPUInfo* fCPUInfos; nanotime_t fBaseTime; - Model::SchedulingState fState; + ExtendedSchedulingState* fState; uint32 fMaxCPUIndex; }; Modified: haiku/trunk/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp =================================================================== --- haiku/trunk/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp 2009-12-20 18:04:20 UTC (rev 34727) +++ haiku/trunk/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp 2009-12-20 19:48:39 UTC (rev 34728) @@ -133,35 +133,21 @@ 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 @@ || event->previous_thread == threadID ; break; } - + case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE: { thread_enqueued_in_run_queue* event @@ -187,7 +173,7 @@ keepEvent = event->thread == threadID; break; } - + case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE: { thread_removed_from_run_queue* event @@ -200,10 +186,8 @@ 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) {