darwin-kernel-rwlocks-20081023
authorDerrick Brashear <shadow@dementia.org>
Fri, 24 Oct 2008 22:07:01 +0000 (22:07 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 24 Oct 2008 22:07:01 +0000 (22:07 +0000)
LICENSE IPL10

convert to kernel rwlocks on darwin

src/rx/DARWIN/rx_kmutex.c
src/rx/DARWIN/rx_kmutex.h

index 98f9ba4..007769c 100644 (file)
@@ -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
index cf3f9aa..e297303 100644 (file)
@@ -18,6 +18,9 @@
 
 #ifdef AFS_DARWIN80_ENV
 #include <kern/locks.h>
+/* 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 <sys/lock.h>
 #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);       \
 
 #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