From 951be023f912e22f580467a909cbd006d2d3974d Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 9 Dec 2009 15:31:39 +0000 Subject: [PATCH] Added tool tips to the SchedulingView. A tool tip shows the time and the thread at the mouse cursor position as well as the thread's state, how long the thread has been in this state, and what threads are running on all CPUs. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34590 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../gui/main_window/SchedulingPage.cpp | 114 +++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp b/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp index 9d557b3289..86e9e7c177 100644 --- a/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp +++ b/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -29,6 +30,7 @@ #include "chart/StringChartLegend.h" #include "HeaderView.h" #include "Model.h" +#include "util/TimeUtils.h" static const float kThreadNameMargin = 3.0f; @@ -637,7 +639,7 @@ public: fListener->DataRangeChanged(); } - void MessageReceived(BMessage* message) + virtual void MessageReceived(BMessage* message) { switch (message->what) { case B_MOUSE_WHEEL_CHANGED: @@ -659,7 +661,8 @@ public: LineBaseView::MessageReceived(message); } - void MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) + virtual void MouseMoved(BPoint where, uint32 code, + const BMessage* dragMessage) { fLastMousePos = where - LeftTop(); @@ -670,6 +673,105 @@ public: // + fDraggingStartPos.x - where.x); } + virtual bool GetToolTipAt(BPoint point, BToolTip** _tip) + { + Model::Thread* thread; + nanotime_t time; + _GetThreadAndTimeAt(point, thread, time); + if (thread == NULL) + return false; + + ThreadState threadState = UNKNOWN; + nanotime_t threadStateTime = time; + nanotime_t threadStateEndTime = time; + Model::ThreadWaitObjectGroup* threadWaitObject = NULL; + + // get the thread's state + { + const Array& threadEvents + = fSchedulingData.EventsForThread(thread->Index()); + int32 threadEventCount = threadEvents.Size(); + + int32 lower = 0; + int32 upper = threadEventCount - 1; + while (lower < upper) { + int32 mid = (lower + upper + 1) / 2; + const SchedulingEvent& event = threadEvents[mid]; + if (event.time > time) + upper = mid - 1; + else + lower = mid; + } + + if (lower >= 0 && lower < threadEventCount) { + threadState = threadEvents[lower].state; + threadStateTime = threadEvents[lower].time; + threadWaitObject = threadEvents[lower].waitObject; + if (lower + 1 < threadEventCount) + threadStateEndTime = threadEvents[lower + 1].time; + else + threadStateEndTime = fModel->LastEventTime(); + } + } + + // find out which threads are running + system_profiler_event_header** events = fModel->Events(); + size_t eventIndex = fModel->ClosestEventIndex(time + 1); + // find the first event after the one we're interested in; we'll + // skip it in the loop + + int32 cpuCount = fModel->CountCPUs(); + int32 missingThreads = cpuCount; + Model::Thread* runningThreads[cpuCount]; + memset(runningThreads, 0, sizeof(Model::Thread*) * cpuCount); + + while (missingThreads > 0 && eventIndex > 0) { + eventIndex--; + system_profiler_event_header* header = events[eventIndex]; + if (header->event != B_SYSTEM_PROFILER_THREAD_SCHEDULED + || runningThreads[header->cpu] != NULL) { + continue; + } + + system_profiler_thread_scheduled* event + = (system_profiler_thread_scheduled*)(header + 1); + if (Model::Thread* thread = fModel->ThreadByID(event->thread)) { + runningThreads[header->cpu] = thread; + missingThreads--; + } + } + + // create the tool tip + BString text; + text << "Time: " << format_nanotime(time) << "\n"; + text << "Thread: " << thread->Name() << "\n"; + text << "State: " << thread_state_name(threadState); + if (threadWaitObject != NULL) { + char objectName[32]; + snprintf(objectName, sizeof(objectName), "%#lx", + threadWaitObject->Object()); + text << " at " << wait_object_type_name(threadWaitObject->Type()) + << " \"" << threadWaitObject->Name() << "\" " + << objectName << "\n"; + } else + text << "\n"; + text << "For: " << format_nanotime(time - threadStateTime) << " of " + << format_nanotime(threadStateEndTime - threadStateTime) << "\n"; + + text << "\n"; + text << "Running Threads:"; + for (int32 i = 0; i < cpuCount; i++) { + text << "\n " << i << ": "; + if (Model::Thread* thread = runningThreads[i]) + text << thread->Name() << " (" << thread->ID() << ")"; + else + text << "?"; + } + + *_tip = new(std::nothrow) BTextToolTip(text); + return *_tip != NULL; + } + virtual void Draw(BRect updateRect) { if (fModel == NULL || fSchedulingData.InitCheck() != B_OK) @@ -866,6 +968,14 @@ printf("failed to read event!\n"); } } + void _GetThreadAndTimeAt(BPoint point, Model::Thread*& _thread, + nanotime_t& _time) + { + _thread = fModel->ThreadAt( + fFilterModel->SelectedItemAt(LineAt(point))); + _time = (nanotime_t)point.x * fNSecsPerPixel; + } + float _ScrollOffset() const { if (BScrollBar* scrollBar = ScrollBar(B_HORIZONTAL))