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_locked(uint32 timeoutFlags,
bigtime_t timeout);
void thread_unblock(Thread* thread, status_t status);
// used in syscalls.c
status_t _user_set_thread_priority(thread_id thread, int32 newPriority);

View File

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

View File

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

View File

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

View File

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

View File

@ -246,8 +246,6 @@ public:
void WakeUpThread(bool waitForMessage)
{
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
if (waitForMessage) {
// Wake up all waiting thread for a message
// TODO: this can cause starvation for any
@ -255,14 +253,14 @@ public:
while (queued_thread *entry = fWaitingToReceive.RemoveHead()) {
entry->queued = false;
fThreadsWaitingToReceive--;
thread_unblock_locked(entry->thread, 0);
thread_unblock(entry->thread, 0);
}
} else {
// Wake up only one thread waiting to send
if (queued_thread *entry = fWaitingToSend.RemoveHead()) {
entry->queued = false;
fThreadsWaitingToSend--;
thread_unblock_locked(entry->thread, 0);
thread_unblock(entry->thread, 0);
}
}
}
@ -400,15 +398,13 @@ XsiMessageQueue::~XsiMessageQueue()
// Wake up any threads still waiting
if (fThreadsWaitingToSend || fThreadsWaitingToReceive) {
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
while (queued_thread *entry = fWaitingToReceive.RemoveHead()) {
entry->queued = false;
thread_unblock_locked(entry->thread, EIDRM);
thread_unblock(entry->thread, EIDRM);
}
while (queued_thread *entry = fWaitingToSend.RemoveHead()) {
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.
// Wake up any remaing awaiting threads
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
while (queued_thread *entry = fWaitingToIncreaseQueue.RemoveHead()) {
entry->queued = false;
thread_unblock_locked(entry->thread, EIDRM);
thread_unblock(entry->thread, EIDRM);
}
while (queued_thread *entry = fWaitingToBeZeroQueue.RemoveHead()) {
entry->queued = false;
thread_unblock_locked(entry->thread, EIDRM);
thread_unblock(entry->thread, EIDRM);
}
// No need to remove any sem_undo request still
// hanging. When the process exit and doesn't found
@ -218,20 +216,19 @@ public:
void WakeUpThread(bool waitingForZero)
{
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
if (waitingForZero) {
// Wake up all threads waiting on zero
while (queued_thread *entry = fWaitingToBeZeroQueue.RemoveHead()) {
entry->queued = false;
fThreadsWaitingToBeZero--;
thread_unblock_locked(entry->thread, 0);
thread_unblock(entry->thread, 0);
}
} else {
// Wake up all threads even though they might go back to sleep
while (queued_thread *entry = fWaitingToIncreaseQueue.RemoveHead()) {
entry->queued = false;
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;
// free any threads waiting for this semaphore
SpinLocker schedulerLocker(gSchedulerLock);
while (queued_thread* entry = sem.queue.RemoveHead()) {
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;
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.
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) {
// remove from list and unblock
*it = waiter->next;
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
thread_unblock_locked(waiter->thread, B_OK);
thread_unblock(waiter->thread, B_OK);
} else
it = &waiter->next;
}

View File

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