kernel: Add thread_unblock() and use it where possible

This commit is contained in:
Pawel Dziepak 2013-10-30 03:58:36 +01:00
parent d70728f54d
commit c8dd9f7780
11 changed files with 33 additions and 41 deletions

View File

@ -132,6 +132,7 @@ status_t thread_block();
status_t thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout); status_t thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout);
status_t thread_block_with_timeout_locked(uint32 timeoutFlags, status_t thread_block_with_timeout_locked(uint32 timeoutFlags,
bigtime_t timeout); bigtime_t timeout);
void thread_unblock(Thread* thread, status_t status);
// used in syscalls.c // used in syscalls.c
status_t _user_set_thread_priority(thread_id thread, int32 newPriority); status_t _user_set_thread_priority(thread_id thread, int32 newPriority);

View File

@ -298,8 +298,7 @@ SystemProfiler::~SystemProfiler()
// inactive. // inactive.
InterruptsSpinLocker locker(fLock); InterruptsSpinLocker locker(fLock);
if (fWaitingProfilerThread != NULL) { if (fWaitingProfilerThread != NULL) {
InterruptsSpinLocker schedulerLocker(gSchedulerLock); thread_unblock(fWaitingProfilerThread, B_OK);
thread_unblock_locked(fWaitingProfilerThread, B_OK);
fWaitingProfilerThread = NULL; fWaitingProfilerThread = NULL;
} }
fProfilingActive = false; fProfilingActive = false;

View File

@ -88,6 +88,5 @@ vnode::_WakeUpLocker()
atomic_and(&fFlags, ~kFlagsWaitingLocker); atomic_and(&fFlags, ~kFlagsWaitingLocker);
// and wake it up // and wake it up
InterruptsSpinLocker threadLocker(gSchedulerLock); thread_unblock(waiter->thread, B_OK);
thread_unblock_locked(waiter->thread, B_OK);
} }

View File

@ -100,8 +100,7 @@ public:
TRACE("ReadRequest %p::Notify(), fNotified %d\n", this, fNotified); TRACE("ReadRequest %p::Notify(), fNotified %d\n", this, fNotified);
if (!fNotified) { if (!fNotified) {
SpinLocker schedulerLocker(gSchedulerLock); thread_unblock(fThread, status);
thread_unblock_locked(fThread, status);
fNotified = true; fNotified = true;
} }
} }

View File

@ -197,9 +197,7 @@ rw_lock_unblock(rw_lock* lock)
lock->holder = waiter->thread->id; lock->holder = waiter->thread->id;
// unblock thread // unblock thread
InterruptsSpinLocker schedulerLocker(gSchedulerLock); thread_unblock(waiter->thread, B_OK);
thread_unblock_locked(waiter->thread, B_OK);
schedulerLocker.Unlock();
waiter->thread = NULL; waiter->thread = NULL;
return RW_LOCK_WRITER_COUNT_BASE; return RW_LOCK_WRITER_COUNT_BASE;
@ -216,9 +214,7 @@ rw_lock_unblock(rw_lock* lock)
readerCount++; readerCount++;
// unblock thread // unblock thread
InterruptsSpinLocker schedulerLocker(gSchedulerLock); thread_unblock(waiter->thread, B_OK);
thread_unblock_locked(waiter->thread, B_OK);
schedulerLocker.Unlock();
waiter->thread = NULL; waiter->thread = NULL;
} while ((waiter = lock->waiters) != NULL && !waiter->writer); } while ((waiter = lock->waiters) != NULL && !waiter->writer);
@ -293,8 +289,7 @@ rw_lock_destroy(rw_lock* lock)
lock->waiters = waiter->next; lock->waiters = waiter->next;
// unblock thread // unblock thread
InterruptsSpinLocker _(gSchedulerLock); thread_unblock(waiter->thread, B_ERROR);
thread_unblock_locked(waiter->thread, B_ERROR);
} }
lock->name = NULL; lock->name = NULL;
@ -637,8 +632,7 @@ mutex_destroy(mutex* lock)
lock->waiters = waiter->next; lock->waiters = waiter->next;
// unblock thread // unblock thread
InterruptsSpinLocker schedulerLocker(gSchedulerLock); thread_unblock(waiter->thread, B_ERROR);
thread_unblock_locked(waiter->thread, B_ERROR);
} }
lock->name = NULL; lock->name = NULL;
@ -783,9 +777,7 @@ _mutex_unlock(mutex* lock)
lock->waiters->last = waiter->last; lock->waiters->last = waiter->last;
// unblock thread // unblock thread
InterruptsSpinLocker schedulerLocker(gSchedulerLock); thread_unblock(waiter->thread, B_OK);
thread_unblock_locked(waiter->thread, B_OK);
schedulerLocker.Unlock();
#if KDEBUG #if KDEBUG
// Already set the holder to the unblocked thread. Besides that this // Already set the holder to the unblocked thread. Besides that this

