* The rw_lock is now using a mutex to protect its reader/writer counts. This
makes the reader case a lot less expensive, and should relieve the thread spinlock contention a bit. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33643 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -42,6 +42,7 @@ struct rw_lock_waiter;
|
|||||||
|
|
||||||
typedef struct rw_lock {
|
typedef struct rw_lock {
|
||||||
const char* name;
|
const char* name;
|
||||||
|
mutex lock;
|
||||||
struct rw_lock_waiter* waiters;
|
struct rw_lock_waiter* waiters;
|
||||||
thread_id holder;
|
thread_id holder;
|
||||||
int32 reader_count;
|
int32 reader_count;
|
||||||
@@ -85,7 +86,8 @@ typedef struct rw_lock {
|
|||||||
# define RECURSIVE_LOCK_INITIALIZER(name) { MUTEX_INITIALIZER(name), -1, 0 }
|
# define RECURSIVE_LOCK_INITIALIZER(name) { MUTEX_INITIALIZER(name), -1, 0 }
|
||||||
#endif
|
#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
|
#if KDEBUG
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ rw_lock_wait(rw_lock* lock, bool writer)
|
|||||||
|
|
||||||
lock->waiters->last = &waiter;
|
lock->waiters->last = &waiter;
|
||||||
|
|
||||||
|
InterruptsSpinLocker locker(gThreadSpinlock);
|
||||||
|
|
||||||
|
_mutex_unlock(&lock->lock, true);
|
||||||
|
|
||||||
// block
|
// block
|
||||||
thread_prepare_to_block(waiter.thread, 0, THREAD_BLOCK_TYPE_RW_LOCK, lock);
|
thread_prepare_to_block(waiter.thread, 0, THREAD_BLOCK_TYPE_RW_LOCK, lock);
|
||||||
return thread_block_locked(waiter.thread);
|
return thread_block_locked(waiter.thread);
|
||||||
@@ -190,6 +194,7 @@ rw_lock_unblock(rw_lock* lock)
|
|||||||
lock->holder = waiter->thread->id;
|
lock->holder = waiter->thread->id;
|
||||||
|
|
||||||
// unblock thread
|
// unblock thread
|
||||||
|
InterruptsSpinLocker locker(gThreadSpinlock);
|
||||||
thread_unblock_locked(waiter->thread, B_OK);
|
thread_unblock_locked(waiter->thread, B_OK);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -205,6 +210,7 @@ rw_lock_unblock(rw_lock* lock)
|
|||||||
lock->reader_count++;
|
lock->reader_count++;
|
||||||
|
|
||||||
// unblock thread
|
// unblock thread
|
||||||
|
InterruptsSpinLocker locker(gThreadSpinlock);
|
||||||
thread_unblock_locked(waiter->thread, B_OK);
|
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->owner_count = 0;
|
||||||
lock->flags = 0;
|
lock->flags = 0;
|
||||||
|
|
||||||
|
mutex_init(&lock->lock, name);
|
||||||
|
|
||||||
T_SCHEDULING_ANALYSIS(InitRWLock(lock, name));
|
T_SCHEDULING_ANALYSIS(InitRWLock(lock, name));
|
||||||
NotifyWaitObjectListeners(&WaitObjectListener::RWLockInitialized, lock);
|
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->owner_count = 0;
|
||||||
lock->flags = flags & RW_LOCK_FLAG_CLONE_NAME;
|
lock->flags = flags & RW_LOCK_FLAG_CLONE_NAME;
|
||||||
|
|
||||||
|
mutex_init(&lock->lock, lock->name);
|
||||||
|
|
||||||
T_SCHEDULING_ANALYSIS(InitRWLock(lock, name));
|
T_SCHEDULING_ANALYSIS(InitRWLock(lock, name));
|
||||||
NotifyWaitObjectListeners(&WaitObjectListener::RWLockInitialized, lock);
|
NotifyWaitObjectListeners(&WaitObjectListener::RWLockInitialized, lock);
|
||||||
}
|
}
|
||||||
@@ -252,8 +262,8 @@ rw_lock_destroy(rw_lock* lock)
|
|||||||
InterruptsSpinLocker locker(gThreadSpinlock);
|
InterruptsSpinLocker locker(gThreadSpinlock);
|
||||||
|
|
||||||
#if KDEBUG
|
#if KDEBUG
|
||||||
if (lock->waiters != NULL && thread_get_current_thread_id()
|
if (lock->waiters != NULL
|
||||||
!= lock->holder) {
|
&& thread_get_current_thread_id() != lock->holder) {
|
||||||
panic("rw_lock_destroy(): there are blocking threads, but the caller "
|
panic("rw_lock_destroy(): there are blocking threads, but the caller "
|
||||||
"doesn't hold the write lock (%p)", lock);
|
"doesn't hold the write lock (%p)", lock);
|
||||||
|
|
||||||
@@ -275,6 +285,7 @@ rw_lock_destroy(rw_lock* lock)
|
|||||||
lock->name = NULL;
|
lock->name = NULL;
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
mutex_destroy(&lock->lock);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
@@ -286,7 +297,7 @@ rw_lock_read_lock(rw_lock* lock)
|
|||||||
#if KDEBUG_RW_LOCK_DEBUG
|
#if KDEBUG_RW_LOCK_DEBUG
|
||||||
return rw_lock_write_lock(lock);
|
return rw_lock_write_lock(lock);
|
||||||
#else
|
#else
|
||||||
InterruptsSpinLocker locker(gThreadSpinlock);
|
MutexLocker locker(lock->lock);
|
||||||
|
|
||||||
if (lock->writer_count == 0) {
|
if (lock->writer_count == 0) {
|
||||||
lock->reader_count++;
|
lock->reader_count++;
|
||||||
@@ -297,6 +308,8 @@ rw_lock_read_lock(rw_lock* lock)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locker.Detach();
|
||||||
|
|
||||||
return rw_lock_wait(lock, false);
|
return rw_lock_wait(lock, false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -308,7 +321,7 @@ rw_lock_read_unlock(rw_lock* lock)
|
|||||||
#if KDEBUG_RW_LOCK_DEBUG
|
#if KDEBUG_RW_LOCK_DEBUG
|
||||||
return rw_lock_write_unlock(lock);
|
return rw_lock_write_unlock(lock);
|
||||||
#else
|
#else
|
||||||
InterruptsSpinLocker locker(gThreadSpinlock);
|
MutexLocker locker(lock->lock);
|
||||||
|
|
||||||
if (lock->holder == thread_get_current_thread_id()) {
|
if (lock->holder == thread_get_current_thread_id()) {
|
||||||
if (--lock->owner_count > 0)
|
if (--lock->owner_count > 0)
|
||||||
@@ -338,7 +351,7 @@ rw_lock_read_unlock(rw_lock* lock)
|
|||||||
status_t
|
status_t
|
||||||
rw_lock_write_lock(rw_lock* lock)
|
rw_lock_write_lock(rw_lock* lock)
|
||||||
{
|
{
|
||||||
InterruptsSpinLocker locker(gThreadSpinlock);
|
MutexLocker locker(lock->lock);
|
||||||
|
|
||||||
if (lock->reader_count == 0 && lock->writer_count == 0) {
|
if (lock->reader_count == 0 && lock->writer_count == 0) {
|
||||||
lock->writer_count++;
|
lock->writer_count++;
|
||||||
@@ -352,6 +365,7 @@ rw_lock_write_lock(rw_lock* lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lock->writer_count++;
|
lock->writer_count++;
|
||||||
|
locker.Detach();
|
||||||
|
|
||||||
status_t status = rw_lock_wait(lock, true);
|
status_t status = rw_lock_wait(lock, true);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
@@ -365,7 +379,7 @@ rw_lock_write_lock(rw_lock* lock)
|
|||||||
status_t
|
status_t
|
||||||
rw_lock_write_unlock(rw_lock* lock)
|
rw_lock_write_unlock(rw_lock* lock)
|
||||||
{
|
{
|
||||||
InterruptsSpinLocker locker(gThreadSpinlock);
|
MutexLocker locker(lock->lock);
|
||||||
|
|
||||||
if (thread_get_current_thread_id() != lock->holder) {
|
if (thread_get_current_thread_id() != lock->holder) {
|
||||||
panic("rw_lock_write_unlock(): lock %p not write-locked by this thread",
|
panic("rw_lock_write_unlock(): lock %p not write-locked by this thread",
|
||||||
|
|||||||
Reference in New Issue
Block a user