added lock.[ch]: recursive read/write locking support. (not actually used yet)
authorNathan Bryant <loanshark@uncensored.citadel.org>
Thu, 17 Jan 2002 00:22:35 +0000 (00:22 +0000)
committerNathan Bryant <loanshark@uncensored.citadel.org>
Thu, 17 Jan 2002 00:22:35 +0000 (00:22 +0000)
citadel/ChangeLog
citadel/lock.c [new file with mode: 0644]
citadel/lock.h [new file with mode: 0644]

index b189fe31535ea0d8c45b7fe714d32798eafcb11b..29058f95b641bbc74df8141f021236e057fa8e25 100644 (file)
@@ -1,4 +1,7 @@
  $Log$
+ Revision 590.65  2002/01/17 00:22:35  nbryant
+ added lock.[ch]: recursive read/write locking support. (not actually used yet)
+
  Revision 590.64  2002/01/15 12:41:53  error
  * Implement alternate_semantics (see comments in citadel.rc file)
 
@@ -3165,5 +3168,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import 
-
-
diff --git a/citadel/lock.c b/citadel/lock.c
new file mode 100644 (file)
index 0000000..39feab0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * read/write locks.
+ * this is just a thin wrapper around POSIX rwlocks to provide recursive
+ * write-locking.
+ * by nathan bryant <nbryant@optonline.net>
+ *
+ * pthread_rwlock_* directly maps to lock_*, using lock_t instead of
+ * pthread_rwlock_t, except lock_init doesn't take an attribute parameter
+ *
+ * There is no initializer macro; use lock_init().
+ *
+ * $Id$
+ */
+
+#define _XOPEN_SOURCE 500 /* Unix98 */
+
+#include <stdlib.h>
+#include "sysdep_decls.h"
+#include "lock.h"
+
+int lock_init(lock_t *lock) {
+       int ret;
+       
+        if ((ret = pthread_key_create(&lock->count, NULL)))
+               return ret;
+
+       return pthread_rwlock_init(&lock->lock, NULL);
+}
+
+int lock_wrlock(lock_t *lock) {
+       int ret;
+       long count;
+
+       if ((count = (long)pthread_getspecific(lock->count)) > 0)
+               return pthread_setspecific(lock->count, (void *)(count + 1));
+
+       ret = pthread_rwlock_wrlock(&lock->lock);
+       if (!ret) {
+               ret = pthread_setspecific(lock->count, (void *)1);
+
+               if (ret)
+                       pthread_rwlock_unlock(&lock->lock);
+       }
+
+       return ret;
+}
+
+int lock_trywrlock(lock_t *lock) {
+        int ret;
+       long count;
+
+        if ((count = (long)pthread_getspecific(lock->count)) > 0)
+                return pthread_setspecific(lock->count, (void *)(count + 1));
+
+        ret = pthread_rwlock_trywrlock(&lock->lock);
+        if (!ret) {
+                ret = pthread_setspecific(lock->count, (void *)1);
+
+               if (ret)
+                       pthread_rwlock_unlock(&lock->lock);
+       }
+
+        return ret;
+}
+
+int lock_unlock(lock_t *lock) {
+       int ret;
+       long count;
+
+       if ((count = (long)pthread_getspecific(lock->count)) > 0) {
+               if (count > 1)
+                       return pthread_setspecific(lock->count,
+                                                  (void *)(count - 1));
+
+               ret = pthread_rwlock_unlock(&lock->lock);
+               if (ret)
+                       return ret;
+
+               return pthread_setspecific(lock->count, (void *)0);
+       }
+
+       return pthread_rwlock_unlock(&lock->lock);
+}
+
+int lock_destroy(lock_t *lock) {
+       int ret1, ret2;
+
+       ret1 = pthread_key_delete(lock->count);
+       ret2 = pthread_rwlock_destroy(&lock->lock);
+
+       if (ret2)
+               return ret2;
+
+       return ret1;
+}
diff --git a/citadel/lock.h b/citadel/lock.h
new file mode 100644 (file)
index 0000000..163c6b1
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * read/write locks.
+ * this is just a thin wrapper around POSIX rwlocks to provide recursive
+ * write-locking.
+ * by nathan bryant <nbryant@optonline.net>
+ *
+ * pthread_rwlock_* directly maps to lock_*, using lock_t instead of
+ * pthread_rwlock_t, except lock_init doesn't take an attribute parameter
+ *
+ * There is no initializer macro; use lock_init().
+ *
+ * $Id$
+ */
+
+#ifndef LOCK_H
+#define LOCK_H
+
+#include <pthread.h>
+
+typedef struct {
+       pthread_rwlock_t lock;
+       pthread_key_t count;
+} lock_t;
+
+/* The following are implemented in lock.c */
+
+int lock_init(lock_t *lock);
+int lock_wrlock(lock_t *lock);
+int lock_trywrlock(lock_t *lock);
+int lock_unlock(lock_t *lock);
+int lock_destroy(lock_t *lock);
+
+/* The remaining functions are actually implemented here as macros:
+
+int lock_rdlock(lock_t *lock);
+int lock_tryrdlock(lock_t *lock);
+
+*/
+
+#define lock_rdlock(lock) (pthread_rwlock_rdlock(&(lock)->lock))
+#define lock_tryrdlock(lock) (pthread_rwlock_tryrdlock(&(lock)->lock))
+
+#endif /* LOCK_H */