diff --git a/headers/private/kernel/kscheduler.h b/headers/private/kernel/kscheduler.h index 2d8222ebed..cbad85d9e2 100644 --- a/headers/private/kernel/kscheduler.h +++ b/headers/private/kernel/kscheduler.h @@ -83,6 +83,8 @@ status_t scheduler_set_operation_mode(scheduler_mode mode); */ void scheduler_dump_thread_data(Thread* thread); +void scheduler_new_thread_entry(Thread* thread); + void scheduler_set_cpu_enabled(int32 cpu, bool enabled); void scheduler_add_listener(struct SchedulerListener* listener); diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index ede18e6a26..b1bcef7d15 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -1007,6 +1007,58 @@ update_cpu_performance(Thread* thread, int32 thisCore) } +static inline void +stop_cpu_timers(Thread* fromThread, Thread* toThread) +{ + SpinLocker teamLocker(&fromThread->team->time_lock); + SpinLocker threadLocker(&fromThread->time_lock); + + if (fromThread->HasActiveCPUTimeUserTimers() + || fromThread->team->HasActiveCPUTimeUserTimers()) { + user_timer_stop_cpu_timers(fromThread, toThread); + } +} + + +static inline void +continue_cpu_timers(Thread* thread, cpu_ent* cpu) +{ + SpinLocker teamLocker(&thread->team->time_lock); + SpinLocker threadLocker(&thread->time_lock); + + if (thread->HasActiveCPUTimeUserTimers() + || thread->team->HasActiveCPUTimeUserTimers()) { + user_timer_continue_cpu_timers(thread, cpu->previous_thread); + } +} + + +static void +thread_resumes(Thread* thread) +{ + cpu_ent* cpu = thread->cpu; + + release_spinlock(&cpu->previous_thread->scheduler_lock); + + // continue CPU time based user timers + continue_cpu_timers(thread, cpu); + + // notify the user debugger code + if ((thread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) + user_debug_thread_scheduled(thread); +} + + +void +scheduler_new_thread_entry(Thread* thread) +{ + thread_resumes(thread); + + SpinLocker locker(thread->time_lock); + thread->last_time = system_time(); +} + + /*! Switches the currently running thread. This is a service function for scheduler implementations. @@ -1022,14 +1074,7 @@ switch_thread(Thread* fromThread, Thread* toThread) 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); + stop_cpu_timers(fromThread, toThread); // update CPU and Thread structures and perform the context switch cpu_ent* cpu = fromThread->cpu; @@ -1041,25 +1086,10 @@ switch_thread(Thread* fromThread, Thread* toThread) 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); + thread_resumes(fromThread); } @@ -1068,28 +1098,25 @@ update_thread_times(Thread* oldThread, Thread* nextThread) { bigtime_t now = system_time(); if (oldThread == nextThread) { - acquire_spinlock(&oldThread->time_lock); + SpinLocker _(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); + SpinLocker locker(oldThread->time_lock); oldThread->kernel_time += now - oldThread->last_time; oldThread->last_time = 0; - release_spinlock(&oldThread->time_lock); + locker.Unlock(); - acquire_spinlock(&nextThread->time_lock); + locker.SetTo(nextThread->time_lock, false); 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); + SpinLocker _(team->time_lock); if (team->HasActiveUserTimeUserTimers()) user_timer_check_team_user_timers(team); - release_spinlock(&team->time_lock); } diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index ca66a46140..f3474b58ca 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -698,25 +698,9 @@ common_thread_entry(void* _args) // The thread is new and has been scheduled the first time. - // start CPU time based user timers - acquire_spinlock(&thread->team->time_lock); - acquire_spinlock(&thread->time_lock); - if (thread->HasActiveCPUTimeUserTimers() - || thread->team->HasActiveCPUTimeUserTimers()) { - user_timer_continue_cpu_timers(thread, thread->cpu->previous_thread); - } - - // start tracking time - thread->last_time = system_time(); - release_spinlock(&thread->time_lock); - release_spinlock(&thread->team->time_lock); - - // notify the user debugger code - if ((thread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) - user_debug_thread_scheduled(thread); + scheduler_new_thread_entry(thread); // unlock the scheduler lock and enable interrupts - release_spinlock(&thread->cpu->previous_thread->scheduler_lock); release_spinlock(&thread->scheduler_lock); enable_interrupts();