kernel: Introduce Thread::time_lock and Team::time_lock

This commit is contained in:
Pawel Dziepak
2013-11-07 22:16:36 +01:00
parent 3519eb334a
commit 72addc62e0
5 changed files with 78 additions and 52 deletions
+6 -5
View File
@@ -264,10 +264,11 @@ struct Team : TeamThreadIteratorEntry<team_id>, KernelReferenceable,
struct team_debug_info debug_info; struct team_debug_info debug_info;
// protected by scheduler lock // protected by time_lock
bigtime_t dead_threads_kernel_time; bigtime_t dead_threads_kernel_time;
bigtime_t dead_threads_user_time; bigtime_t dead_threads_user_time;
bigtime_t cpu_clock_offset; bigtime_t cpu_clock_offset;
spinlock time_lock;
// user group information; protected by fLock, the *_uid/*_gid fields also // user group information; protected by fLock, the *_uid/*_gid fields also
// by the scheduler lock // by the scheduler lock
@@ -516,7 +517,7 @@ struct Thread : TeamThreadIteratorEntry<thread_id>, KernelReferenceable,
bigtime_t user_time; // protected by time_lock bigtime_t user_time; // protected by time_lock
bigtime_t kernel_time; // protected by time_lock bigtime_t kernel_time; // protected by time_lock
bigtime_t last_time; // protected by time_lock bigtime_t last_time; // protected by time_lock
bigtime_t cpu_clock_offset; // protected by scheduler lock bigtime_t cpu_clock_offset; // protected by time_lock
void (*post_interrupt_callback)(void*); void (*post_interrupt_callback)(void*);
void* post_interrupt_data; void* post_interrupt_data;
@@ -610,7 +611,7 @@ private:
UserTimerList fUserTimers; // protected by fLock UserTimerList fUserTimers; // protected by fLock
ThreadTimeUserTimerList fCPUTimeUserTimers; ThreadTimeUserTimerList fCPUTimeUserTimers;
// protected by scheduler lock // protected by time_lock
}; };
@@ -749,7 +750,7 @@ Thread::DequeuePendingSignal(sigset_t nonBlocked, Signal& buffer)
/*! Returns the thread's current total CPU time (kernel + user + offset). /*! Returns the thread's current total CPU time (kernel + user + offset).
The caller must hold the scheduler lock. The caller must hold \c time_lock.
\param ignoreCurrentRun If \c true and the thread is currently running, \param ignoreCurrentRun If \c true and the thread is currently running,
don't add the time since the last time \c last_time was updated. Should don't add the time since the last time \c last_time was updated. Should
@@ -764,7 +765,7 @@ Thread::CPUTime(bool ignoreCurrentRun) const
// If currently running, also add the time since the last check, unless // If currently running, also add the time since the last check, unless
// requested otherwise. // requested otherwise.
if (!ignoreCurrentRun && cpu != NULL) if (!ignoreCurrentRun && last_time != 0)
time += system_time() - last_time; time += system_time() - last_time;
return time; return time;
+40 -34
View File
@@ -137,8 +137,6 @@ UserTimer::~UserTimer()
Cancels the timer, if it is already scheduled, and optionally schedules it Cancels the timer, if it is already scheduled, and optionally schedules it
with new parameters. with new parameters.
The caller must not hold the scheduler lock.
\param nextTime The time at which the timer should go off the next time. If \param nextTime The time at which the timer should go off the next time. If
\c B_INFINITE_TIMEOUT, the timer will not be scheduled. Whether the \c B_INFINITE_TIMEOUT, the timer will not be scheduled. Whether the
value is interpreted as absolute or relative time, depends on \c flags. value is interpreted as absolute or relative time, depends on \c flags.
@@ -160,8 +158,6 @@ UserTimer::~UserTimer()
/*! Cancels the timer, if it is scheduled. /*! Cancels the timer, if it is scheduled.
The caller must not hold the scheduler lock.
*/ */
void void
UserTimer::Cancel() UserTimer::Cancel()
@@ -176,8 +172,6 @@ UserTimer::Cancel()
uint32& _overrunCount) uint32& _overrunCount)
Return information on the current timer. Return information on the current timer.
The caller must not hold the scheduler lock.
\param _remainingTime Return variable that will be set to the microseconds \param _remainingTime Return variable that will be set to the microseconds
remaining to the time for which the timer was scheduled next before the remaining to the time for which the timer was scheduled next before the
call. If it wasn't scheduled, the variable is set to call. If it wasn't scheduled, the variable is set to
@@ -513,7 +507,7 @@ TeamTimeUserTimer::Schedule(bigtime_t nextTime, bigtime_t interval,
uint32 flags, bigtime_t& _oldRemainingTime, bigtime_t& _oldInterval) uint32 flags, bigtime_t& _oldRemainingTime, bigtime_t& _oldInterval)
{ {
InterruptsWriteSequentialLocker locker(sUserTimerLock); InterruptsWriteSequentialLocker locker(sUserTimerLock);
InterruptsSpinLocker schedulerLocker(gSchedulerLock); SpinLocker timeLocker(fTeam != NULL ? &fTeam->time_lock : NULL);
// get the current time, but only if needed // get the current time, but only if needed
bool nowValid = fTeam != NULL; bool nowValid = fTeam != NULL;
@@ -547,9 +541,13 @@ TeamTimeUserTimer::Schedule(bigtime_t nextTime, bigtime_t interval,
// Get the team. If it doesn't exist anymore, just don't schedule the // Get the team. If it doesn't exist anymore, just don't schedule the
// timer anymore. // timer anymore.
fTeam = Team::Get(fTeamID); Team* newTeam = Team::Get(fTeamID);
if (fTeam == NULL) if (newTeam == NULL) {
fTeam = NULL;
return; return;
} else if (fTeam == NULL)
timeLocker.SetTo(newTeam->time_lock, false);
fTeam = newTeam;
fAbsolute = (flags & B_RELATIVE_TIMEOUT) == 0; fAbsolute = (flags & B_RELATIVE_TIMEOUT) == 0;
@@ -576,7 +574,7 @@ TeamTimeUserTimer::GetInfo(bigtime_t& _remainingTime, bigtime_t& _interval,
count = acquire_read_seqlock(&sUserTimerLock); count = acquire_read_seqlock(&sUserTimerLock);
if (fTeam != NULL) { if (fTeam != NULL) {
InterruptsSpinLocker schedulerLocker(gSchedulerLock); InterruptsSpinLocker timeLocker(fTeam->time_lock);
_remainingTime = fNextTime - fTeam->CPUTime(false); _remainingTime = fNextTime - fTeam->CPUTime(false);
_interval = fInterval; _interval = fInterval;
} else { } else {
@@ -591,7 +589,7 @@ TeamTimeUserTimer::GetInfo(bigtime_t& _remainingTime, bigtime_t& _interval,
/*! Deactivates the timer, if it is activated. /*! Deactivates the timer, if it is activated.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
*/ */
void void
TeamTimeUserTimer::Deactivate() TeamTimeUserTimer::Deactivate()
@@ -619,7 +617,7 @@ TeamTimeUserTimer::Deactivate()
was just set. Schedules a kernel timer for the remaining time, respectively was just set. Schedules a kernel timer for the remaining time, respectively
cancels it. cancels it.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
\param unscheduledThread If not \c NULL, this is the thread that is \param unscheduledThread If not \c NULL, this is the thread that is
currently running and which is in the process of being unscheduled. currently running and which is in the process of being unscheduled.
@@ -646,7 +644,7 @@ TeamTimeUserTimer::Update(Thread* unscheduledThread)
/*! Called when the team's CPU time clock which this timer refers to has been /*! Called when the team's CPU time clock which this timer refers to has been
set. set.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
\param changedBy The value by which the clock has changed. \param changedBy The value by which the clock has changed.
*/ */
@@ -689,7 +687,7 @@ TeamTimeUserTimer::HandleTimer()
/*! Schedules/cancels the kernel timer as necessary. /*! Schedules/cancels the kernel timer as necessary.
\c fRunningThreads must be up-to-date. \c fRunningThreads must be up-to-date.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
\param unscheduling \c true, when the current thread is in the process of \param unscheduling \c true, when the current thread is in the process of
being unscheduled. being unscheduled.
@@ -757,7 +755,7 @@ TeamUserTimeUserTimer::Schedule(bigtime_t nextTime, bigtime_t interval,
uint32 flags, bigtime_t& _oldRemainingTime, bigtime_t& _oldInterval) uint32 flags, bigtime_t& _oldRemainingTime, bigtime_t& _oldInterval)
{ {
InterruptsWriteSequentialLocker locker(sUserTimerLock); InterruptsWriteSequentialLocker locker(sUserTimerLock);
InterruptsSpinLocker schedulerLocker(gSchedulerLock); SpinLocker timeLocker(fTeam != NULL ? &fTeam->time_lock : NULL);
// get the current time, but only if needed // get the current time, but only if needed
bool nowValid = fTeam != NULL; bool nowValid = fTeam != NULL;
@@ -786,9 +784,13 @@ TeamUserTimeUserTimer::Schedule(bigtime_t nextTime, bigtime_t interval,
// Get the team. If it doesn't exist anymore, just don't schedule the // Get the team. If it doesn't exist anymore, just don't schedule the
// timer anymore. // timer anymore.
fTeam = Team::Get(fTeamID); Team* newTeam = Team::Get(fTeamID);
if (fTeam == NULL) if (newTeam == NULL) {
fTeam = NULL;
return; return;
} else if (fTeam == NULL)
timeLocker.SetTo(newTeam->time_lock, false);
fTeam = newTeam;
// convert relative to absolute timeouts // convert relative to absolute timeouts
if ((flags & B_RELATIVE_TIMEOUT) != 0) { if ((flags & B_RELATIVE_TIMEOUT) != 0) {
@@ -813,7 +815,7 @@ TeamUserTimeUserTimer::GetInfo(bigtime_t& _remainingTime, bigtime_t& _interval,
count = acquire_read_seqlock(&sUserTimerLock); count = acquire_read_seqlock(&sUserTimerLock);
if (fTeam != NULL) { if (fTeam != NULL) {
InterruptsSpinLocker schedulerLocker(gSchedulerLock); InterruptsSpinLocker timeLocker(fTeam->time_lock);
_remainingTime = fNextTime - fTeam->UserCPUTime(); _remainingTime = fNextTime - fTeam->UserCPUTime();
_interval = fInterval; _interval = fInterval;
} else { } else {
@@ -828,7 +830,7 @@ TeamUserTimeUserTimer::GetInfo(bigtime_t& _remainingTime, bigtime_t& _interval,
/*! Deactivates the timer, if it is activated. /*! Deactivates the timer, if it is activated.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
*/ */
void void
TeamUserTimeUserTimer::Deactivate() TeamUserTimeUserTimer::Deactivate()
@@ -845,7 +847,7 @@ TeamUserTimeUserTimer::Deactivate()
/*! Checks whether the timer is up, firing an event, if so. /*! Checks whether the timer is up, firing an event, if so.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
*/ */
void void
TeamUserTimeUserTimer::Check() TeamUserTimeUserTimer::Check()
@@ -899,7 +901,7 @@ ThreadTimeUserTimer::Schedule(bigtime_t nextTime, bigtime_t interval,
uint32 flags, bigtime_t& _oldRemainingTime, bigtime_t& _oldInterval) uint32 flags, bigtime_t& _oldRemainingTime, bigtime_t& _oldInterval)
{ {
InterruptsWriteSequentialLocker locker(sUserTimerLock); InterruptsWriteSequentialLocker locker(sUserTimerLock);
InterruptsSpinLocker schedulerLocker(gSchedulerLock); SpinLocker timeLocker(fThread->time_lock);
// get the current time, but only if needed // get the current time, but only if needed
bool nowValid = fThread != NULL; bool nowValid = fThread != NULL;
@@ -933,9 +935,13 @@ ThreadTimeUserTimer::Schedule(bigtime_t nextTime, bigtime_t interval,
// Get the thread. If it doesn't exist anymore, just don't schedule the // Get the thread. If it doesn't exist anymore, just don't schedule the
// timer anymore. // timer anymore.
fThread = Thread::Get(fThreadID); Thread* newThread = Thread::Get(fThreadID);
if (fThread == NULL) if (newThread == NULL) {
fThread = NULL;
return; return;
} else if (fThread == NULL)
timeLocker.SetTo(newThread->time_lock, false);
fThread = newThread;
fAbsolute = (flags & B_RELATIVE_TIMEOUT) == 0; fAbsolute = (flags & B_RELATIVE_TIMEOUT) == 0;
@@ -963,7 +969,7 @@ ThreadTimeUserTimer::GetInfo(bigtime_t& _remainingTime, bigtime_t& _interval,
count = acquire_read_seqlock(&sUserTimerLock); count = acquire_read_seqlock(&sUserTimerLock);
if (fThread != NULL) { if (fThread != NULL) {
InterruptsSpinLocker schedulerLocker(gSchedulerLock); SpinLocker timeLocker(fThread->time_lock);
_remainingTime = fNextTime - fThread->CPUTime(false); _remainingTime = fNextTime - fThread->CPUTime(false);
_interval = fInterval; _interval = fInterval;
} else { } else {
@@ -978,7 +984,7 @@ ThreadTimeUserTimer::GetInfo(bigtime_t& _remainingTime, bigtime_t& _interval,
/*! Deactivates the timer, if it is activated. /*! Deactivates the timer, if it is activated.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
*/ */
void void
ThreadTimeUserTimer::Deactivate() ThreadTimeUserTimer::Deactivate()
@@ -1005,7 +1011,7 @@ ThreadTimeUserTimer::Deactivate()
scheduled, or, when the timer was just set and the thread is already scheduled, or, when the timer was just set and the thread is already
running. Schedules a kernel timer for the remaining time. running. Schedules a kernel timer for the remaining time.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
*/ */
void void
ThreadTimeUserTimer::Start() ThreadTimeUserTimer::Start()
@@ -1066,7 +1072,7 @@ ThreadTimeUserTimer::Stop()
/*! Called when the team's CPU time clock which this timer refers to has been /*! Called when the team's CPU time clock which this timer refers to has been
set. set.
The caller must hold the scheduler lock and \c sUserTimerLock. The caller must hold \c time_lock and \c sUserTimerLock.
\param changedBy The value by which the clock has changed. \param changedBy The value by which the clock has changed.
*/ */
@@ -1358,7 +1364,7 @@ create_timer(clockid_t clockID, int32 timerID, Team* team, Thread* thread,
/*! Called when the CPU time clock of the given thread has been set. /*! Called when the CPU time clock of the given thread has been set.
The caller must hold the scheduler lock. The caller must hold \c time_lock.
\param thread The thread whose CPU time clock has been set. \param thread The thread whose CPU time clock has been set.
\param changedBy The value by which the CPU time clock has changed \param changedBy The value by which the CPU time clock has changed
@@ -1377,7 +1383,7 @@ thread_clock_changed(Thread* thread, bigtime_t changedBy)
/*! Called when the CPU time clock of the given team has been set. /*! Called when the CPU time clock of the given team has been set.
The caller must hold the scheduler lock. The caller must hold \c time_lock.
\param team The team whose CPU time clock has been set. \param team The team whose CPU time clock has been set.
\param changedBy The value by which the CPU time clock has changed \param changedBy The value by which the CPU time clock has changed
@@ -1477,7 +1483,7 @@ user_timer_get_clock(clockid_t clockID, bigtime_t& _time)
case CLOCK_THREAD_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID:
{ {
Thread* thread = thread_get_current_thread(); Thread* thread = thread_get_current_thread();
InterruptsSpinLocker schedulerLocker(gSchedulerLock); InterruptsSpinLocker timeLocker(thread->time_lock);
_time = thread->CPUTime(false); _time = thread->CPUTime(false);
return B_OK; return B_OK;
} }
@@ -1485,7 +1491,7 @@ user_timer_get_clock(clockid_t clockID, bigtime_t& _time)
case CLOCK_PROCESS_USER_CPUTIME_ID: case CLOCK_PROCESS_USER_CPUTIME_ID:
{ {
Team* team = thread_get_current_thread()->team; Team* team = thread_get_current_thread()->team;
InterruptsSpinLocker schedulerLocker(gSchedulerLock); InterruptsSpinLocker timeLocker(team->time_lock);
_time = team->UserCPUTime(); _time = team->UserCPUTime();
return B_OK; return B_OK;
} }
@@ -1513,7 +1519,7 @@ user_timer_get_clock(clockid_t clockID, bigtime_t& _time)
BReference<Team> teamReference(team, true); BReference<Team> teamReference(team, true);
// get the time // get the time
InterruptsSpinLocker schedulerLocker(gSchedulerLock); InterruptsSpinLocker timeLocker(team->time_lock);
_time = team->CPUTime(false); _time = team->CPUTime(false);
return B_OK; return B_OK;
@@ -1630,7 +1636,7 @@ _user_set_clock(clockid_t clockID, bigtime_t time)
case CLOCK_THREAD_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID:
{ {
Thread* thread = thread_get_current_thread(); Thread* thread = thread_get_current_thread();
InterruptsSpinLocker schedulerLocker(gSchedulerLock); InterruptsSpinLocker timeLocker(thread->time_lock);
bigtime_t diff = time - thread->CPUTime(false); bigtime_t diff = time - thread->CPUTime(false);
thread->cpu_clock_offset += diff; thread->cpu_clock_offset += diff;
@@ -1665,7 +1671,7 @@ _user_set_clock(clockid_t clockID, bigtime_t time)
BReference<Team> teamReference(team, true); BReference<Team> teamReference(team, true);
// set the time offset // set the time offset
InterruptsSpinLocker schedulerLocker(gSchedulerLock); InterruptsSpinLocker timeLocker(team->time_lock);
bigtime_t diff = time - team->CPUTime(false); bigtime_t diff = time - team->CPUTime(false);
team->cpu_clock_offset += diff; team->cpu_clock_offset += diff;
@@ -26,10 +26,14 @@ scheduler_switch_thread(Thread* fromThread, Thread* toThread)
user_debug_thread_unscheduled(fromThread); user_debug_thread_unscheduled(fromThread);
// stop CPU time based user timers // stop CPU time based user timers
acquire_spinlock(&fromThread->team->time_lock);
acquire_spinlock(&fromThread->time_lock);
if (fromThread->HasActiveCPUTimeUserTimers() if (fromThread->HasActiveCPUTimeUserTimers()
|| fromThread->team->HasActiveCPUTimeUserTimers()) { || fromThread->team->HasActiveCPUTimeUserTimers()) {
user_timer_stop_cpu_timers(fromThread, toThread); 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 // update CPU and Thread structures and perform the context switch
cpu_ent* cpu = fromThread->cpu; cpu_ent* cpu = fromThread->cpu;
@@ -46,10 +50,14 @@ scheduler_switch_thread(Thread* fromThread, Thread* toThread)
// first time the same is done in thread.cpp:common_thread_entry(). // first time the same is done in thread.cpp:common_thread_entry().
// continue CPU time based user timers // continue CPU time based user timers
acquire_spinlock(&fromThread->team->time_lock);
acquire_spinlock(&fromThread->time_lock);
if (fromThread->HasActiveCPUTimeUserTimers() if (fromThread->HasActiveCPUTimeUserTimers()
|| fromThread->team->HasActiveCPUTimeUserTimers()) { || fromThread->team->HasActiveCPUTimeUserTimers()) {
user_timer_continue_cpu_timers(fromThread, cpu->previous_thread); 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 // notify the user debugger code
if ((fromThread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) if ((fromThread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0)
@@ -69,6 +77,7 @@ scheduler_update_thread_times(Thread* oldThread, Thread* nextThread)
} else { } else {
acquire_spinlock(&oldThread->time_lock); acquire_spinlock(&oldThread->time_lock);
oldThread->kernel_time += now - oldThread->last_time; oldThread->kernel_time += now - oldThread->last_time;
oldThread->last_time = 0;
release_spinlock(&oldThread->time_lock); release_spinlock(&oldThread->time_lock);
acquire_spinlock(&nextThread->time_lock); acquire_spinlock(&nextThread->time_lock);
@@ -78,8 +87,11 @@ scheduler_update_thread_times(Thread* oldThread, Thread* nextThread)
// If the old thread's team has user time timers, check them now. // If the old thread's team has user time timers, check them now.
Team* team = oldThread->team; Team* team = oldThread->team;
acquire_spinlock(&team->time_lock);
if (team->HasActiveUserTimeUserTimers()) if (team->HasActiveUserTimeUserTimers())
user_timer_check_team_user_timers(team); user_timer_check_team_user_timers(team);
release_spinlock(&team->time_lock);
} }
+7 -6
View File
@@ -490,6 +490,7 @@ Team::Team(team_id id, bool kernel)
// init dead/stopped/continued children condition vars // init dead/stopped/continued children condition vars
dead_children.condition_variable.Init(&dead_children, "team children"); dead_children.condition_variable.Init(&dead_children, "team children");
B_INITIALIZE_SPINLOCK(&time_lock);
B_INITIALIZE_SPINLOCK(&signal_lock); B_INITIALIZE_SPINLOCK(&signal_lock);
fQueuedSignalsCounter = new(std::nothrow) BKernel::QueuedSignalsCounter( fQueuedSignalsCounter = new(std::nothrow) BKernel::QueuedSignalsCounter(
@@ -908,7 +909,7 @@ Team::DeactivateCPUTimeUserTimers()
/*! Returns the team's current total CPU time (kernel + user + offset). /*! Returns the team's current total CPU time (kernel + user + offset).
The caller must hold the scheduler lock. The caller must hold \c time_lock.
\param ignoreCurrentRun If \c true and the current thread is one team's \param ignoreCurrentRun If \c true and the current thread is one team's
threads, don't add the time since the last time \c last_time was threads, don't add the time since the last time \c last_time was
@@ -931,7 +932,7 @@ Team::CPUTime(bool ignoreCurrentRun) const
SpinLocker threadTimeLocker(thread->time_lock); SpinLocker threadTimeLocker(thread->time_lock);
time += thread->kernel_time + thread->user_time; time += thread->kernel_time + thread->user_time;
if (thread->IsRunning()) { if (thread->last_time != 0) {
if (!ignoreCurrentRun || thread != currentThread) if (!ignoreCurrentRun || thread != currentThread)
time += now - thread->last_time; time += now - thread->last_time;
} }
@@ -943,7 +944,7 @@ Team::CPUTime(bool ignoreCurrentRun) const
/*! Returns the team's current user CPU time. /*! Returns the team's current user CPU time.
The caller must hold the scheduler lock. The caller must hold \c time_lock.
\return The team's current user CPU time. \return The team's current user CPU time.
*/ */
@@ -959,7 +960,7 @@ Team::UserCPUTime() const
SpinLocker threadTimeLocker(thread->time_lock); SpinLocker threadTimeLocker(thread->time_lock);
time += thread->user_time; time += thread->user_time;
if (thread->IsRunning() && !thread->in_kernel) if (thread->last_time != 0 && !thread->in_kernel)
time += now - thread->last_time; time += now - thread->last_time;
} }
@@ -3093,12 +3094,12 @@ team_shutdown_team(Team* team)
team->DeleteUserTimers(false); team->DeleteUserTimers(false);
// deactivate CPU time user timers for the team // deactivate CPU time user timers for the team
InterruptsSpinLocker schedulerLocker(gSchedulerLock); InterruptsSpinLocker timeLocker(team->time_lock);
if (team->HasActiveCPUTimeUserTimers()) if (team->HasActiveCPUTimeUserTimers())
team->DeactivateCPUTimeUserTimers(); team->DeactivateCPUTimeUserTimers();
schedulerLocker.Unlock(); timeLocker.Unlock();
// kill all threads but the main thread // kill all threads but the main thread
team_death_entry deathEntry; team_death_entry deathEntry;
+13 -7
View File
@@ -696,18 +696,22 @@ common_thread_entry(void* _args)
// The thread is new and has been scheduled the first time. // The thread is new and has been scheduled the first time.
// start CPU time based user timers // start CPU time based user timers
acquire_spinlock(&thread->team->time_lock);
acquire_spinlock(&thread->time_lock);
if (thread->HasActiveCPUTimeUserTimers() if (thread->HasActiveCPUTimeUserTimers()
|| thread->team->HasActiveCPUTimeUserTimers()) { || thread->team->HasActiveCPUTimeUserTimers()) {
user_timer_continue_cpu_timers(thread, thread->cpu->previous_thread); 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 // notify the user debugger code
if ((thread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) if ((thread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0)
user_debug_thread_scheduled(thread); user_debug_thread_scheduled(thread);
// start tracking time
thread->last_time = system_time();
// unlock the scheduler lock and enable interrupts // unlock the scheduler lock and enable interrupts
release_spinlock(&gSchedulerLock); release_spinlock(&gSchedulerLock);
enable_interrupts(); enable_interrupts();
@@ -1991,10 +1995,10 @@ thread_exit(void)
// remember how long this thread lasted // remember how long this thread lasted
bigtime_t now = system_time(); bigtime_t now = system_time();
InterruptsSpinLocker threadTimeLocker(thread->time_lock); InterruptsSpinLocker teamTimeLocker(team->time_lock);
SpinLocker threadTimeLocker(thread->time_lock);
thread->kernel_time += now - thread->last_time; thread->kernel_time += now - thread->last_time;
thread->last_time = now; thread->last_time = now;
threadTimeLocker.Unlock();
team->dead_threads_kernel_time += thread->kernel_time; team->dead_threads_kernel_time += thread->kernel_time;
team->dead_threads_user_time += thread->user_time; team->dead_threads_user_time += thread->user_time;
@@ -2009,6 +2013,9 @@ thread_exit(void)
if (thread->HasActiveCPUTimeUserTimers()) if (thread->HasActiveCPUTimeUserTimers())
thread->DeactivateCPUTimeUserTimers(); thread->DeactivateCPUTimeUserTimers();
threadTimeLocker.Unlock();
teamTimeLocker.Unlock();
// put the thread into the kernel team until it dies // put the thread into the kernel team until it dies
remove_thread_from_team(team, thread); remove_thread_from_team(team, thread);
insert_thread_into_team(kernelTeam, thread); insert_thread_into_team(kernelTeam, thread);
@@ -2334,11 +2341,10 @@ thread_reset_for_exec(void)
thread->user_stack_size = 0; thread->user_stack_size = 0;
// reset signals // reset signals
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
thread->ResetSignalsOnExec(); thread->ResetSignalsOnExec();
// reset thread CPU time clock // reset thread CPU time clock
InterruptsSpinLocker timeLocker(thread->time_lock);
thread->cpu_clock_offset = -thread->CPUTime(false); thread->cpu_clock_offset = -thread->CPUTime(false);
} }