diff --git a/build/config_headers/tracing_config.h b/build/config_headers/tracing_config.h index 2c1c596a16..b6d2498db5 100644 --- a/build/config_headers/tracing_config.h +++ b/build/config_headers/tracing_config.h @@ -32,6 +32,7 @@ #define NET_BUFFER_TRACING 0 #define NET_BUFFER_TRACING_STACK_TRACE 0 /* stack trace depth */ #define RUNTIME_LOADER_TRACING 0 +#define SCHEDULER_TRACING 0 #define SIGNAL_TRACING 0 #define SYSCALL_TRACING 0 #define SYSCALL_TRACING_IGNORE_KTRACE_OUTPUT 1 diff --git a/src/system/kernel/scheduler.cpp b/src/system/kernel/scheduler.cpp index 918eb95b7d..5c4dd87ac5 100644 --- a/src/system/kernel/scheduler.cpp +++ b/src/system/kernel/scheduler.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -30,6 +31,98 @@ #endif +#if SCHEDULER_TRACING +namespace SchedulerTracing { + +class EnqueueThread : public AbstractTraceEntry { +public: + EnqueueThread(struct thread* thread, struct thread* previous, + struct thread* next) + : + fID(thread->id), + fPreviousID(-1), + fNextID(-1), + fPriority(thread->priority) + { + if (previous != NULL) + fPreviousID = previous->id; + if (next != NULL) + fNextID = next->id; + fName = alloc_tracing_buffer_strcpy(thread->name, B_OS_NAME_LENGTH, + false); + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("scheduler enqueue %ld \"%s\", priority %d (previous %ld, " + "next %ld)", fID, fName, fPriority, fPreviousID, fNextID); + } + +private: + thread_id fID; + thread_id fPreviousID; + thread_id fNextID; + char* fName; + uint8 fPriority; +}; + +class RemoveThread : public AbstractTraceEntry { +public: + RemoveThread(struct thread* thread) + : + fID(thread->id), + fPriority(thread->priority) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("scheduler remove %ld, priority %d", fID, fPriority); + } + +private: + thread_id fID; + uint8 fPriority; +}; + +class ScheduleThread : public AbstractTraceEntry { +public: + ScheduleThread(struct thread* thread, struct thread* previous) + : + fID(thread->id), + fPreviousID(previous->id), + fCPU(previous->cpu->cpu_num), + fPriority(thread->priority) + { + fName = alloc_tracing_buffer_strcpy(thread->name, B_OS_NAME_LENGTH, + false); + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("schedule %ld \"%s\", priority %d (from %ld, CPU %ld)", fID, + fName, fPriority, fPreviousID, fCPU); + } + +private: + thread_id fID; + thread_id fPreviousID; + int32 fCPU; + char* fName; + uint8 fPriority; +}; + +} // namespace SchedulerTracing + +# define T(x) new(std::nothrow) SchedulerTracing::x; +#else +# define T(x) ; +#endif + + // The run queue. Holds the threads ready to run ordered by priority. static struct thread *sRunQueue = NULL; @@ -94,6 +187,8 @@ scheduler_enqueue_in_run_queue(struct thread *thread) prev = sRunQueue; } + T(EnqueueThread(thread, prev, curr)); + thread->queue_next = curr; if (prev) prev->queue_next = thread; @@ -112,6 +207,8 @@ scheduler_remove_from_run_queue(struct thread *thread) { struct thread *item, *prev; + T(RemoveThread(thread)); + // find thread in run queue for (item = sRunQueue, prev = NULL; item && item != thread; item = item->queue_next) { @@ -246,6 +343,8 @@ scheduler_reschedule(void) else sRunQueue = nextThread->queue_next; + T(ScheduleThread(nextThread, oldThread)); + nextThread->state = B_THREAD_RUNNING; nextThread->next_state = B_THREAD_READY; oldThread->was_yielded = false;