View File

@ -246,8 +246,6 @@ public:
void WakeUpThread(bool waitForMessage) void WakeUpThread(bool waitForMessage)
{ {
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
if (waitForMessage) { if (waitForMessage) {
// Wake up all waiting thread for a message // Wake up all waiting thread for a message
// TODO: this can cause starvation for any // TODO: this can cause starvation for any
@ -255,14 +253,14 @@ public:
while (queued_thread *entry = fWaitingToReceive.RemoveHead()) { while (queued_thread *entry = fWaitingToReceive.RemoveHead()) {
entry->queued = false; entry->queued = false;
fThreadsWaitingToReceive--; fThreadsWaitingToReceive--;
thread_unblock_locked(entry->thread, 0); thread_unblock(entry->thread, 0);
} }
} else { } else {
// Wake up only one thread waiting to send // Wake up only one thread waiting to send
if (queued_thread *entry = fWaitingToSend.RemoveHead()) { if (queued_thread *entry = fWaitingToSend.RemoveHead()) {
entry->queued = false; entry->queued = false;
fThreadsWaitingToSend--; fThreadsWaitingToSend--;
thread_unblock_locked(entry->thread, 0); thread_unblock(entry->thread, 0);
} }
} }
} }
@ -400,15 +398,13 @@ XsiMessageQueue::~XsiMessageQueue()
// Wake up any threads still waiting // Wake up any threads still waiting
if (fThreadsWaitingToSend || fThreadsWaitingToReceive) { if (fThreadsWaitingToSend || fThreadsWaitingToReceive) {
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
while (queued_thread *entry = fWaitingToReceive.RemoveHead()) { while (queued_thread *entry = fWaitingToReceive.RemoveHead()) {
entry->queued = false; entry->queued = false;
thread_unblock_locked(entry->thread, EIDRM); thread_unblock(entry->thread, EIDRM);
} }
while (queued_thread *entry = fWaitingToSend.RemoveHead()) { while (queued_thread *entry = fWaitingToSend.RemoveHead()) {
entry->queued = false; entry->queued = false;
thread_unblock_locked(entry->thread, EIDRM); thread_unblock(entry->thread, EIDRM);
} }
} }

View File

