From 79b5db483c9152a930b2097e3d8646fe2c74f493 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 23 Aug 2008 00:12:27 +0000 Subject: [PATCH] Enhanced scheduler tracing. The reschedule tracing entry does now record more information of the unscheduled thread, namely its new state and, if waiting, also the object it is going to wait on. When scheduler tracing level 2 is enabled, additionally the address where the thread was preempted is recorded. The latter could be interesting for analyzing race condition bugs. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27168 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/scheduler.cpp | 60 +++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/scheduler.cpp b/src/system/kernel/scheduler.cpp index 70bc7f50a2..2e222d56b4 100644 --- a/src/system/kernel/scheduler.cpp +++ b/src/system/kernel/scheduler.cpp @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -109,17 +110,64 @@ public: SchedulerTraceEntry(thread), fPreviousID(previous->id), fCPU(previous->cpu->cpu_num), - fPriority(thread->priority) + fPriority(thread->priority), + fPreviousState(previous->state), + fPreviousWaitObjectType(previous->wait.type) { fName = alloc_tracing_buffer_strcpy(thread->name, B_OS_NAME_LENGTH, false); + +#if SCHEDULER_TRACING >= 2 + if (fPreviousState == B_THREAD_READY) + fPreviousPC = arch_debug_get_interrupt_pc(); + else +#endif + fPreviousWaitObject = previous->wait.object; + Initialized(); } virtual void AddDump(TraceOutput& out) { - out.Print("schedule %ld \"%s\", priority %d (from %ld, CPU %ld)", fID, - fName, fPriority, fPreviousID, fCPU); + out.Print("schedule %ld \"%s\", priority %d, CPU %ld, " + "previous thread: %ld (", fID, fName, fPriority, fCPU, fPreviousID); + if (fPreviousState == B_THREAD_WAITING) { + switch (fPreviousWaitObjectType) { + case THREAD_BLOCK_TYPE_SEMAPHORE: + out.Print("sem %ld", (sem_id)(addr_t)fPreviousWaitObject); + break; + case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: + out.Print("cvar %p", fPreviousWaitObject); + break; + case THREAD_BLOCK_TYPE_SNOOZE: + out.Print("snooze()"); + break; + case THREAD_BLOCK_TYPE_SIGNAL: + out.Print("signal"); + break; + case THREAD_BLOCK_TYPE_MUTEX: + out.Print("mutex %p", fPreviousWaitObject); + break; + case THREAD_BLOCK_TYPE_RW_LOCK: + out.Print("rwlock %p", fPreviousWaitObject); + break; + case THREAD_BLOCK_TYPE_OTHER: + out.Print("other (%p)", fPreviousWaitObject); + // We could print the string, but it might come from a + // kernel module that has already been unloaded. + break; + default: + out.Print("unknown (%p)", fPreviousWaitObject); + break; + } +#if SCHEDULER_TRACING >= 2 + } else if (fPreviousState == B_THREAD_READY) { + out.Print("ready at %p", fPreviousPC); +#endif + } else + out.Print("%s", thread_state_to_text(NULL, fPreviousState)); + + out.Print(")"); } thread_id PreviousThreadID() const { return fPreviousID; } @@ -129,6 +177,12 @@ private: int32 fCPU; char* fName; uint8 fPriority; + uint8 fPreviousState; + uint16 fPreviousWaitObjectType; + union { + const void* fPreviousWaitObject; + void* fPreviousPC; + }; }; } // namespace SchedulerTracing