From 069cd726c093d4856dc98353a75080547ea4e751 Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Fri, 24 Oct 2008 22:07:01 +0000 Subject: [PATCH] darwin-kernel-rwlocks-20081023 LICENSE IPL10 convert to kernel rwlocks on darwin --- src/rx/DARWIN/rx_kmutex.c | 4 + src/rx/DARWIN/rx_kmutex.h | 159 ++++++++++++++++++++++++++------------ 2 files changed, 114 insertions(+), 49 deletions(-) diff --git a/src/rx/DARWIN/rx_kmutex.c b/src/rx/DARWIN/rx_kmutex.c index 98f9ba4c8a..007769ce5d 100644 --- a/src/rx/DARWIN/rx_kmutex.c +++ b/src/rx/DARWIN/rx_kmutex.c @@ -35,6 +35,7 @@ RCSID #endif /* defined(AFS_DARWIN70_ENV) */ lck_grp_t * openafs_lck_grp; +lck_grp_t * openafs_rw_grp; static lck_grp_attr_t * openafs_lck_grp_attr; void rx_kmutex_setup(void) { openafs_lck_grp_attr= lck_grp_attr_alloc_init(); @@ -43,10 +44,13 @@ void rx_kmutex_setup(void) { openafs_lck_grp = lck_grp_alloc_init("openafs", openafs_lck_grp_attr); lck_grp_attr_free(openafs_lck_grp_attr); + openafs_rw_grp = lck_grp_alloc_init("openafs-rw", openafs_lck_grp_attr); + lck_grp_attr_free(openafs_lck_grp_attr); } void rx_kmutex_finish(void) { lck_grp_free(openafs_lck_grp); + lck_grp_free(openafs_rw_grp); } #endif diff --git a/src/rx/DARWIN/rx_kmutex.h b/src/rx/DARWIN/rx_kmutex.h index cf3f9aae9a..e29730394b 100644 --- a/src/rx/DARWIN/rx_kmutex.h +++ b/src/rx/DARWIN/rx_kmutex.h @@ -18,6 +18,9 @@ #ifdef AFS_DARWIN80_ENV #include +/* kernel private from osfmk/kern/locks.h ... sigh */ +extern boolean_t lck_mtx_try_lock(lck_mtx_t *lck); +extern boolean_t lck_rw_try_lock(lck_rw_t *lck, lck_rw_type_t lck_rw_type); #else #include #endif @@ -52,9 +55,7 @@ if (isGlockOwner) AFS_GUNLOCK(); \ osi_Assert((lck)->owner == current_thread()); \ (lck)->owner = (thread_t)0; \ - lck_mtx_lock((lck)->meta); \ - (lck)->waiters--; \ - lck_mtx_unlock((lck)->meta); \ + OSAtomicDecrement32Barrier((lck)->waiters); \ msleep(cv, (lck)->lock, PDROP|PVFS, "afs_CV_WAIT", NULL); \ if (isGlockOwner) AFS_GLOCK(); \ MUTEX_ENTER(lck); \ @@ -68,9 +69,7 @@ if (isGlockOwner) AFS_GUNLOCK(); \ osi_Assert((lck)->owner == current_thread()); \ (lck)->owner = (thread_t)0; \ - lck_mtx_lock((lck)->meta); \ - (lck)->waiters--; \ - lck_mtx_unlock((lck)->meta); \ + OSAtomicDecrement32Barrier((lck)->waiters); \ msleep(cv, (lck)->lock, PDROP|PVFS, "afs_CV_TIMEDWAIT", &ts); \ if (isGlockOwner) AFS_GLOCK(); \ MUTEX_ENTER(lck); \ @@ -124,74 +123,136 @@ #ifdef AFS_DARWIN80_ENV typedef struct { - lck_mtx_t *meta; int waiters; /* also includes anyone holding the lock */ lck_mtx_t *lock; thread_t owner; } afs_kmutex_t; typedef int afs_kcondvar_t; +typedef struct { + int readers; + lck_mtx_t *lock; + thread_t owner; +} afs_krwlock_t; + extern lck_grp_t * openafs_lck_grp; +extern lck_grp_t * openafs_rw_grp; + +#define RWLOCK_UPLOCK(a) \ + do { \ + osi_Assert((a)->owner != current_thread()); \ + lck_rw_lock_shared_to_exclusive((a)->lock); \ + osi_Assert((a)->owner == (thread_t)0); \ + (a)->owner = current_thread(); \ + OSAtomicDecrement32Barrier((a)->readers); \ + } while(0) + +#define RWLOCK_INIT(a,b,c,d) \ + do { \ + lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \ + (a)->lock = lck_rw_alloc_init(openafs_rw_grp, openafs_lck_attr); \ + lck_attr_free(openafs_lck_attr); \ + (a)->readers = 0; \ + (a)->owner = (thread_t)0; \ + } while(0) +#define RWLOCK_DESTROY(a) \ + do { \ + lck_rw_destroy((a)->lock, openafs_rw_grp); \ + (a)->owner = (thread_t)-1; \ + } while(0) +#define RWLOCK_RDLOCK(a) \ + do { \ + OSAtomicIncrement32Barrier((a)->readers); \ + lck_rw_lock_shared((a)->lock); \ + } while(0) +#define RWLOCK_WRLOCK(a) \ + do { \ + osi_Assert((a)->owner != current_thread()); \ + lck_rw_lock_exclusive((a)->lock); \ + osi_Assert((a)->owner == (thread_t)0); \ + (a)->owner = current_thread(); \ + } while(0) + +/* acquire main lock before releasing meta lock, so we don't race */ +#define RWLOCK_TRYRDLOCK(a) ({ \ + int _ret; \ + _ret = lck_rw_try_lock((a)->lock, LCK_RW_TYPE_SHARED); \ + if (_ret) { \ + OSAtomicIncrement32Barrier((a)->readers); \ + } \ + _ret; \ + }) + +/* acquire main lock before releasing meta lock, so we don't race */ +#define RWLOCK_TRYWRLOCK(a) ({ \ + int _ret; \ + osi_Assert((a)->owner != current_thread()); \ + _ret = lck_rw_try_lock((a)->lock, LCK_RW_TYPE_EXCLUSIVE); \ + if (_ret) { \ + osi_Assert((a)->owner == (thread_t)0); \ + (a)->owner = current_thread(); \ + } \ + _ret; \ + }) + +#define RWLOCK_UNLOCK(a) \ + do { \ + if ((a)->owner == current_thread()) { \ + (a)->owner = (thread_t)0; \ + lck_rw_unlock_exclusive((a)->lock); \ + } else { \ + lck_rw_unlock_shared((a)->lock); \ + OSAtomicDecrement32Barrier((a)->readers); \ + } \ + } while(0) #define MUTEX_SETUP() rx_kmutex_setup() #define MUTEX_FINISH() rx_kmutex_finish() #define LOCKINIT(a) \ do { \ - lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \ + lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \ (a) = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \ - lck_attr_free(openafs_lck_attr); \ + lck_attr_free(openafs_lck_attr); \ } while(0) #define MUTEX_INIT(a,b,c,d) \ - do { \ - lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \ - (a)->meta = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \ + do { \ + lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \ (a)->lock = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \ - lck_attr_free(openafs_lck_attr); \ - (a)->waiters = 0; \ - (a)->owner = (thread_t)0; \ + lck_attr_free(openafs_lck_attr); \ + (a)->waiters = 0; \ + (a)->owner = (thread_t)0; \ } while(0) #define MUTEX_DESTROY(a) \ do { \ - lck_mtx_destroy((a)->lock, openafs_lck_grp); \ - lck_mtx_destroy((a)->meta, openafs_lck_grp); \ - (a)->owner = (thread_t)-1; \ + lck_mtx_destroy((a)->lock, openafs_lck_grp); \ + (a)->owner = (thread_t)-1; \ } while(0) -#define MUTEX_ENTER(a) \ - do { \ - lck_mtx_lock((a)->meta); \ - (a)->waiters++; \ - lck_mtx_unlock((a)->meta); \ - lck_mtx_lock((a)->lock); \ - osi_Assert((a)->owner == (thread_t)0); \ - (a)->owner = current_thread(); \ +#define MUTEX_ENTER(a) \ + do { \ + OSAtomicIncrement32Barrier((a)->waiters); \ + lck_mtx_lock((a)->lock); \ + osi_Assert((a)->owner == (thread_t)0); \ + (a)->owner = current_thread(); \ } while(0) /* acquire main lock before releasing meta lock, so we don't race */ -#define MUTEX_TRYENTER(a) ({ \ - int _ret; \ - lck_mtx_lock((a)->meta); \ - if ((a)->waiters) { \ - lck_mtx_unlock((a)->meta); \ - _ret = 0; \ - } else { \ - (a)->waiters++; \ - lck_mtx_lock((a)->lock); \ - lck_mtx_unlock((a)->meta); \ - osi_Assert((a)->owner == (thread_t)0); \ - (a)->owner = current_thread(); \ - _ret = 1; \ - } \ - _ret; \ -}) +#define MUTEX_TRYENTER(a) ({ \ + int _ret; \ + _ret = lck_mtx_try_lock((a)->lock); \ + if (_ret) { \ + OSAtomicIncrement32Barrier((a)->waiters); \ + osi_Assert((a)->owner == (thread_t)0); \ + (a)->owner = current_thread(); \ + } \ + _ret; \ + }) -#define MUTEX_EXIT(a) \ - do { \ +#define MUTEX_EXIT(a) \ + do { \ osi_Assert((a)->owner == current_thread()); \ - (a)->owner = (thread_t)0; \ - lck_mtx_unlock((a)->lock); \ - lck_mtx_lock((a)->meta); \ - (a)->waiters--; \ - lck_mtx_unlock((a)->meta); \ + (a)->owner = (thread_t)0; \ + lck_mtx_unlock((a)->lock); \ + OSAtomicDecrement32Barrier((a)->waiters); \ } while(0) #undef MUTEX_ISMINE