windows-pthread-rwlock-20081017
authorJeffrey Altman <jaltman@your-file-system.com>
Fri, 17 Oct 2008 21:24:19 +0000 (21:24 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 17 Oct 2008 21:24:19 +0000 (21:24 +0000)
LICENSE MIT

Adds pthread rwlock support to the library.

src/WINNT/pthread/pthread.c
src/WINNT/pthread/pthread.def
src/WINNT/pthread/pthread.h

index 24949a2..739c7b9 100644 (file)
@@ -33,6 +33,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <process.h>
 #include <errno.h>
 #include <sys/timeb.h>
 
@@ -213,6 +214,201 @@ int pthread_mutex_destroy(pthread_mutex_t *mp) {
     return rc;
 }
 
+int pthread_rwlock_destroy(pthread_rwlock_t *rwp)
+{
+    int rc = 0;
+
+    if (rwp != NULL) {
+        pthread_mutex_destroy(&rwp->read_access_completion_mutex);
+        pthread_mutex_destroy(&rwp->write_access_mutex);
+        pthread_cond_destroy(&rwp->read_access_completion_wait);
+    } else {
+#ifdef PTHREAD_DEBUG
+        DebugBreak();
+#endif
+       rc = EINVAL;
+    }
+
+    return rc;
+}
+
+int pthread_rwlock_init(pthread_rwlock_t *rwp, const pthread_rwlockattr_t *attr)
+{
+    int rc = 0;
+
+    if (rwp == NULL)
+        return EINVAL;
+
+    rwp->readers = 0;
+
+    rc = pthread_mutex_init(&rwp->write_access_mutex, NULL);
+    if (rc)
+        return rc;
+
+    rc = pthread_mutex_init(&rwp->read_access_completion_mutex, NULL);
+    if (rc)
+        goto error1;
+
+    rc = pthread_cond_init(&rwp->read_access_completion_wait, NULL);
+    if (rc == 0)
+        return 0;       /* success */
+
+    pthread_mutex_destroy(&rwp->read_access_completion_mutex);
+
+  error1:
+    pthread_mutex_destroy(&rwp->write_access_mutex);
+
+    return rc;
+}
+
+int pthread_rwlock_wrlock(pthread_rwlock_t *rwp)
+{
+    int rc = 0;
+
+    if (rwp == NULL)
+        return EINVAL;
+
+    if ((rc = pthread_mutex_lock(&rwp->write_access_mutex)) != 0)
+        return rc;
+
+    if ((rc = pthread_mutex_lock(&rwp->read_access_completion_mutex)) != 0)
+    {
+        pthread_mutex_unlock(&rwp->write_access_mutex);
+        return rc;
+    }
+
+    while (rc == 0 && rwp->readers > 0) {
+        rc = pthread_cond_wait( &rwp->read_access_completion_wait, 
+                                &rwp->read_access_completion_mutex);
+    }
+
+    pthread_mutex_unlock(&rwp->read_access_completion_mutex);
+
+    if (rc)
+        pthread_mutex_unlock(&rwp->write_access_mutex);
+
+    return rc;
+}
+
+int pthread_rwlock_rdlock(pthread_rwlock_t *rwp)
+{
+    int rc = 0;
+
+    if (rwp == NULL)
+        return EINVAL;
+
+    if ((rc = pthread_mutex_lock(&rwp->write_access_mutex)) != 0)
+        return rc;
+
+    if ((rc = pthread_mutex_lock(&rwp->read_access_completion_mutex)) != 0)
+    {
+        pthread_mutex_unlock(&rwp->write_access_mutex);
+        return rc;
+    }
+
+    rwp->readers++;
+
+    pthread_mutex_unlock(&rwp->read_access_completion_mutex);
+
+    pthread_mutex_unlock(&rwp->write_access_mutex);
+
+    return rc;
+        
+}
+
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwp)
+{
+    int rc = 0;
+
+    if (rwp == NULL)
+        return EINVAL;
+
+    if ((rc = pthread_mutex_trylock(&rwp->write_access_mutex)) != 0)
+        return rc;
+
+    if ((rc = pthread_mutex_trylock(&rwp->read_access_completion_mutex)) != 0) {
+        pthread_mutex_unlock(&rwp->write_access_mutex);
+        return rc;
+    }
+
+    rwp->readers++;
+
+    pthread_mutex_unlock(&rwp->read_access_completion_mutex);
+
+    pthread_mutex_unlock(&rwp->write_access_mutex);
+
+    return rc;
+}
+
+int pthread_rwlock_trywrlock(pthread_rwlock_t *rwp)
+{
+    int rc = 0;
+
+    if (rwp == NULL)
+        return EINVAL;
+
+    if ((rc = pthread_mutex_trylock(&rwp->write_access_mutex)) != 0)
+        return rc;
+
+    if ((rc = pthread_mutex_trylock(&rwp->read_access_completion_mutex)) != 0)
+    {
+        pthread_mutex_unlock(&rwp->write_access_mutex);
+        return rc;
+    }
+
+    if (rwp->readers > 0)
+        rc = EBUSY;
+
+    pthread_mutex_unlock(&rwp->read_access_completion_mutex);
+
+    if (rc)
+        pthread_mutex_unlock(&rwp->write_access_mutex);
+
+    return rc;
+}
+
+int pthread_rwlock_unlock(pthread_rwlock_t *rwp)
+{
+    int rc = 0;
+
+    if (rwp == NULL)
+        return EINVAL;
+
+    rc = pthread_mutex_trylock(&rwp->write_access_mutex);
+    if (rc != EDEADLK)
+    {
+        /* unlock a read lock */
+        if (rc == 0)
+            pthread_mutex_unlock(&rwp->write_access_mutex);
+        
+        if ((rc = pthread_mutex_lock(&rwp->read_access_completion_mutex)) != 0)
+        {
+            pthread_mutex_unlock(&rwp->write_access_mutex);
+            return rc;
+        }
+
+        if (rwp->readers <= 0)
+        {
+            rc = EINVAL;
+        }
+        else 
+        {
+            if (--rwp->readers == 0) 
+                pthread_cond_broadcast(&rwp->read_access_completion_wait);
+        }
+
+        pthread_mutex_unlock(&rwp->read_access_completion_mutex);
+    } 
+    else
+    {
+        /* unlock a write lock */
+        rc = pthread_mutex_unlock(&rwp->write_access_mutex);
+    }
+
+    return rc;
+}
+
+
 /*
  * keys is used to keep track of which keys are currently
  * in use by the threads library.  pthread_tsd_mutex is used
index 45e33d7..387c1bf 100644 (file)
@@ -26,3 +26,10 @@ EXPORTS
        pthread_attr_setdetachstate                     @24
        pthread_exit                                    @25
        DllMain                                         @26
+        pthread_rwlock_destroy                          @27
+        pthread_rwlock_init                             @28
+        pthread_rwlock_rdlock                           @29
+        pthread_rwlock_wrlock                           @30
+        pthread_rwlock_tryrdlock                        @31
+        pthread_rwlock_trywrlock                        @32
+        pthread_rwlock_unlock                           @33
index d0dc019..dbd39c5 100644 (file)
@@ -31,6 +31,7 @@ typedef struct {
 
 typedef int pthread_condattr_t;
 typedef int pthread_mutexattr_t;
+typedef int pthread_rwlockattr_t;
 typedef int pthread_key_t;
 typedef void *pthread_t;
 
@@ -56,6 +57,13 @@ typedef struct {
     struct rx_queue waiting_threads;
 } pthread_cond_t;
 
+typedef struct {
+    pthread_mutex_t write_access_mutex;
+    pthread_mutex_t read_access_completion_mutex;
+    pthread_cond_t  read_access_completion_wait;
+    int readers;
+} pthread_rwlock_t;
+
 #define PTHREAD_ONCE_INIT {0,1}
 
 extern int pthread_cond_broadcast(pthread_cond_t *cond);
@@ -69,11 +77,21 @@ extern void *pthread_getspecific(pthread_key_t key);
 extern int pthread_join(pthread_t target_thread, void **status);
 extern int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value));
 extern int pthread_key_delete(pthread_key_t key);
+
 extern int pthread_mutex_destroy(pthread_mutex_t *mp);
 extern int pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *attr);
 extern int pthread_mutex_lock(pthread_mutex_t *mp);
 extern int pthread_mutex_trylock(pthread_mutex_t *mp);
 extern int pthread_mutex_unlock(pthread_mutex_t *mp);
+
+extern int pthread_rwlock_destroy(pthread_rwlock_t *rwp);
+extern int pthread_rwlock_init(pthread_rwlock_t *rwp, const pthread_rwlockattr_t *attr);
+extern int pthread_rwlock_rdlock(pthread_rwlock_t *rwp);
+extern int pthread_rwlock_wrlock(pthread_rwlock_t *rwp);
+extern int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwp);
+extern int pthread_rwlock_trywrlock(pthread_rwlock_t *rwp);
+extern int pthread_rwlock_unlock(pthread_rwlock_t *rwp);
+
 extern int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
 extern int pthread_setspecific(pthread_key_t key, const void *value);
 extern pthread_t pthread_self(void);