R/W lock implementation:
* Changed the rw_lock_{read,write}_unlock() return values to void. They
returned a value != B_OK only in case of user error and no-one checked them
anyway.
* Optimized rw_lock_read_[un]lock(). They are inline now and as long as
there's no contending write locker, they will only perform an atomic_add().
* Changed the semantics of nested locking after acquiring a write lock: Read
and write locks are counted separately, so read locks no longer implicitly
become write locks. This does e.g. make degrading a write lock to a read
lock by way of read_lock + write_unlock (as used in the VM) actually work.
These changes speed up the -j8 Haiku image build on my machine by a few
percent, but more interestingly they reduce the total kernel time by 25 %.
Apparently we get more contention on other locks, now.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34830 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, [email protected].
|
||||
* Copyright 2008-2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2002-2009, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
@@ -45,12 +45,21 @@ typedef struct rw_lock {
|
||||
const char* name;
|
||||
struct rw_lock_waiter* waiters;
|
||||
thread_id holder;
|
||||
int32 reader_count;
|
||||
int32 writer_count;
|
||||
vint32 count;
|
||||
int32 owner_count;
|
||||
int16 active_readers;
|
||||
// Only > 0 while a writer is waiting: number
|
||||
// of active readers when the first waiting
|
||||
// writer started waiting.
|
||||
int16 pending_readers;
|
||||
// Number of readers that have already
|
||||
// incremented "count", but have not yet started
|
||||
// to wait at the time the last writer unlocked.
|
||||
uint32 flags;
|
||||
} rw_lock;
|
||||
|
||||
#define RW_LOCK_WRITER_COUNT_BASE 0x10000
|
||||
|
||||
#define RW_LOCK_FLAG_CLONE_NAME 0x1
|
||||
|
||||
|
||||
@@ -114,10 +123,8 @@ extern void rw_lock_init(rw_lock* lock, const char* name);
|
||||
// name is *not* cloned nor freed in rw_lock_destroy()
|
||||
extern void rw_lock_init_etc(rw_lock* lock, const char* name, uint32 flags);
|
||||
extern void rw_lock_destroy(rw_lock* lock);
|
||||
extern status_t rw_lock_read_lock(rw_lock* lock);
|
||||
extern status_t rw_lock_read_unlock(rw_lock* lock);
|
||||
extern status_t rw_lock_write_lock(rw_lock* lock);
|
||||
extern status_t rw_lock_write_unlock(rw_lock* lock);
|
||||
extern void rw_lock_write_unlock(rw_lock* lock);
|
||||
|
||||
extern void mutex_init(mutex* lock, const char* name);
|
||||
// name is *not* cloned nor freed in mutex_destroy()
|
||||
@@ -129,7 +136,12 @@ extern status_t mutex_switch_lock(mutex* from, mutex* to);
|
||||
// to, the operation is safe as long as "from" is held while destroying
|
||||
// "to".
|
||||
|
||||
|
||||
// implementation private:
|
||||
|
||||
extern status_t _rw_lock_read_lock(rw_lock* lock);
|
||||
extern void _rw_lock_read_unlock(rw_lock* lock);
|
||||
|
||||
extern status_t _mutex_lock(mutex* lock, bool threadsLocked);
|
||||
extern void _mutex_unlock(mutex* lock, bool threadsLocked);
|
||||
extern status_t _mutex_trylock(mutex* lock);
|
||||
@@ -137,6 +149,33 @@ extern status_t _mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags,
|
||||
bigtime_t timeout);
|
||||
|
||||
|
||||
static inline status_t
|
||||
rw_lock_read_lock(rw_lock* lock)
|
||||
{
|
||||
#if KDEBUG_RW_LOCK_DEBUG
|
||||
return rw_lock_write_lock(lock);
|
||||
#else
|
||||
int32 oldCount = atomic_add(&lock->count, 1);
|
||||
if (oldCount >= RW_LOCK_WRITER_COUNT_BASE)
|
||||
return _rw_lock_read_lock(lock);
|
||||
return B_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
rw_lock_read_unlock(rw_lock* lock)
|
||||
{
|
||||
#if KDEBUG_RW_LOCK_DEBUG
|
||||
rw_lock_write_unlock(lock);
|
||||
#else
|
||||
int32 oldCount = atomic_add(&lock->count, -1);
|
||||
if (oldCount >= RW_LOCK_WRITER_COUNT_BASE)
|
||||
_rw_lock_read_unlock(lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline status_t
|
||||
mutex_lock(mutex* lock)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user