diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 6437cb0d32..968d583d13 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -328,55 +328,28 @@ switch_thread(Thread* fromThread, Thread* toThread) } -static inline void -update_thread_times(Thread* oldThread, Thread* nextThread) -{ - SCHEDULER_ENTER_FUNCTION(); - - bigtime_t now = system_time(); - if (oldThread == nextThread) { - SpinLocker _(oldThread->time_lock); - oldThread->kernel_time += now - oldThread->last_time; - oldThread->last_time = now; - } else { - SpinLocker locker(oldThread->time_lock); - oldThread->kernel_time += now - oldThread->last_time; - oldThread->last_time = 0; - locker.Unlock(); - - locker.SetTo(nextThread->time_lock, false); - nextThread->last_time = now; - } - - // If the old thread's team has user time timers, check them now. - Team* team = oldThread->team; - - SpinLocker _(team->time_lock); - if (team->HasActiveUserTimeUserTimers()) - user_timer_check_team_user_timers(team); -} - - static void reschedule(int32 nextState) { ASSERT(!are_interrupts_enabled()); SCHEDULER_ENTER_FUNCTION(); - SchedulerModeLocker modeLocker; - - Thread* oldThread = thread_get_current_thread(); - int32 thisCPU = smp_get_current_cpu(); CPUEntry* cpu = CPUEntry::GetCPU(thisCPU); CoreEntry* core = CoreEntry::GetCore(thisCPU); + Thread* oldThread = thread_get_current_thread(); + ThreadData* oldThreadData = oldThread->scheduler_data; + + oldThreadData->StopCPUTime(); + + SchedulerModeLocker modeLocker; + TRACE("reschedule(): cpu %ld, current thread = %ld\n", thisCPU, oldThread->id); oldThread->state = nextState; - ThreadData* oldThreadData = oldThread->scheduler_data; // return time spent in interrupts oldThreadData->SetStolenInterruptTime(gCPU[thisCPU].interrupt_time); @@ -470,9 +443,7 @@ reschedule(int32 nextState) ASSERT(nextThreadData->Core() == core); nextThread->state = B_THREAD_RUNNING; - - // track kernel time (user time is tracked in thread_at_kernel_entry()) - update_thread_times(oldThread, nextThread); + nextThreadData->StartCPUTime(); // track CPU activity cpu->TrackActivity(oldThreadData, nextThreadData); diff --git a/src/system/kernel/scheduler/scheduler_thread.h b/src/system/kernel/scheduler/scheduler_thread.h index 026d5237b7..e812065175 100644 --- a/src/system/kernel/scheduler/scheduler_thread.h +++ b/src/system/kernel/scheduler/scheduler_thread.h @@ -50,6 +50,9 @@ public: inline bool IsCPUBound() const { return fCPUBound; } + inline void StartCPUTime(); + inline void StopCPUTime(); + inline void CancelPenalty(); inline bool ShouldCancelPenalty() const; @@ -216,6 +219,35 @@ ThreadData::_IncreasePenalty() } +inline void +ThreadData::StartCPUTime() +{ + SCHEDULER_ENTER_FUNCTION(); + + SpinLocker threadTimeLocker(fThread->time_lock); + fThread->last_time = system_time(); +} + + +inline void +ThreadData::StopCPUTime() +{ + SCHEDULER_ENTER_FUNCTION(); + + // User time is tracked in thread_at_kernel_entry() + SpinLocker threadTimeLocker(fThread->time_lock); + fThread->kernel_time += system_time() - fThread->last_time; + fThread->last_time = 0; + threadTimeLocker.Unlock(); + + // If the old thread's team has user time timers, check them now. + Team* team = fThread->team; + SpinLocker teamTimeLocker(team->time_lock); + if (team->HasActiveUserTimeUserTimers()) + user_timer_check_team_user_timers(team); +} + + inline void ThreadData::CancelPenalty() {