diff options
author | davidxu <davidxu@FreeBSD.org> | 2008-04-22 06:44:11 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2008-04-22 06:44:11 +0000 |
commit | b794176bc5fb652ecc675b87c6385b595cf319ee (patch) | |
tree | bf1782465a09041792c827bf1c707189517061c9 /lib | |
parent | f478ca6e496d8d256e422e83bce84fa1d0c67ac2 (diff) | |
download | FreeBSD-src-b794176bc5fb652ecc675b87c6385b595cf319ee.zip FreeBSD-src-b794176bc5fb652ecc675b87c6385b595cf319ee.tar.gz |
Use native rwlock.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libthr/thread/thr_rtld.c | 74 |
1 files changed, 20 insertions, 54 deletions
diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index f8437a1..a8cd61d 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -40,8 +40,6 @@ extern int errno; #define CACHE_LINE_SIZE 64 -#define WAFLAG 0x1 -#define RC_INCR 0x2 static int _thr_rtld_clr_flag(int); static void *_thr_rtld_lock_create(void); @@ -52,11 +50,7 @@ static int _thr_rtld_set_flag(int); static void _thr_rtld_wlock_acquire(void *); struct rtld_lock { - volatile int lock; - volatile int rd_waiters; - volatile int wr_waiters; - volatile long rd_cv; - volatile long wr_cv; + struct urwlock lock; void *base; }; @@ -67,19 +61,22 @@ _thr_rtld_lock_create(void) char *p; uintptr_t r; struct rtld_lock *l; + size_t size; - THR_ASSERT(sizeof(struct rtld_lock) <= CACHE_LINE_SIZE, - "rtld_lock too large"); - base = calloc(1, CACHE_LINE_SIZE); + size = CACHE_LINE_SIZE; + while (size < sizeof(struct rtld_lock)) + size <<= 1; + base = calloc(1, size); p = (char *)base; if ((uintptr_t)p % CACHE_LINE_SIZE != 0) { free(base); - base = calloc(1, 2 * CACHE_LINE_SIZE); + base = calloc(1, size + CACHE_LINE_SIZE); p = (char *)base; if ((r = (uintptr_t)p % CACHE_LINE_SIZE) != 0) p += CACHE_LINE_SIZE - r; } l = (struct rtld_lock *)p; + l->lock.rw_flags = URWLOCK_PREFER_READER; l->base = base; return (l); } @@ -110,7 +107,6 @@ _thr_rtld_rlock_acquire(void *lock) { struct pthread *curthread; struct rtld_lock *l; - long v; int errsave; curthread = _get_curthread(); @@ -118,18 +114,8 @@ _thr_rtld_rlock_acquire(void *lock) l = (struct rtld_lock *)lock; THR_CRITICAL_ENTER(curthread); - atomic_add_acq_int(&l->lock, RC_INCR); - if (!(l->lock & WAFLAG)) { - RESTORE_ERRNO(); - return; - } - v = l->rd_cv; - atomic_add_int(&l->rd_waiters, 1); - while (l->lock & WAFLAG) { - _thr_umtx_wait(&l->rd_cv, v, NULL); - v = l->rd_cv; - } - atomic_add_int(&l->rd_waiters, -1); + while (_thr_rwlock_rdlock(&l->lock, 0, NULL) != 0) + ; RESTORE_ERRNO(); } @@ -138,7 +124,6 @@ _thr_rtld_wlock_acquire(void *lock) { struct pthread *curthread; struct rtld_lock *l; - long v; int errsave; curthread = _get_curthread(); @@ -146,19 +131,9 @@ _thr_rtld_wlock_acquire(void *lock) l = (struct rtld_lock *)lock; _thr_signal_block(curthread); - for (;;) { - if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) { - RESTORE_ERRNO(); - return; - } - v = l->wr_cv; - atomic_add_int(&l->wr_waiters, 1); - while (l->lock != 0) { - _thr_umtx_wait(&l->wr_cv, v, NULL); - v = l->wr_cv; - } - atomic_add_int(&l->wr_waiters, -1); - } + while (_thr_rwlock_wrlock(&l->lock, NULL) != 0) + ; + RESTORE_ERRNO(); } static void @@ -166,29 +141,20 @@ _thr_rtld_lock_release(void *lock) { struct pthread *curthread; struct rtld_lock *l; + int32_t state; int errsave; curthread = _get_curthread(); SAVE_ERRNO(); l = (struct rtld_lock *)lock; - if ((l->lock & WAFLAG) == 0) { - atomic_add_rel_int(&l->lock, -RC_INCR); - if (l->lock == 0 && l->wr_waiters) { - atomic_add_long(&l->wr_cv, 1); - _thr_umtx_wake(&l->wr_cv, l->wr_waiters); - } - THR_CRITICAL_LEAVE(curthread); - } else { - atomic_add_rel_int(&l->lock, -WAFLAG); - if (l->lock == 0 && l->wr_waiters) { - atomic_add_long(&l->wr_cv, 1); - _thr_umtx_wake(&l->wr_cv, l->wr_waiters); - } else if (l->rd_waiters) { - atomic_add_long(&l->rd_cv, 1); - _thr_umtx_wake(&l->rd_cv, l->rd_waiters); + state = l->lock.rw_state; + if (_thr_rwlock_unlock(&l->lock) == 0) { + if ((state & URWLOCK_WRITE_OWNER) == 0) { + THR_CRITICAL_LEAVE(curthread); + } else { + _thr_signal_unblock(curthread); } - _thr_signal_unblock(curthread); } RESTORE_ERRNO(); } |