scheduler: Check team user time timers before entering scheduler
User timers may cause another thread to become ready in which case we would like this to happen before scheduler_reschedule() chooses next thread to be executed.
This commit is contained in:
parent
27c7c040de
commit
7adce94d45
@ -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);
|
||||
|
@ -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()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user