From 03fb2d886830e4dd4b344c56725db59f96733216 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Fri, 8 Nov 2013 02:41:26 +0100 Subject: [PATCH] kernel: Remove gSchedulerLock * Thread::scheduler_lock protects thread state, priority, etc. * sThreadCreationLock protects thread creation and removal and list of threads in team. * Team::signal_lock and Team::time_lock protect list of threads in team as well. * Scheduler uses its own internal locking. --- headers/private/kernel/condition_variable.h | 27 +++--- headers/private/kernel/kscheduler.h | 19 ++-- headers/private/kernel/listeners.h | 2 +- headers/private/kernel/team.h | 2 +- headers/private/kernel/thread.h | 3 + headers/private/kernel/thread_types.h | 10 +-- .../invalidate_on_exit/invalidate_on_exit.cpp | 6 -- src/libs/compat/freebsd_network/Condvar.cpp | 2 +- src/system/kernel/arch/x86/arch_int.cpp | 2 +- src/system/kernel/condition_variable.cpp | 26 +++--- src/system/kernel/debug/system_profiler.cpp | 13 +-- src/system/kernel/debug/user_debugger.cpp | 8 +- src/system/kernel/device_manager/IOCache.cpp | 6 +- src/system/kernel/image.cpp | 13 ++- src/system/kernel/port.cpp | 8 +- src/system/kernel/scheduler/scheduler.cpp | 35 +++++--- .../kernel/scheduler/scheduler_common.h | 2 + src/system/kernel/sem.cpp | 20 ++--- src/system/kernel/signal.cpp | 24 ++--- src/system/kernel/team.cpp | 44 +++++----- src/system/kernel/thread.cpp | 88 ++++++++++--------- 21 files changed, 182 insertions(+), 178 deletions(-) diff --git a/headers/private/kernel/condition_variable.h b/headers/private/kernel/condition_variable.h index 9f4c0366b6..4e91baec22 100644 --- a/headers/private/kernel/condition_variable.h +++ b/headers/private/kernel/condition_variable.h @@ -56,19 +56,13 @@ public: void Publish(const void* object, const char* objectType); - void Unpublish(bool schedulerLocked = false); + void Unpublish(); - inline void NotifyOne(bool schedulerLocked = false, - status_t result = B_OK); - inline void NotifyAll(bool schedulerLocked = false, - status_t result = B_OK); + inline void NotifyOne(status_t result = B_OK); + inline void NotifyAll(status_t result = B_OK); - static void NotifyOne(const void* object, - bool schedulerLocked = false, - status_t result = B_OK); - static void NotifyAll(const void* object, - bool schedulerLocked = false, - status_t result = B_OK); + static void NotifyOne(const void* object, status_t result); + static void NotifyAll(const void* object, status_t result); // (both methods) caller must ensure that // the variable is not unpublished // concurrently @@ -86,8 +80,7 @@ public: void Dump() const; private: - void _Notify(bool all, bool schedulerLocked, - status_t result); + void _Notify(bool all, status_t result); void _NotifyLocked(bool all, status_t result); protected: @@ -124,16 +117,16 @@ ConditionVariableEntry::~ConditionVariableEntry() inline void -ConditionVariable::NotifyOne(bool schedulerLocked, status_t result) +ConditionVariable::NotifyOne(status_t result) { - _Notify(false, schedulerLocked, result); + _Notify(false, result); } inline void -ConditionVariable::NotifyAll(bool schedulerLocked, status_t result) +ConditionVariable::NotifyAll(status_t result) { - _Notify(true, schedulerLocked, result); + _Notify(true, result); } diff --git a/headers/private/kernel/kscheduler.h b/headers/private/kernel/kscheduler.h index c1eeb39c1d..bcb5fd6e0d 100644 --- a/headers/private/kernel/kscheduler.h +++ b/headers/private/kernel/kscheduler.h @@ -24,15 +24,13 @@ typedef enum scheduler_mode { SCHEDULER_MODE_COUNT } scheduler_mode; -extern spinlock gSchedulerLock; - #ifdef __cplusplus extern "C" { #endif /*! Enqueues the thread in the ready-to-run queue. - The caller must hold the scheduler lock (with disabled interrupts). + The caller must hold the enqueued thread \c scheduler_lock. */ void scheduler_enqueue_in_run_queue(Thread* thread); @@ -42,15 +40,14 @@ void scheduler_enqueue_in_run_queue(Thread* thread); If it's the same thread, the thread will just continue to run. In either case, unless the thread is dead or is sleeping/waiting indefinitely, the function will eventually return. - The caller must hold the scheduler lock (with disabled interrupts). + The caller must hold the current thread \c scheduler_lock. */ void scheduler_reschedule(void); /*! Sets the given thread's priority. The thread may be running or may be in the ready-to-run queue. - The caller must hold the scheduler lock (with disabled interrupts). */ -void scheduler_set_thread_priority(Thread* thread, int32 priority); +int32 scheduler_set_thread_priority(Thread* thread, int32 priority); /*! Called when the Thread structure is first created. Per-thread housekeeping resources can be allocated. @@ -61,7 +58,6 @@ status_t scheduler_on_thread_create(Thread* thread, bool idleThread); /*! Called when a Thread structure is initialized and made ready for use. The per-thread housekeeping data structures are reset, if needed. - The caller must hold the scheduler lock (with disabled interrupts). */ void scheduler_on_thread_init(Thread* thread); @@ -75,8 +71,6 @@ void scheduler_on_thread_destroy(Thread* thread); /*! Called in the early boot process to start thread scheduling on the current CPU. The function is called once for each CPU. - Interrupts must be disabled, but the caller must not hold the scheduler - lock. */ void scheduler_start(void); @@ -122,11 +116,14 @@ scheduler_reschedule_if_necessary() { if (are_interrupts_enabled()) { cpu_status state = disable_interrupts(); - acquire_spinlock(&gSchedulerLock); + + Thread* thread = get_cpu_struct()->running_thread; + acquire_spinlock(&thread->scheduler_lock); scheduler_reschedule_if_necessary_locked(); - release_spinlock(&gSchedulerLock); + release_spinlock(&thread->scheduler_lock); + restore_interrupts(state); } } diff --git a/headers/private/kernel/listeners.h b/headers/private/kernel/listeners.h index 64bb94d3d1..6406435325 100644 --- a/headers/private/kernel/listeners.h +++ b/headers/private/kernel/listeners.h @@ -34,7 +34,7 @@ struct SchedulerListener : DoublyLinkedListLinkImpl { typedef DoublyLinkedList SchedulerListenerList; extern SchedulerListenerList gSchedulerListeners; - // guarded by the thread spinlock +extern spinlock gSchedulerListenersLock; template diff --git a/headers/private/kernel/team.h b/headers/private/kernel/team.h index ce09ea470a..2fb555e493 100644 --- a/headers/private/kernel/team.h +++ b/headers/private/kernel/team.h @@ -46,7 +46,7 @@ thread_id load_image_etc(int32 argCount, const char* const* args, const char* const* env, int32 priority, team_id parentID, uint32 flags); void team_set_job_control_state(Team* team, job_control_state newState, - Signal* signal, bool threadsLocked); + Signal* signal); void team_set_controlling_tty(int32 index); int32 team_get_controlling_tty(); status_t team_set_foreground_process_group(int32 ttyIndex, pid_t processGroup); diff --git a/headers/private/kernel/thread.h b/headers/private/kernel/thread.h index 9cc12499c2..72d123b503 100644 --- a/headers/private/kernel/thread.h +++ b/headers/private/kernel/thread.h @@ -69,6 +69,9 @@ public: using BKernel::ThreadCreationAttributes; +extern spinlock gThreadCreationLock; + + #ifdef __cplusplus extern "C" { #endif diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index c0448213e3..6212deb48d 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -243,10 +243,10 @@ struct Team : TeamThreadIteratorEntry, KernelReferenceable, struct job_control_entry* job_control_entry; VMAddressSpace *address_space; - Thread *main_thread; // protected by fLock and the scheduler - // lock (and the thread's lock), immutable + Thread *main_thread; // protected by fLock, immutable // after first set - Thread *thread_list; // protected by fLock and the scheduler lock + Thread *thread_list; // protected by fLock, signal_lock and + // gThreadCreationLock struct team_loading_info *loading_info; // protected by fLock struct list image_list; // protected by sImageMutex struct list watcher_list; @@ -270,8 +270,7 @@ struct Team : TeamThreadIteratorEntry, KernelReferenceable, bigtime_t cpu_clock_offset; spinlock time_lock; - // user group information; protected by fLock, the *_uid/*_gid fields also - // by the scheduler lock + // user group information; protected by fLock uid_t saved_set_uid; uid_t real_uid; uid_t effective_uid; @@ -430,6 +429,7 @@ struct Thread : TeamThreadIteratorEntry, KernelReferenceable, struct cpu_ent *previous_cpu; // protected by scheduler lock int32 pinned_to_cpu; // only accessed by this thread or in the // scheduler, when thread is not running + spinlock scheduler_lock; sigset_t sig_block_mask; // protected by team->signal_lock, // only modified by the thread itself diff --git a/src/add-ons/kernel/debugger/invalidate_on_exit/invalidate_on_exit.cpp b/src/add-ons/kernel/debugger/invalidate_on_exit/invalidate_on_exit.cpp index 3ff72b3842..abcea1c286 100644 --- a/src/add-ons/kernel/debugger/invalidate_on_exit/invalidate_on_exit.cpp +++ b/src/add-ons/kernel/debugger/invalidate_on_exit/invalidate_on_exit.cpp @@ -39,12 +39,6 @@ invalidate_loop(void *data) static void exit_debugger() { - // If someone holds the scheduler lock at this point, release_sem_etc() - // will block forever. So avoid that. - if (!try_acquire_spinlock(&gSchedulerLock)) - return; - release_spinlock(&gSchedulerLock); - release_sem_etc(sRequestSem, 1, B_DO_NOT_RESCHEDULE); } diff --git a/src/libs/compat/freebsd_network/Condvar.cpp b/src/libs/compat/freebsd_network/Condvar.cpp index 74499ef0cb..9cb5be1dcd 100644 --- a/src/libs/compat/freebsd_network/Condvar.cpp +++ b/src/libs/compat/freebsd_network/Condvar.cpp @@ -77,5 +77,5 @@ publishedConditionTimedWait(const void* waitChannel, const int timeout) void publishedConditionNotifyAll(const void* waitChannel) { - ConditionVariable::NotifyAll(waitChannel); + ConditionVariable::NotifyAll(waitChannel, B_OK); } diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 1fabe85b1b..3591f909e8 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -231,7 +231,7 @@ x86_hardware_interrupt(struct iframe* frame) cpu_status state = disable_interrupts(); if (thread->cpu->invoke_scheduler) { - SpinLocker schedulerLocker(gSchedulerLock); + SpinLocker schedulerLocker(thread->scheduler_lock); scheduler_reschedule(); schedulerLocker.Unlock(); restore_interrupts(state); diff --git a/src/system/kernel/condition_variable.cpp b/src/system/kernel/condition_variable.cpp index 7f6152ebce..85c7a3f87b 100644 --- a/src/system/kernel/condition_variable.cpp +++ b/src/system/kernel/condition_variable.cpp @@ -217,13 +217,11 @@ ConditionVariable::Publish(const void* object, const char* objectType) void -ConditionVariable::Unpublish(bool schedulerLocked) +ConditionVariable::Unpublish() { ASSERT(fObject != NULL); - InterruptsLocker _; - SpinLocker schedulerLocker(schedulerLocked ? NULL : &gSchedulerLock); - SpinLocker locker(sConditionVariablesLock); + InterruptsSpinLocker locker(sConditionVariablesLock); #if KDEBUG ConditionVariable* variable = sConditionVariableHash.Lookup(fObject); @@ -259,8 +257,7 @@ ConditionVariable::Wait(uint32 flags, bigtime_t timeout) /*static*/ void -ConditionVariable::NotifyOne(const void* object, bool schedulerLocked, - status_t result) +ConditionVariable::NotifyOne(const void* object, status_t result) { InterruptsSpinLocker locker(sConditionVariablesLock); ConditionVariable* variable = sConditionVariableHash.Lookup(object); @@ -268,13 +265,12 @@ ConditionVariable::NotifyOne(const void* object, bool schedulerLocked, if (variable == NULL) return; - variable->NotifyOne(schedulerLocked, result); + variable->NotifyOne(result); } /*static*/ void -ConditionVariable::NotifyAll(const void* object, bool schedulerLocked, - status_t result) +ConditionVariable::NotifyAll(const void* object, status_t result) { InterruptsSpinLocker locker(sConditionVariablesLock); ConditionVariable* variable = sConditionVariableHash.Lookup(object); @@ -282,7 +278,7 @@ ConditionVariable::NotifyAll(const void* object, bool schedulerLocked, if (variable == NULL) return; - variable->NotifyAll(schedulerLocked, result); + variable->NotifyAll(result); } @@ -318,11 +314,9 @@ ConditionVariable::Dump() const void -ConditionVariable::_Notify(bool all, bool schedulerLocked, status_t result) +ConditionVariable::_Notify(bool all, status_t result) { - InterruptsLocker _; - SpinLocker schedulerLocker(schedulerLocked ? NULL : &gSchedulerLock); - SpinLocker locker(sConditionVariablesLock); + InterruptsSpinLocker locker(sConditionVariablesLock); if (!fEntries.IsEmpty()) { if (result > B_OK) { @@ -348,8 +342,10 @@ ConditionVariable::_NotifyLocked(bool all, status_t result) if (entry->fWaitStatus <= 0) continue; - if (entry->fWaitStatus == STATUS_WAITING) + if (entry->fWaitStatus == STATUS_WAITING) { + SpinLocker _(entry->fThread->scheduler_lock); thread_unblock_locked(entry->fThread, result); + } entry->fWaitStatus = result; diff --git a/src/system/kernel/debug/system_profiler.cpp b/src/system/kernel/debug/system_profiler.cpp index d0d3e22016..5b341b2254 100644 --- a/src/system/kernel/debug/system_profiler.cpp +++ b/src/system/kernel/debug/system_profiler.cpp @@ -220,6 +220,7 @@ SystemProfiler::_MaybeNotifyProfilerThreadLocked() int cpu = smp_get_current_cpu(); fReentered[cpu] = true; + InterruptsSpinLocker _(fWaitingProfilerThread->scheduler_lock); thread_unblock_locked(fWaitingProfilerThread, B_OK); fWaitingProfilerThread = NULL; @@ -234,7 +235,6 @@ SystemProfiler::_MaybeNotifyProfilerThread() if (fWaitingProfilerThread == NULL) return; - InterruptsSpinLocker schedulerLocker(gSchedulerLock); SpinLocker locker(fLock); _MaybeNotifyProfilerThreadLocked(); @@ -305,10 +305,8 @@ SystemProfiler::~SystemProfiler() locker.Unlock(); // stop scheduler listening - if (fSchedulerNotificationsRequested) { - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + if (fSchedulerNotificationsRequested) scheduler_remove_listener(this); - } // stop wait object listening if (fWaitObjectNotificationsRequested) { @@ -498,8 +496,6 @@ SystemProfiler::Init() fThreadNotificationsEnabled = true; } - InterruptsSpinLocker schedulerLocker(gSchedulerLock); - fProfilingActive = true; // start scheduler and wait object listening @@ -521,8 +517,6 @@ SystemProfiler::Init() } } - schedulerLocker.Unlock(); - // I/O scheduling if ((fFlags & B_SYSTEM_PROFILER_IO_SCHEDULING_EVENTS) != 0) { IOSchedulerRoster* roster = IOSchedulerRoster::Default(); @@ -571,12 +565,9 @@ SystemProfiler::NextBuffer(size_t bytesRead, uint64* _droppedEvents) Thread* thread = thread_get_current_thread(); fWaitingProfilerThread = thread; - InterruptsSpinLocker schedulerLocker(gSchedulerLock); - thread_prepare_to_block(thread, B_CAN_INTERRUPT, THREAD_BLOCK_TYPE_OTHER, "system profiler buffer"); - schedulerLocker.Unlock(); locker.Unlock(); status_t error = thread_block_with_timeout(B_RELATIVE_TIMEOUT, 1000000); diff --git a/src/system/kernel/debug/user_debugger.cpp b/src/system/kernel/debug/user_debugger.cpp index a3f1915878..6999556c04 100644 --- a/src/system/kernel/debug/user_debugger.cpp +++ b/src/system/kernel/debug/user_debugger.cpp @@ -440,7 +440,7 @@ finish_debugger_change(Team* team) ConditionVariable* condition = team->debug_info.debugger_changed_condition; team->debug_info.debugger_changed_condition = NULL; - condition->NotifyAll(false); + condition->NotifyAll(); } @@ -2901,7 +2901,7 @@ _user_debug_thread(thread_id threadID) // resume/interrupt the thread, if necessary threadDebugInfoLocker.Unlock(); - SpinLocker schedulerLocker(gSchedulerLock); + SpinLocker schedulerLocker(thread->scheduler_lock); switch (thread->state) { case B_THREAD_SUSPENDED: @@ -2916,6 +2916,10 @@ _user_debug_thread(thread_id threadID) // about to acquire a semaphore (before // thread_prepare_to_block()), we won't interrupt it. // Maybe we should rather send a signal (SIGTRAP). + schedulerLocker.Unlock(); + + schedulerLocker.SetTo(thread_get_current_thread()->scheduler_lock, + false); scheduler_reschedule_if_necessary_locked(); break; } diff --git a/src/system/kernel/device_manager/IOCache.cpp b/src/system/kernel/device_manager/IOCache.cpp index a65e515d28..7cd834b8a5 100644 --- a/src/system/kernel/device_manager/IOCache.cpp +++ b/src/system/kernel/device_manager/IOCache.cpp @@ -205,10 +205,10 @@ IOCache::OperationCompleted(IOOperation* operation, status_t status, { if (status == B_OK) { // always fail in case of partial transfers - ((Operation*)operation)->finishedCondition.NotifyAll(false, + ((Operation*)operation)->finishedCondition.NotifyAll( transferredBytes == operation->Length() ? B_OK : B_ERROR); } else - ((Operation*)operation)->finishedCondition.NotifyAll(false, status); + ((Operation*)operation)->finishedCondition.NotifyAll(status); } @@ -498,7 +498,7 @@ IOCache::_DoOperation(Operation& operation) status_t error = fIOCallback(fIOCallbackData, &operation); if (error != B_OK) { - operation.finishedCondition.NotifyAll(false, error); + operation.finishedCondition.NotifyAll(error); // removes the entry from the variable return error; } diff --git a/src/system/kernel/image.cpp b/src/system/kernel/image.cpp index e76cc60118..55ac115dff 100644 --- a/src/system/kernel/image.cpp +++ b/src/system/kernel/image.cpp @@ -370,15 +370,20 @@ notify_loading_app(status_t result, bool suspend) // we're done with the team stuff, get the scheduler lock instead teamLocker.Unlock(); - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + Thread* thread = loadingInfo->thread; + InterruptsSpinLocker schedulerLocker(thread->scheduler_lock); // wake up the waiting thread - if (loadingInfo->thread->state == B_THREAD_SUSPENDED) - scheduler_enqueue_in_run_queue(loadingInfo->thread); + if (thread->state == B_THREAD_SUSPENDED) + scheduler_enqueue_in_run_queue(thread); + schedulerLocker.Unlock(); // suspend ourselves, if desired if (suspend) { - thread_get_current_thread()->next_state = B_THREAD_SUSPENDED; + Thread* thread = thread_get_current_thread(); + InterruptsSpinLocker schedulerLocker(thread->scheduler_lock); + + thread->next_state = B_THREAD_SUSPENDED; scheduler_reschedule(); } } diff --git a/src/system/kernel/port.cpp b/src/system/kernel/port.cpp index e4ba96c7ae..d5b6700db0 100644 --- a/src/system/kernel/port.cpp +++ b/src/system/kernel/port.cpp @@ -684,8 +684,8 @@ uninit_port_locked(Port* port) // Release the threads that were blocking on this port. // read_port() will see the B_BAD_PORT_ID return value, and act accordingly - port->read_condition.NotifyAll(false, B_BAD_PORT_ID); - port->write_condition.NotifyAll(false, B_BAD_PORT_ID); + port->read_condition.NotifyAll(B_BAD_PORT_ID); + port->write_condition.NotifyAll(B_BAD_PORT_ID); sNotificationService.Notify(PORT_REMOVED, port->id); } @@ -891,8 +891,8 @@ close_port(port_id id) notify_port_select_events(port, B_EVENT_INVALID); port->select_infos = NULL; - port->read_condition.NotifyAll(false, B_BAD_PORT_ID); - port->write_condition.NotifyAll(false, B_BAD_PORT_ID); + port->read_condition.NotifyAll(B_BAD_PORT_ID); + port->write_condition.NotifyAll(B_BAD_PORT_ID); return B_OK; } diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index e113e25dde..6f7a2bf050 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -45,10 +45,11 @@ #endif -spinlock gSchedulerLock = B_SPINLOCK_INITIALIZER; SchedulerListenerList gSchedulerListeners; +spinlock gSchedulerListenersLock = B_SPINLOCK_INITIALIZER; -bool sSchedulerEnabled; +static spinlock sSchedulerInternalLock; +static bool sSchedulerEnabled; const bigtime_t kThreadQuantum = 1000; const bigtime_t kMinThreadQuantum = 3000; @@ -1129,6 +1130,8 @@ enqueue(Thread* thread, bool newOne) void scheduler_enqueue_in_run_queue(Thread *thread) { + InterruptsSpinLocker _(sSchedulerInternalLock); + TRACE("enqueueing new thread %ld with static priority %ld\n", thread->id, thread->priority); enqueue(thread, true); @@ -1156,17 +1159,19 @@ put_back(Thread* thread) /*! Sets the priority of a thread. - Note: thread lock must be held when entering this function */ -void +int32 scheduler_set_thread_priority(Thread *thread, int32 priority) { + InterruptsSpinLocker _(sSchedulerInternalLock); + if (priority == thread->priority) - return; + return thread->priority; + + int32 oldPriority = thread->priority; TRACE("changing thread %ld priority to %ld (old: %ld, effective: %ld)\n", - thread->id, priority, thread->priority, - get_effective_priority(thread)); + thread->id, priority, oldPriority, get_effective_priority(thread)); if (thread->state != B_THREAD_READY) { cancel_penalty(thread); @@ -1174,7 +1179,7 @@ scheduler_set_thread_priority(Thread *thread, int32 priority) if (thread->state == B_THREAD_RUNNING) update_priority_heaps(thread->cpu->cpu_num, priority); - return; + return oldPriority; } // The thread is in the run queue. We need to remove it and re-insert it at @@ -1194,8 +1199,9 @@ scheduler_set_thread_priority(Thread *thread, int32 priority) // set priority and re-insert cancel_penalty(thread); thread->priority = priority; + enqueue(thread, true); - scheduler_enqueue_in_run_queue(thread); + return oldPriority; } @@ -1403,6 +1409,8 @@ update_cpu_performance(Thread* thread, int32 thisCore) static void _scheduler_reschedule(void) { + InterruptsSpinLocker internalLocker(sSchedulerInternalLock); + Thread* oldThread = thread_get_current_thread(); int32 thisCPU = smp_get_current_cpu(); @@ -1473,6 +1481,8 @@ _scheduler_reschedule(void) nextThread = dequeue_thread(thisCPU); if (!nextThread) panic("reschedule(): run queues are empty!\n"); + if (nextThread != oldThread) + acquire_spinlock(&nextThread->scheduler_lock); TRACE("reschedule(): cpu %ld, next thread = %ld\n", thisCPU, nextThread->id); @@ -1513,6 +1523,7 @@ _scheduler_reschedule(void) } else nextThread->scheduler_data->quantum_start = system_time(); + internalLocker.Unlock(); if (nextThread != oldThread) scheduler_switch_thread(oldThread, nextThread); } @@ -1566,7 +1577,7 @@ scheduler_on_thread_destroy(Thread* thread) void scheduler_start(void) { - SpinLocker schedulerLocker(gSchedulerLock); + InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock); _scheduler_reschedule(); } @@ -1583,7 +1594,7 @@ scheduler_set_operation_mode(scheduler_mode mode) const char* modeNames[] = { "performance", "power saving" }; dprintf("scheduler: switching to %s mode\n", modeNames[mode]); - InterruptsSpinLocker _(gSchedulerLock); + InterruptsSpinLocker _(sSchedulerInternalLock); sSchedulerMode = mode; switch (mode) { @@ -1877,6 +1888,7 @@ SchedulerListener::~SchedulerListener() void scheduler_add_listener(struct SchedulerListener* listener) { + InterruptsSpinLocker _(gSchedulerListenersLock); gSchedulerListeners.Add(listener); } @@ -1886,6 +1898,7 @@ scheduler_add_listener(struct SchedulerListener* listener) void scheduler_remove_listener(struct SchedulerListener* listener) { + InterruptsSpinLocker _(gSchedulerListenersLock); gSchedulerListeners.Remove(listener); } diff --git a/src/system/kernel/scheduler/scheduler_common.h b/src/system/kernel/scheduler/scheduler_common.h index 266f7d878a..a105eb8a52 100644 --- a/src/system/kernel/scheduler/scheduler_common.h +++ b/src/system/kernel/scheduler/scheduler_common.h @@ -45,6 +45,8 @@ scheduler_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(). diff --git a/src/system/kernel/sem.cpp b/src/system/kernel/sem.cpp index 7980ed29e2..b947f2080e 100644 --- a/src/system/kernel/sem.cpp +++ b/src/system/kernel/sem.cpp @@ -393,7 +393,7 @@ delete_sem_internal(sem_id id, bool checkPermission) char* name; uninit_sem_locked(sSems[slot], &name); - SpinLocker schedulerLocker(gSchedulerLock); + SpinLocker schedulerLocker(thread_get_current_thread()->scheduler_lock); scheduler_reschedule_if_necessary_locked(); schedulerLocker.Unlock(); @@ -644,9 +644,8 @@ remove_thread_from_sem(queued_thread *entry, struct sem_entry *sem) // for that time, so the blocking state of threads won't change (due to // interruption or timeout). We need that lock anyway when unblocking a // thread. - SpinLocker schedulerLocker(gSchedulerLock); - while ((entry = sem->queue.Head()) != NULL) { + SpinLocker schedulerLocker(entry->thread->scheduler_lock); if (thread_is_blocked(entry->thread)) { // The thread is still waiting. If its count is satisfied, unblock // it. Otherwise we can't unblock any other thread. @@ -665,8 +664,6 @@ remove_thread_from_sem(queued_thread *entry, struct sem_entry *sem) entry->queued = false; } - schedulerLocker.Unlock(); - // select notification, if the semaphore is now acquirable if (sem->u.used.count > 0) notify_sem_select_events(sem, B_EVENT_ACQUIRE_SEMAPHORE); @@ -823,7 +820,7 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, // do a quick check to see if the thread has any pending signals // this should catch most of the cases where the thread had a signal - SpinLocker schedulerLocker(gSchedulerLock); + SpinLocker schedulerLocker(thread->scheduler_lock); if (thread_is_interrupted(thread, flags)) { schedulerLocker.Unlock(); sSems[slot].u.used.count += count; @@ -832,6 +829,8 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, goto err; } + schedulerLocker.Unlock(); + if ((flags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) == 0) timeout = B_INFINITE_TIMEOUT; @@ -843,7 +842,6 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_SEMAPHORE, (void*)(addr_t)id); - schedulerLocker.Unlock(); RELEASE_SEM_LOCK(sSems[slot]); // release the other semaphore, if any @@ -968,8 +966,6 @@ release_sem_etc(sem_id id, int32 count, uint32 flags) // Grab the scheduler lock, so thread_is_blocked() is reliable (due to // possible interruptions or timeouts, it wouldn't be otherwise). - SpinLocker schedulerLocker(gSchedulerLock); - while (count > 0) { queued_thread* entry = sSems[slot].queue.Head(); if (entry == NULL) { @@ -980,6 +976,7 @@ release_sem_etc(sem_id id, int32 count, uint32 flags) break; } + SpinLocker schedulerLock(entry->thread->scheduler_lock); if (thread_is_blocked(entry->thread)) { // The thread is still waiting. If its count is satisfied, // unblock it. Otherwise we can't unblock any other thread. @@ -1005,8 +1002,6 @@ release_sem_etc(sem_id id, int32 count, uint32 flags) entry->queued = false; } - schedulerLocker.Unlock(); - if (sSems[slot].u.used.count > 0) notify_sem_select_events(&sSems[slot], B_EVENT_ACQUIRE_SEMAPHORE); @@ -1014,7 +1009,8 @@ release_sem_etc(sem_id id, int32 count, uint32 flags) // been told not to. if ((flags & B_DO_NOT_RESCHEDULE) == 0) { semLocker.Unlock(); - schedulerLocker.Lock(); + + SpinLocker _(thread_get_current_thread()->scheduler_lock); scheduler_reschedule_if_necessary_locked(); } diff --git a/src/system/kernel/signal.cpp b/src/system/kernel/signal.cpp index 7907dfa9b4..5377903308 100644 --- a/src/system/kernel/signal.cpp +++ b/src/system/kernel/signal.cpp @@ -1064,7 +1064,7 @@ handle_signals(Thread* thread) team->LockTeamAndParent(false); team_set_job_control_state(team, - JOB_CONTROL_STATE_CONTINUED, signal, false); + JOB_CONTROL_STATE_CONTINUED, signal); team->UnlockTeamAndParent(); @@ -1099,7 +1099,7 @@ handle_signals(Thread* thread) team->LockTeamAndParent(false); team_set_job_control_state(team, - JOB_CONTROL_STATE_STOPPED, signal, false); + JOB_CONTROL_STATE_STOPPED, signal); // send a SIGCHLD to the parent (if it does have // SA_NOCLDSTOP defined) @@ -1128,7 +1128,7 @@ handle_signals(Thread* thread) locker.Unlock(); if (!resume) { - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + InterruptsSpinLocker _(thread->scheduler_lock); thread->next_state = B_THREAD_SUSPENDED; scheduler_reschedule(); } @@ -1377,7 +1377,7 @@ send_signal_to_thread_locked(Thread* thread, uint32 signalNumber, if (thread->team == team_get_kernel_team()) { // Signals to kernel threads will only wake them up - SpinLocker _(gSchedulerLock); + SpinLocker _(thread->scheduler_lock); if (thread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(thread); return B_OK; @@ -1401,7 +1401,7 @@ send_signal_to_thread_locked(Thread* thread, uint32 signalNumber, mainThread->AddPendingSignal(SIGKILLTHR); // wake up main thread - SpinLocker locker(gSchedulerLock); + SpinLocker locker(mainThread->scheduler_lock); if (mainThread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(mainThread); else @@ -1416,7 +1416,7 @@ send_signal_to_thread_locked(Thread* thread, uint32 signalNumber, case SIGKILLTHR: { // Wake up suspended threads and interrupt waiting ones - SpinLocker locker(gSchedulerLock); + SpinLocker locker(thread->scheduler_lock); if (thread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(thread); else @@ -1427,7 +1427,7 @@ send_signal_to_thread_locked(Thread* thread, uint32 signalNumber, case SIGNAL_CONTINUE_THREAD: { // wake up thread, and interrupt its current syscall - SpinLocker locker(gSchedulerLock); + SpinLocker locker(thread->scheduler_lock); if (thread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(thread); @@ -1438,7 +1438,7 @@ send_signal_to_thread_locked(Thread* thread, uint32 signalNumber, { // Wake up thread if it was suspended, otherwise interrupt it, if // the signal isn't blocked. - SpinLocker locker(gSchedulerLock); + SpinLocker locker(thread->scheduler_lock); if (thread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(thread); else if ((SIGNAL_TO_MASK(SIGCONT) & ~thread->sig_block_mask) != 0) @@ -1455,7 +1455,7 @@ send_signal_to_thread_locked(Thread* thread, uint32 signalNumber, & (~thread->sig_block_mask | SIGNAL_TO_MASK(SIGCHLD))) != 0) { // Interrupt thread if it was waiting - SpinLocker locker(gSchedulerLock); + SpinLocker locker(thread->scheduler_lock); thread_interrupt(thread, false); } break; @@ -1605,7 +1605,7 @@ send_signal_to_team_locked(Team* team, uint32 signalNumber, Signal* signal, mainThread->AddPendingSignal(SIGKILLTHR); // wake up main thread - SpinLocker _(gSchedulerLock); + SpinLocker _(mainThread->scheduler_lock); if (mainThread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(mainThread); else @@ -1619,7 +1619,7 @@ send_signal_to_team_locked(Team* team, uint32 signalNumber, Signal* signal, // don't block the signal. for (Thread* thread = team->thread_list; thread != NULL; thread = thread->team_next) { - SpinLocker _(gSchedulerLock); + SpinLocker _(thread->scheduler_lock); if (thread->state == B_THREAD_SUSPENDED) { scheduler_enqueue_in_run_queue(thread); } else if ((SIGNAL_TO_MASK(SIGCONT) & ~thread->sig_block_mask) @@ -1662,7 +1662,7 @@ send_signal_to_team_locked(Team* team, uint32 signalNumber, Signal* signal, sigset_t nonBlocked = ~thread->sig_block_mask | SIGNAL_TO_MASK(SIGCHLD); if ((thread->AllPendingSignals() & nonBlocked) != 0) { - SpinLocker _(gSchedulerLock); + SpinLocker _(thread->scheduler_lock); thread_interrupt(thread, false); } } diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index 6b651e58cf..175645a15c 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -1794,11 +1794,13 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount, // wait for the loader of the new team to finish its work if ((flags & B_WAIT_TILL_LOADED) != 0) { - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + if (mainThread != NULL) { + InterruptsSpinLocker schedulerLocker(mainThread->scheduler_lock); - // resume the team's main thread - if (mainThread != NULL && mainThread->state == B_THREAD_SUSPENDED) - scheduler_enqueue_in_run_queue(mainThread); + // resume the team's main thread + if (mainThread->state == B_THREAD_SUSPENDED) + scheduler_enqueue_in_run_queue(mainThread); + } // Now suspend ourselves until loading is finished. We will be woken // either by the thread, when it finished or aborted loading, or when @@ -1806,12 +1808,13 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount, // setting `loadingInfo.done' is responsible for removing the info from // the team structure. while (!loadingInfo.done) { - thread_get_current_thread()->next_state = B_THREAD_SUSPENDED; + Thread* thread = thread_get_current_thread(); + + InterruptsSpinLocker schedulerLocker(thread->scheduler_lock); + thread->next_state = B_THREAD_SUSPENDED; scheduler_reschedule(); } - schedulerLocker.Unlock(); - if (loadingInfo.result < B_OK) return loadingInfo.result; } @@ -2444,7 +2447,7 @@ wait_for_child(pid_t child, uint32 flags, siginfo_t& _info) } else { // The child is well. Reset its job control state. team_set_job_control_state(entry->team, - JOB_CONTROL_STATE_NONE, NULL, false); + JOB_CONTROL_STATE_NONE, NULL); } } } @@ -2531,14 +2534,16 @@ wait_for_child(pid_t child, uint32 flags, siginfo_t& _info) // If SIGCHLD is blocked, we shall clear pending SIGCHLDs, if no other child // status is available. TeamLocker teamLocker(team); - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + InterruptsSpinLocker signalLocker(team->signal_lock); + SpinLocker threadCreationLocker(gThreadCreationLock); if (is_team_signal_blocked(team, SIGCHLD)) { if (get_job_control_entry(team, child, flags) == NULL) team->RemovePendingSignals(SIGNAL_TO_MASK(SIGCHLD)); } - schedulerLocker.Unlock(); + threadCreationLocker.Unlock(); + signalLocker.Unlock(); teamLocker.Unlock(); // When the team is dead, the main thread continues to live in the kernel @@ -2925,12 +2930,12 @@ team_set_foreground_process_group(int32 ttyIndex, pid_t processGroupID) if (session->foreground_group != -1 && session->foreground_group != team->group_id && team->SignalActionFor(SIGTTOU).sa_handler != SIG_IGN) { - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + InterruptsSpinLocker signalLocker(team->signal_lock); if (!is_team_signal_blocked(team, SIGTTOU)) { pid_t groupID = team->group_id; - schedulerLocker.Unlock(); + signalLocker.Unlock(); sessionLocker.Unlock(); teamLocker.Unlock(); @@ -3170,7 +3175,7 @@ team_delete_team(Team* team, port_id debuggerPort) loadingInfo->result = B_ERROR; loadingInfo->done = true; - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + InterruptsSpinLocker _(loadingInfo->thread->scheduler_lock); // wake up the waiting thread if (loadingInfo->thread->state == B_THREAD_SUSPENDED) @@ -3256,8 +3261,7 @@ team_get_address_space(team_id id, VMAddressSpace** _addressSpace) /*! Sets the team's job control state. The caller must hold the parent team's lock. Interrupts are allowed to be - enabled or disabled. In the latter case the scheduler lock may be held as - well. + enabled or disabled. \a team The team whose job control state shall be set. \a newState The new state to be set. \a signal The signal the new state was caused by. Can \c NULL, if none. Then @@ -3266,11 +3270,10 @@ team_get_address_space(team_id id, VMAddressSpace** _addressSpace) \c JOB_CONTROL_STATE_NONE: - \c signal: The number of the signal causing the state change. - \c signaling_user: The real UID of the user sending the signal. - \a schedulerLocked indicates whether the scheduler lock is being held, too. */ void team_set_job_control_state(Team* team, job_control_state newState, - Signal* signal, bool schedulerLocked) + Signal* signal) { if (team == NULL || team->job_control_entry == NULL) return; @@ -3326,8 +3329,7 @@ team_set_job_control_state(Team* team, job_control_state newState, if (childList != NULL) { childList->entries.Add(entry); - team->parent->dead_children.condition_variable.NotifyAll( - schedulerLocked); + team->parent->dead_children.condition_variable.NotifyAll(); } } @@ -4087,7 +4089,7 @@ _user_setpgid(pid_t processID, pid_t groupID) // Changing the process group might have changed the situation for a // parent waiting in wait_for_child(). Hence we notify it. - team->parent->dead_children.condition_variable.NotifyAll(false); + team->parent->dead_children.condition_variable.NotifyAll(); return group->id; } @@ -4129,7 +4131,7 @@ _user_setsid(void) // Changing the process group might have changed the situation for a // parent waiting in wait_for_child(). Hence we notify it. - team->parent->dead_children.condition_variable.NotifyAll(false); + team->parent->dead_children.condition_variable.NotifyAll(); return group->id; } diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index 185da50376..7b1cdcbcde 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -81,6 +81,8 @@ static thread_id sNextThreadID = 2; static int32 sMaxThreads = 4096; static int32 sUsedThreads = 0; +spinlock gThreadCreationLock = B_SPINLOCK_INITIALIZER; + struct UndertakerEntry : DoublyLinkedListLinkImpl { Thread* thread; @@ -206,6 +208,7 @@ Thread::Thread(const char* name, thread_id threadID, struct cpu_ent* cpu) mutex_init_etc(&fLock, lockName, MUTEX_FLAG_CLONE_NAME); B_INITIALIZE_SPINLOCK(&time_lock); + B_INITIALIZE_SPINLOCK(&scheduler_lock); B_INITIALIZE_RW_SPINLOCK(&team_lock); // init name @@ -713,7 +716,8 @@ common_thread_entry(void* _args) user_debug_thread_scheduled(thread); // unlock the scheduler lock and enable interrupts - release_spinlock(&gSchedulerLock); + release_spinlock(&thread->cpu->previous_thread->scheduler_lock); + release_spinlock(&thread->scheduler_lock); enable_interrupts(); // call the kernel function, if any @@ -1020,7 +1024,8 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel) // for our own use (and threadReference remains armed). ThreadLocker threadLocker(thread); - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + + InterruptsSpinLocker threadCreationLocker(gThreadCreationLock); SpinLocker threadHashLocker(sThreadHashLock); // check the thread limit @@ -1028,7 +1033,7 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel) // Clean up the user_thread structure. It's a bit unfortunate that the // Thread destructor cannot do that, so we have to do that explicitly. threadHashLocker.Unlock(); - schedulerLocker.Unlock(); + threadCreationLocker.Unlock(); user_thread* userThread = thread->user_thread; thread->user_thread = NULL; @@ -1044,6 +1049,7 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel) // make thread visible in global hash/list thread->visible = true; sUsedThreads++; + scheduler_on_thread_init(thread); thread->AcquireReference(); @@ -1060,11 +1066,16 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel) } } - // insert thread into team - insert_thread_into_team(team, thread); + { + SpinLocker signalLocker(team->signal_lock); + SpinLocker timeLocker(team->time_lock); + + // insert thread into team + insert_thread_into_team(team, thread); + } threadHashLocker.Unlock(); - schedulerLocker.Unlock(); + threadCreationLocker.Unlock(); threadLocker.Unlock(); teamLocker.Unlock(); @@ -1106,13 +1117,17 @@ undertaker(void* /*args*/) Team* kernelTeam = team_get_kernel_team(); TeamLocker kernelTeamLocker(kernelTeam); thread->Lock(); - InterruptsSpinLocker signalLocker(kernelTeam->signal_lock); - SpinLocker schedulerLocker(gSchedulerLock); + + InterruptsSpinLocker threadCreationLocker(gThreadCreationLock); + SpinLocker signalLocker(kernelTeam->signal_lock); + SpinLocker timeLocker(kernelTeam->time_lock); remove_thread_from_team(kernelTeam, thread); - schedulerLocker.Unlock(); + timeLocker.Unlock(); signalLocker.Unlock(); + threadCreationLocker.Unlock(); + kernelTeamLocker.Unlock(); // free the thread structure @@ -1921,10 +1936,7 @@ thread_exit(void) panic("thread_exit() called with interrupts disabled!\n"); // boost our priority to get this over with - { - InterruptsSpinLocker _(gSchedulerLock); - scheduler_set_thread_priority(thread, B_URGENT_DISPLAY_PRIORITY); - } + scheduler_set_thread_priority(thread, B_URGENT_DISPLAY_PRIORITY); if (team != kernelTeam) { // Delete all user timers associated with the thread. @@ -1989,14 +2001,17 @@ thread_exit(void) vm_swap_address_space(team->address_space, VMAddressSpace::Kernel()); WriteSpinLocker teamLocker(thread->team_lock); - SpinLocker schedulerLocker(gSchedulerLock); + SpinLocker threadCreationLocker(gThreadCreationLock); // removing the thread and putting its death entry to the parent // team needs to be an atomic operation // remember how long this thread lasted bigtime_t now = system_time(); - InterruptsSpinLocker teamTimeLocker(team->time_lock); + + InterruptsSpinLocker signalLocker(kernelTeam->signal_lock); + SpinLocker teamTimeLocker(kernelTeam->time_lock); SpinLocker threadTimeLocker(thread->time_lock); + thread->kernel_time += now - thread->last_time; thread->last_time = now; @@ -2014,17 +2029,19 @@ thread_exit(void) thread->DeactivateCPUTimeUserTimers(); threadTimeLocker.Unlock(); - teamTimeLocker.Unlock(); // put the thread into the kernel team until it dies remove_thread_from_team(team, thread); insert_thread_into_team(kernelTeam, thread); + teamTimeLocker.Unlock(); + signalLocker.Unlock(); + teamLocker.Unlock(); if (team->death_entry != NULL) { if (--team->death_entry->remaining_threads == 0) - team->death_entry->condition.NotifyOne(true, B_OK); + team->death_entry->condition.NotifyOne(); } if (deleteTeam) { @@ -2032,8 +2049,7 @@ thread_exit(void) // Set the team job control state to "dead" and detach the job // control entry from our team struct. - team_set_job_control_state(team, JOB_CONTROL_STATE_DEAD, NULL, - true); + team_set_job_control_state(team, JOB_CONTROL_STATE_DEAD, NULL); death = team->job_control_entry; team->job_control_entry = NULL; @@ -2050,7 +2066,7 @@ thread_exit(void) death = NULL; } - schedulerLocker.Unlock(); + threadCreationLocker.Unlock(); restore_interrupts(state); threadLocker.Unlock(); @@ -2113,7 +2129,7 @@ thread_exit(void) } } - schedulerLocker.Unlock(); + threadCreationLocker.Unlock(); restore_interrupts(state); threadLocker.Unlock(); @@ -2138,7 +2154,7 @@ thread_exit(void) ThreadLocker threadLocker(thread); state = disable_interrupts(); - SpinLocker schedulerLocker(gSchedulerLock); + SpinLocker threadCreationLocker(gThreadCreationLock); // mark invisible in global hash/list, so it's no longer accessible SpinLocker threadHashLocker(sThreadHashLock); @@ -2156,7 +2172,7 @@ thread_exit(void) select_info* selectInfos = thread->select_infos; thread->select_infos = NULL; - schedulerLocker.Unlock(); + threadCreationLocker.Unlock(); restore_interrupts(state); threadLocker.Unlock(); @@ -2243,7 +2259,7 @@ thread_exit(void) sUndertakerCondition.NotifyOne(); undertakerLocker.Unlock(); - schedulerLocker.Lock(); + SpinLocker schedulerLocker(thread->scheduler_lock); thread->next_state = THREAD_STATE_FREE_ON_RESCHED; scheduler_reschedule(); @@ -2392,7 +2408,7 @@ thread_yield(void) if (thread == NULL) return; - InterruptsSpinLocker _(gSchedulerLock); + InterruptsSpinLocker _(thread->scheduler_lock); thread->has_yielded = true; scheduler_reschedule(); @@ -2604,7 +2620,6 @@ thread_get_io_priority(thread_id id) int32 priority = thread->io_priority; if (priority < 0) { // negative I/O priority means using the (CPU) priority - InterruptsSpinLocker schedulerLocker(gSchedulerLock); priority = thread->priority; } @@ -2798,7 +2813,7 @@ thread_block_timeout(timer* timer) status_t thread_block() { - InterruptsSpinLocker _(gSchedulerLock); + InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock); return thread_block_locked(thread_get_current_thread()); } @@ -2835,7 +2850,7 @@ thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout) { Thread* thread = thread_get_current_thread(); - InterruptsSpinLocker locker(gSchedulerLock); + InterruptsSpinLocker locker(thread->scheduler_lock); if (thread->wait.status != 1) return thread->wait.status; @@ -2881,7 +2896,7 @@ thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout) void thread_unblock(Thread* thread, status_t status) { - InterruptsSpinLocker _(gSchedulerLock); + InterruptsSpinLocker locker(thread->scheduler_lock); thread_unblock_locked(thread, status); } @@ -2902,7 +2917,7 @@ user_unblock_thread(thread_id threadID, status_t status) if (thread->user_thread == NULL) return B_NOT_ALLOWED; - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + InterruptsSpinLocker locker(thread->scheduler_lock); if (thread->user_thread->wait_status > 0) { thread->user_thread->wait_status = status; @@ -3005,7 +3020,7 @@ _get_thread_info(thread_id id, thread_info *info, size_t size) ThreadLocker threadLocker(thread, true); // fill the info -- also requires the scheduler lock to be held - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + InterruptsSpinLocker locker(thread->scheduler_lock); fill_thread_info(thread, info, size); @@ -3055,7 +3070,7 @@ _get_next_thread_info(team_id teamID, int32 *_cookie, thread_info *info, *_cookie = lastID; ThreadLocker threadLocker(thread); - InterruptsSpinLocker schedulerLocker(gSchedulerLock); + InterruptsSpinLocker locker(thread->scheduler_lock); fill_thread_info(thread, info, size); @@ -3121,8 +3136,6 @@ rename_thread(thread_id id, const char* name) status_t set_thread_priority(thread_id id, int32 priority) { - int32 oldPriority; - // make sure the passed in priority is within bounds if (priority > THREAD_MAX_SET_PRIORITY) priority = THREAD_MAX_SET_PRIORITY; @@ -3140,12 +3153,7 @@ set_thread_priority(thread_id id, int32 priority) if (thread_is_idle_thread(thread)) return B_NOT_ALLOWED; - InterruptsSpinLocker schedulerLocker(gSchedulerLock); - - oldPriority = thread->priority; - scheduler_set_thread_priority(thread, priority); - - return oldPriority; + return scheduler_set_thread_priority(thread, priority); }