diff --git a/headers/private/kernel/lock.h b/headers/private/kernel/lock.h index 23de9af291..f526f5e807 100644 --- a/headers/private/kernel/lock.h +++ b/headers/private/kernel/lock.h @@ -42,6 +42,7 @@ struct rw_lock_waiter; typedef struct rw_lock { const char* name; + mutex lock; struct rw_lock_waiter* waiters; thread_id holder; int32 reader_count; @@ -85,7 +86,8 @@ typedef struct rw_lock { # define RECURSIVE_LOCK_INITIALIZER(name) { MUTEX_INITIALIZER(name), -1, 0 } #endif -#define RW_LOCK_INITIALIZER(name) { name, NULL, -1, 0, 0, 0 } +#define RW_LOCK_INITIALIZER(name) { name, MUTEX_INITIALIZER(name), \ + NULL, -1, 0, 0, 0 } #if KDEBUG diff --git a/src/system/kernel/lock.cpp b/src/system/kernel/lock.cpp index 76220c71de..5f8a7b241f 100644 --- a/src/system/kernel/lock.cpp +++ b/src/system/kernel/lock.cpp @@ -164,6 +164,10 @@ rw_lock_wait(rw_lock* lock, bool writer) lock->waiters->last = &waiter; + InterruptsSpinLocker locker(gThreadSpinlock); + + _mutex_unlock(&lock->lock, true); + // block thread_prepare_to_block(waiter.thread, 0, THREAD_BLOCK_TYPE_RW_LOCK, lock); return thread_block_locked(waiter.thread); @@ -190,6 +194,7 @@ rw_lock_unblock(rw_lock* lock) lock->holder = waiter->thread->id; // unblock thread + InterruptsSpinLocker locker(gThreadSpinlock); thread_unblock_locked(waiter->thread, B_OK); } return; @@ -205,6 +210,7 @@ rw_lock_unblock(rw_lock* lock) lock->reader_count++; // unblock thread + InterruptsSpinLocker locker(gThreadSpinlock); thread_unblock_locked(waiter->thread, B_OK); } } @@ -221,6 +227,8 @@ rw_lock_init(rw_lock* lock, const char* name) lock->owner_count = 0; lock->flags = 0; + mutex_init(&lock->lock, name); + T_SCHEDULING_ANALYSIS(InitRWLock(lock, name)); NotifyWaitObjectListeners(&WaitObjectListener::RWLockInitialized, lock); } @@ -237,6 +245,8 @@ rw_lock_init_etc(rw_lock* lock, const char* name, uint32 flags) lock->owner_count = 0; lock->flags = flags & RW_LOCK_FLAG_CLONE_NAME; + mutex_init(&lock->lock, lock->name); + T_SCHEDULING_ANALYSIS(InitRWLock(lock, name)); NotifyWaitObjectListeners(&WaitObjectListener::RWLockInitialized, lock); } @@ -252,8 +262,8 @@ rw_lock_destroy(rw_lock* lock) InterruptsSpinLocker locker(gThreadSpinlock); #if KDEBUG - if (lock->waiters != NULL && thread_get_current_thread_id() - != lock->holder) { + if (lock->waiters != NULL + && thread_get_current_thread_id() != lock->holder) { panic("rw_lock_destroy(): there are blocking threads, but the caller " "doesn't hold the write lock (%p)", lock); @@ -275,6 +285,7 @@ rw_lock_destroy(rw_lock* lock) lock->name = NULL; locker.Unlock(); + mutex_destroy(&lock->lock); free(name); } @@ -286,7 +297,7 @@ rw_lock_read_lock(rw_lock* lock) #if KDEBUG_RW_LOCK_DEBUG return rw_lock_write_lock(lock); #else - InterruptsSpinLocker locker(gThreadSpinlock); + MutexLocker locker(lock->lock); if (lock->writer_count == 0) { lock->reader_count++; @@ -297,6 +308,8 @@ rw_lock_read_lock(rw_lock* lock) return B_OK; } + locker.Detach(); + return rw_lock_wait(lock, false); #endif } @@ -308,7 +321,7 @@ rw_lock_read_unlock(rw_lock* lock) #if KDEBUG_RW_LOCK_DEBUG return rw_lock_write_unlock(lock); #else - InterruptsSpinLocker locker(gThreadSpinlock); + MutexLocker locker(lock->lock); if (lock->holder == thread_get_current_thread_id()) { if (--lock->owner_count > 0) @@ -338,7 +351,7 @@ rw_lock_read_unlock(rw_lock* lock) status_t rw_lock_write_lock(rw_lock* lock) { - InterruptsSpinLocker locker(gThreadSpinlock); + MutexLocker locker(lock->lock); if (lock->reader_count == 0 && lock->writer_count == 0) { lock->writer_count++; @@ -352,6 +365,7 @@ rw_lock_write_lock(rw_lock* lock) } lock->writer_count++; + locker.Detach(); status_t status = rw_lock_wait(lock, true); if (status == B_OK) { @@ -365,7 +379,7 @@ rw_lock_write_lock(rw_lock* lock) status_t rw_lock_write_unlock(rw_lock* lock) { - InterruptsSpinLocker locker(gThreadSpinlock); + MutexLocker locker(lock->lock); if (thread_get_current_thread_id() != lock->holder) { panic("rw_lock_write_unlock(): lock %p not write-locked by this thread",