@ -101,15 +101,13 @@ public:
{ {
// For some reason the semaphore is getting destroyed. // For some reason the semaphore is getting destroyed.
// Wake up any remaing awaiting threads // Wake up any remaing awaiting threads
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
while (queued_thread *entry = fWaitingToIncreaseQueue.RemoveHead()) { while (queued_thread *entry = fWaitingToIncreaseQueue.RemoveHead()) {
entry->queued = false; entry->queued = false;
thread_unblock_locked(entry->thread, EIDRM); thread_unblock(entry->thread, EIDRM);
} }
while (queued_thread *entry = fWaitingToBeZeroQueue.RemoveHead()) { while (queued_thread *entry = fWaitingToBeZeroQueue.RemoveHead()) {
entry->queued = false; entry->queued = false;
thread_unblock_locked(entry->thread, EIDRM); thread_unblock(entry->thread, EIDRM);
} }
// No need to remove any sem_undo request still // No need to remove any sem_undo request still
// hanging. When the process exit and doesn't found // hanging. When the process exit and doesn't found
@ -218,20 +216,19 @@ public:
void WakeUpThread(bool waitingForZero) void WakeUpThread(bool waitingForZero)
{ {
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
if (waitingForZero) { if (waitingForZero) {
// Wake up all threads waiting on zero // Wake up all threads waiting on zero
while (queued_thread *entry = fWaitingToBeZeroQueue.RemoveHead()) { while (queued_thread *entry = fWaitingToBeZeroQueue.RemoveHead()) {
entry->queued = false; entry->queued = false;
fThreadsWaitingToBeZero--; fThreadsWaitingToBeZero--;
thread_unblock_locked(entry->thread, 0); thread_unblock(entry->thread, 0);
} }
} else { } else {
// Wake up all threads even though they might go back to sleep // Wake up all threads even though they might go back to sleep
while (queued_thread *entry = fWaitingToIncreaseQueue.RemoveHead()) { while (queued_thread *entry = fWaitingToIncreaseQueue.RemoveHead()) {
entry->queued = false; entry->queued = false;
fThreadsWaitingToIncrease--; fThreadsWaitingToIncrease--;
thread_unblock_locked(entry->thread, 0); thread_unblock(entry->thread, 0);
} }
} }
} }

View File

@ -330,12 +330,10 @@ uninit_sem_locked(struct sem_entry& sem, char** _name)
sem.u.used.select_infos = NULL; sem.u.used.select_infos = NULL;
// free any threads waiting for this semaphore // free any threads waiting for this semaphore
SpinLocker schedulerLocker(gSchedulerLock);
while (queued_thread* entry = sem.queue.RemoveHead()) { while (queued_thread* entry = sem.queue.RemoveHead()) {
entry->queued = false; entry->queued = false;
thread_unblock_locked(entry->thread, B_BAD_SEM_ID); thread_unblock(entry->thread, B_BAD_SEM_ID);
} }
schedulerLocker.Unlock();
int32 id = sem.id; int32 id = sem.id;
sem.id = -1; sem.id = -1;

View File

@ -2889,6 +2889,19 @@ thread_block_with_timeout_locked(uint32 timeoutFlags, bigtime_t timeout)
} }
/*! Unblocks a thread.
Acquires the scheduler lock and calls thread_unblock_locked().
See there for more information.
*/
void
thread_unblock(Thread* thread, status_t status)
{
InterruptsSpinLocker _(gSchedulerLock);
thread_unblock_locked(thread, status);
}
/*! Unblocks a userland-blocked thread. /*! Unblocks a userland-blocked thread.
The caller must not hold any locks. The caller must not hold any locks.
*/ */

View File

@ -1383,8 +1383,7 @@ VMCache::_NotifyPageEvents(vm_page* page, uint32 events)
if (waiter->page == page && (waiter->events & events) != 0) { if (waiter->page == page && (waiter->events & events) != 0) {
// remove from list and unblock // remove from list and unblock
*it = waiter->next; *it = waiter->next;
InterruptsSpinLocker schedulerLocker(gSchedulerLock); thread_unblock(waiter->thread, B_OK);
thread_unblock_locked(waiter->thread, B_OK);
} else } else
it = &waiter->next; it = &waiter->next;
} }

View File

@ -1447,8 +1447,7 @@ wake_up_page_reservation_waiters()
sPageReservationWaiters.Remove(waiter); sPageReservationWaiters.Remove(waiter);
InterruptsSpinLocker schedulerLocker(gSchedulerLock); thread_unblock(waiter->thread, B_OK);
thread_unblock_locked(waiter->thread, B_OK);
} }
} }