diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index e1d7c45154..648794c89c 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -1089,8 +1089,94 @@ update_cpu_performance(Thread* thread, int32 thisCore) } +/*! Switches the currently running thread. + This is a service function for scheduler implementations. + + \param fromThread The currently running thread. + \param toThread The thread to switch to. Must be different from + \a fromThread. +*/ +static inline void +switch_thread(Thread* fromThread, Thread* toThread) +{ + // notify the user debugger code + if ((fromThread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) + user_debug_thread_unscheduled(fromThread); + + // stop CPU time based user timers + acquire_spinlock(&fromThread->team->time_lock); + acquire_spinlock(&fromThread->time_lock); + if (fromThread->HasActiveCPUTimeUserTimers() + || fromThread->team->HasActiveCPUTimeUserTimers()) { + user_timer_stop_cpu_timers(fromThread, toThread); + } + release_spinlock(&fromThread->time_lock); + release_spinlock(&fromThread->team->time_lock); + + // update CPU and Thread structures and perform the context switch + cpu_ent* cpu = fromThread->cpu; + toThread->previous_cpu = toThread->cpu = cpu; + fromThread->cpu = NULL; + cpu->running_thread = toThread; + cpu->previous_thread = fromThread; + + arch_thread_set_current_thread(toThread); + arch_thread_context_switch(fromThread, toThread); + + release_spinlock(&fromThread->cpu->previous_thread->scheduler_lock); + + // The use of fromThread below looks weird, but is correct. fromThread had + // been unscheduled earlier, but is back now. For a thread scheduled the + // first time the same is done in thread.cpp:common_thread_entry(). + + // continue CPU time based user timers + acquire_spinlock(&fromThread->team->time_lock); + acquire_spinlock(&fromThread->time_lock); + if (fromThread->HasActiveCPUTimeUserTimers() + || fromThread->team->HasActiveCPUTimeUserTimers()) { + user_timer_continue_cpu_timers(fromThread, cpu->previous_thread); + } + release_spinlock(&fromThread->time_lock); + release_spinlock(&fromThread->team->time_lock); + + // notify the user debugger code + if ((fromThread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) + user_debug_thread_scheduled(fromThread); +} + + +static inline void +update_thread_times(Thread* oldThread, Thread* nextThread) +{ + bigtime_t now = system_time(); + if (oldThread == nextThread) { + acquire_spinlock(&oldThread->time_lock); + oldThread->kernel_time += now - oldThread->last_time; + oldThread->last_time = now; + release_spinlock(&oldThread->time_lock); + } else { + acquire_spinlock(&oldThread->time_lock); + oldThread->kernel_time += now - oldThread->last_time; + oldThread->last_time = 0; + release_spinlock(&oldThread->time_lock); + + acquire_spinlock(&nextThread->time_lock); + nextThread->last_time = now; + release_spinlock(&nextThread->time_lock); + } + + // If the old thread's team has user time timers, check them now. + Team* team = oldThread->team; + + acquire_spinlock(&team->time_lock); + if (team->HasActiveUserTimeUserTimers()) + user_timer_check_team_user_timers(team); + release_spinlock(&team->time_lock); +} + + static void -_scheduler_reschedule(void) +reschedule(void) { ASSERT(!are_interrupts_enabled()); @@ -1206,7 +1292,7 @@ _scheduler_reschedule(void) compute_thread_load(nextThread); // track kernel time (user time is tracked in thread_at_kernel_entry()) - scheduler_update_thread_times(oldThread, nextThread); + update_thread_times(oldThread, nextThread); // track CPU activity track_cpu_activity(oldThread, nextThread, thisCore); @@ -1235,7 +1321,7 @@ _scheduler_reschedule(void) modeLocker.Unlock(); if (nextThread != oldThread) - scheduler_switch_thread(oldThread, nextThread); + switch_thread(oldThread, nextThread); } } @@ -1253,7 +1339,7 @@ scheduler_reschedule(void) return; } - _scheduler_reschedule(); + reschedule(); } @@ -1299,7 +1385,7 @@ scheduler_start(void) { InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock); - _scheduler_reschedule(); + reschedule(); } diff --git a/src/system/kernel/scheduler/scheduler_common.h b/src/system/kernel/scheduler/scheduler_common.h index 190e968978..2f24441855 100644 --- a/src/system/kernel/scheduler/scheduler_common.h +++ b/src/system/kernel/scheduler/scheduler_common.h @@ -184,90 +184,4 @@ get_core_load(struct Scheduler::CoreEntry* core) } -/*! Switches the currently running thread. - This is a service function for scheduler implementations. - - \param fromThread The currently running thread. - \param toThread The thread to switch to. Must be different from - \a fromThread. -*/ -static inline void -scheduler_switch_thread(Thread* fromThread, Thread* toThread) -{ - // notify the user debugger code - if ((fromThread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) - user_debug_thread_unscheduled(fromThread); - - // stop CPU time based user timers - acquire_spinlock(&fromThread->team->time_lock); - acquire_spinlock(&fromThread->time_lock); - if (fromThread->HasActiveCPUTimeUserTimers() - || fromThread->team->HasActiveCPUTimeUserTimers()) { - user_timer_stop_cpu_timers(fromThread, toThread); - } - release_spinlock(&fromThread->time_lock); - release_spinlock(&fromThread->team->time_lock); - - // update CPU and Thread structures and perform the context switch - cpu_ent* cpu = fromThread->cpu; - toThread->previous_cpu = toThread->cpu = cpu; - fromThread->cpu = NULL; - cpu->running_thread = toThread; - cpu->previous_thread = fromThread; - - arch_thread_set_current_thread(toThread); - arch_thread_context_switch(fromThread, toThread); - - release_spinlock(&fromThread->cpu->previous_thread->scheduler_lock); - - // The use of fromThread below looks weird, but is correct. fromThread had - // been unscheduled earlier, but is back now. For a thread scheduled the - // first time the same is done in thread.cpp:common_thread_entry(). - - // continue CPU time based user timers - acquire_spinlock(&fromThread->team->time_lock); - acquire_spinlock(&fromThread->time_lock); - if (fromThread->HasActiveCPUTimeUserTimers() - || fromThread->team->HasActiveCPUTimeUserTimers()) { - user_timer_continue_cpu_timers(fromThread, cpu->previous_thread); - } - release_spinlock(&fromThread->time_lock); - release_spinlock(&fromThread->team->time_lock); - - // notify the user debugger code - if ((fromThread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) - user_debug_thread_scheduled(fromThread); -} - - -static inline void -scheduler_update_thread_times(Thread* oldThread, Thread* nextThread) -{ - bigtime_t now = system_time(); - if (oldThread == nextThread) { - acquire_spinlock(&oldThread->time_lock); - oldThread->kernel_time += now - oldThread->last_time; - oldThread->last_time = now; - release_spinlock(&oldThread->time_lock); - } else { - acquire_spinlock(&oldThread->time_lock); - oldThread->kernel_time += now - oldThread->last_time; - oldThread->last_time = 0; - release_spinlock(&oldThread->time_lock); - - acquire_spinlock(&nextThread->time_lock); - nextThread->last_time = now; - release_spinlock(&nextThread->time_lock); - } - - // If the old thread's team has user time timers, check them now. - Team* team = oldThread->team; - - acquire_spinlock(&team->time_lock); - if (team->HasActiveUserTimeUserTimers()) - user_timer_check_team_user_timers(team); - release_spinlock(&team->time_lock); -} - - #endif // KERNEL_SCHEDULER_COMMON_H