[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cygwin-patches
Subject:    [PATCH] Implement pthread_rwlocks
From:       Thomas Pfaff <tpfaff () gmx ! net>
Date:       2003-02-27 12:28:17
[Download RAW message or body]

This patch adds support for pthread_rwlocks. Attached are testcases from
the pthreads-win32 project.

The rwlock implementation follows the opengroup spec that it will
prefer writers among readers and check for deadlock conditions.

2003-02-27  Thomas Pfaff  <tpfaff@gmx.net>

	* cygwin.din: Add pthread_rwlock_destroy, pthread_rwlock_init,
	pthread_rwlock_rdlock, pthread_rwlock_tryrdlock,
	pthread_rwlock_wrlock, pthread_rwlock_trywrlock,
	pthread_rwlock_unlock, pthread_rwlockattr_init,
	pthread_rwlockattr_getpshared, pthread_rwlockattr_setpshared,
	and pthread_rwlockattr_destroy.
	* include/cygwin/version.h: Bump API minor number.
	* include/pthread.h (PTHREAD_RWLOCK_INITIALIZER): Define a
	reasonable value.
	Add prototypes for pthread_rwlock_destroy, pthread_rwlock_init,
	pthread_rwlock_rdlock, pthread_rwlock_tryrdlock,
	pthread_rwlock_wrlock, pthread_rwlock_trywrlock,
	pthread_rwlock_unlock, pthread_rwlockattr_init,
	pthread_rwlockattr_getpshared, pthread_rwlockattr_setpshared,
	and pthread_rwlockattr_destroy.
	* thread.h (PTHREAD_ONCE_MAGIC): Remove superflous semicolon.
	(PTHREAD_RWLOCK_MAGIC): New define.
	(PTHREAD_RWLOCKATTR_MAGIC): Ditto.
	(pthread_rwlockattr): New class.
	(pthread_rwlock): Ditto.
	(MTinterface::rwlocks): New member.
	(MTinterface::MTinterface): Initialize rwlocks.
	Add prototypes for __pthread_rwlock_destroy,
	__pthread_rwlock_wrlock, __pthread_rwlock_trywrlock,
	__pthread_rwlock_unlock, __pthread_rwlockattr_init,
	__pthread_rwlockattr_getpshared, __pthread_rwlockattr_setpshared,
	and __pthread_rwlockattr_destroy.
	* thread.cc (MTinterface::Init): Initialize rwlock internal mutex.
	(MTinterface::fixup_after_fork): Fixup rwlocks after fork.
	(pthread_rwlockattr::isGoodObject): Implement.
	(pthread_rwlockattr::pthread_rwlockattr): Ditto.
	(pthread_rwlockattr::~pthread_rwlockattr): Ditto.
	(pthread_rwlock::initMutex): Ditto.
	(pthread_rwlock::pthread_rwlock): Ditto.
	(pthread_rwlock::~pthread_rwlock): Ditto.
	(pthread_rwlock::RdLock): Ditto.
	(pthread_rwlock::TryRdLock): Ditto.
	(pthread_rwlock::WrLock): Ditto.
	(pthread_rwlock::TryWrLock): Ditto.
	(pthread_rwlock::UnLock): Ditto.
	(pthread_rwlock::addReader): Ditto.
	(pthread_rwlock::removeReader): Ditto.
	(pthread_rwlock::lookupReader): Ditto.
	(pthread_rwlock::RdLockCleanup): Ditto.
	(pthread_rwlock::WrLockCleanup): Ditto.
	(pthread_rwlock::fixup_after_fork): Ditto.
	(pthread_rwlock::isGoodObject): Ditto.
	(pthread_rwlock::isGoodInitializer): Ditto.
	(pthread_rwlock::isGoodInitializerOrObject): Ditto.
	(pthread_rwlock::isGoodInitializerOrBadObject): Ditto.
	(__pthread_rwlock_destroy): Ditto.
	(pthread_rwlock::init): Ditto.
	(__pthread_rwlock_rdlock): Ditto.
	(__pthread_rwlock_tryrdlock): Ditto.
	(__pthread_rwlock_wrlock): Ditto.
	(__pthread_rwlock_trywrlock): Ditto.
	(__pthread_rwlock_unlock): Ditto.
	(__pthread_rwlockattr_init): Ditto.
	(__pthread_rwlockattr_getpshared): Ditto.
	(__pthread_rwlockattr_setpshared): Ditto.
	(__pthread_rwlockattr_destroy): Ditto.
	* pthread.cc (pthread_rwlock_destroy): Implement:
	(pthread_rwlock_init): Ditto.
	(pthread_rwlock_rdlock): Ditto.
	(pthread_rwlock_tryrdlock): Ditto.
	(pthread_rwlock_wrlock): Ditto.
	(pthread_rwlock_trywrlock): Ditto.
	(pthread_rwlock_unlock): Ditto.
	(pthread_rwlockattr_init): Ditto.
	(pthread_rwlockattr_getpshared): Ditto.
	(pthread_rwlockattr_getpshared): Ditto.
	(pthread_rwlockattr_destroy): Ditto.


["rwlock.tar.gz" (APPLICATION/X-GZIP)]
["pthread_rwlock.patch" (TEXT/PLAIN)]

diff -urp src.old/winsup/cygwin/cygwin.din src/winsup/cygwin/cygwin.din
--- src.old/winsup/cygwin/cygwin.din	2003-02-27 10:14:31.000000000 +0100
+++ src/winsup/cygwin/cygwin.din	2003-02-27 10:18:35.000000000 +0100
@@ -932,6 +932,17 @@ pthread_mutexattr_setprotocol
 pthread_mutexattr_setpshared
 pthread_mutexattr_settype
 pthread_once
+pthread_rwlock_destroy
+pthread_rwlock_init
+pthread_rwlock_rdlock
+pthread_rwlock_tryrdlock
+pthread_rwlock_wrlock
+pthread_rwlock_trywrlock
+pthread_rwlock_unlock
+pthread_rwlockattr_init
+pthread_rwlockattr_getpshared
+pthread_rwlockattr_setpshared
+pthread_rwlockattr_destroy
 pthread_self
 pthread_setcancelstate
 pthread_setcanceltype
diff -urp src.old/winsup/cygwin/include/cygwin/version.h \
                src/winsup/cygwin/include/cygwin/version.h
--- src.old/winsup/cygwin/include/cygwin/version.h	2003-02-27 10:15:17.000000000 \
                +0100
+++ src/winsup/cygwin/include/cygwin/version.h	2003-02-27 10:19:22.000000000 +0100
@@ -185,12 +185,13 @@ details. */
 		  round roundf scalbln scalblnf sincos sincosf tgamma tgammaf
 		  truncf
        76: mallinfo
+       77: Export pthread_rwlock stuff
      */
 
      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 76
+#define CYGWIN_VERSION_API_MINOR 77
 
      /* There is also a compatibity version number associated with the
 	shared memory regions.  It is incremented when incompatible
diff -urp src.old/winsup/cygwin/include/pthread.h src/winsup/cygwin/include/pthread.h
--- src.old/winsup/cygwin/include/pthread.h	2003-02-27 09:25:49.000000000 +0100
+++ src/winsup/cygwin/include/pthread.h	2003-02-27 09:32:18.000000000 +0100
@@ -62,7 +62,7 @@ extern "C"
 #define PTHREAD_PRIO_PROTECT
 #define PTHREAD_PROCESS_SHARED 1
 #define PTHREAD_PROCESS_PRIVATE 0
-#define PTHREAD_RWLOCK_INITIALIZER
+#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t)22
 /* process is the default */
 #define PTHREAD_SCOPE_PROCESS 0
 #define PTHREAD_SCOPE_SYSTEM 1
@@ -161,6 +161,20 @@ int pthread_mutexattr_setprotocol (pthre
 int pthread_mutexattr_setpshared (pthread_mutexattr_t *, int);
 int pthread_mutexattr_settype (pthread_mutexattr_t *, int);
 
+/* RW Locks */
+int pthread_rwlock_destroy (pthread_rwlock_t *rwlock);
+int pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t \
*attr); +int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
+int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock);
+int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
+int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock);
+int pthread_rwlock_unlock (pthread_rwlock_t *rwlock);
+int pthread_rwlockattr_init (pthread_rwlockattr_t *rwlockattr);
+int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr,
+                                   int *pshared);
+int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared);
+int pthread_rwlockattr_destroy (pthread_rwlockattr_t *rwlockattr);
+
 int pthread_once (pthread_once_t *, void (*)(void));
 
 /* Concurrency levels - X/Open interface */
diff -urp src.old/winsup/cygwin/pthread.cc src/winsup/cygwin/pthread.cc
--- src.old/winsup/cygwin/pthread.cc	2003-01-10 18:55:03.000000000 +0100
+++ src/winsup/cygwin/pthread.cc	2003-02-27 09:32:18.000000000 +0100
@@ -388,6 +388,74 @@ pthread_condattr_setpshared (pthread_con
   return __pthread_condattr_setpshared (attr, pshared);
 }
 
+/* RW Locks */
+int
+pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
+{
+  return __pthread_rwlock_destroy (rwlock);
+}
+
+int
+pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
+{
+  return pthread_rwlock::init (rwlock, attr);
+}
+
+int
+pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
+{
+  return __pthread_rwlock_rdlock (rwlock);
+}
+
+int
+pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
+{
+  return __pthread_rwlock_tryrdlock (rwlock);
+}
+
+int
+pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
+{
+  return __pthread_rwlock_wrlock (rwlock);
+}
+
+int
+pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
+{
+  return __pthread_rwlock_trywrlock (rwlock);
+}
+
+int
+pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
+{
+  return __pthread_rwlock_unlock (rwlock);
+}
+
+int
+pthread_rwlockattr_init (pthread_rwlockattr_t *rwlockattr)
+{
+  return __pthread_rwlockattr_init (rwlockattr);
+}
+
+int
+pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr,
+                               int *pshared)
+{
+  return __pthread_rwlockattr_getpshared (attr, pshared);
+}
+
+int
+pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
+{
+  return __pthread_rwlockattr_setpshared (attr, pshared);
+}
+
+int
+pthread_rwlockattr_destroy (pthread_rwlockattr_t *rwlockattr)
+{
+  return __pthread_rwlockattr_destroy (rwlockattr);
+}
+
 /* Scheduling */
 
 int
diff -urp src.old/winsup/cygwin/thread.cc src/winsup/cygwin/thread.cc
--- src.old/winsup/cygwin/thread.cc	2003-02-27 09:31:55.000000000 +0100
+++ src/winsup/cygwin/thread.cc	2003-02-27 09:32:18.000000000 +0100
@@ -199,6 +199,7 @@ MTinterface::Init (int forked)
 
   pthread_mutex::initMutex ();
   pthread_cond::initMutex ();
+  pthread_rwlock::initMutex ();
 }
 
 void
@@ -230,6 +231,13 @@ MTinterface::fixup_after_fork (void)
       cond->fixup_after_fork ();
       cond = cond->next;
     }
+  pthread_rwlock *rwlock = rwlocks;
+  debug_printf ("rwlocks is %x",rwlocks);
+  while (rwlock)
+    {
+      rwlock->fixup_after_fork ();
+      rwlock = rwlock->next;
+    }
   semaphore *sem = semaphores;
   debug_printf ("semaphores is %x",semaphores);
   while (sem)
@@ -998,6 +1006,341 @@ pthread_cond::fixup_after_fork ()
     api_fatal ("pthread_cond::fixup_after_fork () failed to recreate win32 \
semaphore");  }
 
+bool
+pthread_rwlockattr::isGoodObject (pthread_rwlockattr_t const *attr)
+{
+  if (verifyable_object_isvalid (attr, PTHREAD_RWLOCKATTR_MAGIC) != VALID_OBJECT)
+    return false;
+  return true;
+}
+
+pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
+  (PTHREAD_RWLOCKATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE)
+{
+}
+
+pthread_rwlockattr::~pthread_rwlockattr ()
+{
+}
+
+/* This is used for rwlock creation protection within a single process only */
+nativeMutex NO_COPY pthread_rwlock::rwlockInitializationLock;
+
+/* We can only be called once.
+   TODO: (no rush) use a non copied memory section to
+   hold an initialization flag.  */
+void
+pthread_rwlock::initMutex ()
+{
+  if (!rwlockInitializationLock.init ())
+    api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer \
support."); +}
+
+pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) :
+  verifyable_object (PTHREAD_RWLOCK_MAGIC),
+  shared (0), waitingReaders (0), waitingWriters (0), writer (NULL),
+  readers (NULL), mtx (NULL), condReaders (NULL), condWriters (NULL),
+  next (NULL)
+{
+  pthread_mutex *verifyable_mutex_obj = &mtx;
+  pthread_cond *verifyable_cond_obj;
+
+  if (attr)
+    if (attr->shared != PTHREAD_PROCESS_PRIVATE)
+      {
+        magic = 0;
+        return;
+      }
+
+  if (!pthread_mutex::isGoodObject (&verifyable_mutex_obj))
+    {
+      thread_printf ("Internal rwlock mutex is not valid. this %p", this);
+      magic = 0;
+      return;
+    }
+  /* Change the mutex type to NORMAL to speed up mutex operations */
+  mtx.type = PTHREAD_MUTEX_NORMAL;
+
+  verifyable_cond_obj = &condReaders;
+  if (!pthread_cond::isGoodObject (&verifyable_cond_obj))
+    {
+      thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
+      magic = 0;
+      return;
+    }
+
+  verifyable_cond_obj = &condWriters;
+  if (!pthread_cond::isGoodObject (&verifyable_cond_obj))
+    {
+      thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
+      magic = 0;
+      return;
+    }
+
+
+  /* threadsafe addition is easy */
+  next = (pthread_rwlock *) InterlockedExchangePointer (&MT_INTERFACE->rwlocks, \
this); +}
+
+pthread_rwlock::~pthread_rwlock ()
+{
+  /* I'm not 100% sure the next bit is threadsafe. I think it is... */
+  if (MT_INTERFACE->rwlocks == this)
+    InterlockedExchangePointer (&MT_INTERFACE->rwlocks, this->next);
+  else
+    {
+      pthread_rwlock *temprwlock = MT_INTERFACE->rwlocks;
+      while (temprwlock->next && temprwlock->next != this)
+	temprwlock = temprwlock->next;
+      /* but there may be a race between the loop above and this statement */
+      InterlockedExchangePointer (&temprwlock->next, this->next);
+    }
+}
+
+int
+pthread_rwlock::RdLock ()
+{
+  int result = 0;
+  struct RWLOCK_READER *reader;
+  pthread_t self = pthread::self ();
+
+  mtx.Lock ();
+
+  if (lookupReader (self))
+    {
+      result = EDEADLK;
+      goto DONE;
+    }
+
+  reader = new struct RWLOCK_READER;
+  if (!reader)
+    {
+      result = EAGAIN;
+      goto DONE;
+    }
+
+  while (writer || waitingWriters)
+    {  
+      pthread_cleanup_push (pthread_rwlock::RdLockCleanup, this);
+
+      ++waitingReaders;
+      condReaders.Wait (&mtx);
+      --waitingReaders;
+
+      pthread_cleanup_pop (0);
+    }
+
+  reader->thread = self;
+  addReader (reader);
+
+ DONE:
+  mtx.UnLock ();
+
+  return result;
+}
+
+int
+pthread_rwlock::TryRdLock ()
+{
+  int result = 0;
+  pthread_t self = pthread::self ();
+
+  mtx.Lock ();
+
+  if (writer || waitingWriters || lookupReader (self))
+    result = EBUSY;
+  else
+    {
+      struct RWLOCK_READER *reader = new struct RWLOCK_READER;
+      if (reader)
+        {
+          reader->thread = self;
+          addReader (reader);
+        }
+      else
+        result = EAGAIN;
+    }
+    
+  mtx.UnLock ();
+
+  return result;
+}
+
+int
+pthread_rwlock::WrLock ()
+{
+  int result = 0;
+  pthread_t self = pthread::self ();
+
+  mtx.Lock ();
+
+  if (writer == self || lookupReader (self))
+    {
+      result = EDEADLK;
+      goto DONE;
+    }
+
+  while (writer || readers)
+    {  
+      pthread_cleanup_push (pthread_rwlock::WrLockCleanup, this);
+
+      ++waitingWriters;
+      condWriters.Wait (&mtx);
+      --waitingWriters;
+
+      pthread_cleanup_pop (0);
+    }
+
+  writer = self;
+
+ DONE:
+  mtx.UnLock ();
+
+  return result;
+}
+
+int
+pthread_rwlock::TryWrLock ()
+{
+  int result = 0;
+  pthread_t self = pthread::self ();
+
+  mtx.Lock ();
+
+  if (writer || readers)
+    result = EBUSY;
+  else
+    writer = self;
+    
+  mtx.UnLock ();
+
+  return result;
+}
+
+int
+pthread_rwlock::UnLock ()
+{
+  int result = 0;
+  pthread_t self = pthread::self ();
+
+  mtx.Lock ();
+
+  if (writer)
+    {
+      if (writer != self)
+        {
+          result = EPERM;
+          goto DONE;
+        }
+
+      writer = NULL;
+    }
+  else
+    {
+      struct RWLOCK_READER *reader = lookupReader (self);
+
+      if (!reader)
+        {
+          result = EPERM;
+          goto DONE;
+        }
+
+      removeReader (reader);
+      delete reader;
+    }
+
+  if (waitingWriters)
+    {
+      if (!readers)
+        condWriters.UnBlock (false);
+    }
+  else if (waitingReaders)
+    condReaders.UnBlock (true);
+
+ DONE:
+  mtx.UnLock ();
+
+  return result;
+}
+
+void
+pthread_rwlock::addReader (struct RWLOCK_READER *rd)
+{
+  rd->next = (struct RWLOCK_READER *)
+    InterlockedExchangePointer (&readers, rd);
+}
+
+void
+pthread_rwlock::removeReader (struct RWLOCK_READER *rd)
+{
+  if (readers == rd)
+    InterlockedExchangePointer (&readers, rd->next);
+  else
+    {
+      struct RWLOCK_READER *temp = readers;
+      while (temp->next && temp->next != rd)
+	temp = temp->next;
+      /* but there may be a race between the loop above and this statement */
+      InterlockedExchangePointer (&temp->next, rd->next);
+    }
+}
+
+struct pthread_rwlock::RWLOCK_READER *
+pthread_rwlock::lookupReader (pthread_t thread)
+{
+  struct RWLOCK_READER *temp = readers;
+
+  while (temp && temp->thread != thread)
+    temp = temp->next;
+
+  return temp;
+}
+
+void
+pthread_rwlock::RdLockCleanup (void *arg)
+{
+  pthread_rwlock *rwlock = (pthread_rwlock *) arg;
+
+  --(rwlock->waitingReaders);
+  rwlock->mtx.UnLock ();
+}
+
+void
+pthread_rwlock::WrLockCleanup (void *arg)
+{
+  pthread_rwlock *rwlock = (pthread_rwlock *) arg;
+
+  --(rwlock->waitingWriters);
+  rwlock->mtx.UnLock ();
+}
+
+void
+pthread_rwlock::fixup_after_fork ()
+{
+  pthread_t self = pthread::self ();
+  struct RWLOCK_READER **temp = &readers;
+
+  waitingReaders = 0;
+  waitingWriters = 0;
+
+  /* Unlock eventually locked mutex */
+  mtx.UnLock ();
+  /*
+   * Remove all readers except self
+   */
+  while (*temp)
+    {
+      if ((*temp)->thread == self)
+        temp = &((*temp)->next);
+      else
+        {
+          struct RWLOCK_READER *cur = *temp;
+          *temp = (*temp)->next;
+          delete cur;
+        }
+    }
+}
+
 /* pthread_key */
 /* static members */
 /* This stores pthread_key information across fork() boundaries */
@@ -2292,6 +2635,191 @@ __pthread_condattr_destroy (pthread_cond
   return 0;
 }
 
+/* RW locks */
+bool
+pthread_rwlock::isGoodObject (pthread_rwlock_t const *rwlock)
+{
+  if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC) != VALID_OBJECT)
+    return false;
+  return true;
+}
+
+bool
+pthread_rwlock::isGoodInitializer (pthread_rwlock_t const *rwlock)
+{
+  if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, \
PTHREAD_RWLOCK_INITIALIZER) != VALID_STATIC_OBJECT) +    return false;
+  return true;
+}
+
+bool
+pthread_rwlock::isGoodInitializerOrObject (pthread_rwlock_t const *rwlock)
+{
+  if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, \
PTHREAD_RWLOCK_INITIALIZER) == INVALID_OBJECT) +    return false;
+  return true;
+}
+
+bool
+pthread_rwlock::isGoodInitializerOrBadObject (pthread_rwlock_t const *rwlock)
+{
+  verifyable_object_state objectState = verifyable_object_isvalid (rwlock, \
PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER); +  if (objectState == \
VALID_OBJECT) +	return false;
+  return true;
+}
+
+int
+__pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
+{
+  if (pthread_rwlock::isGoodInitializer (rwlock))
+    return 0;
+  if (!pthread_rwlock::isGoodObject (rwlock))
+    return EINVAL;
+
+  if ((*rwlock)->writer || (*rwlock)->readers ||
+      (*rwlock)->waitingReaders || (*rwlock)->waitingWriters)
+    return EBUSY;
+
+  delete (*rwlock);
+  *rwlock = NULL;
+
+  return 0;
+}
+
+int
+pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
+{
+  if (attr && !pthread_rwlockattr::isGoodObject (attr))
+    return EINVAL;
+  if (!rwlockInitializationLock.lock ())
+    return EINVAL;
+
+  if (!isGoodInitializerOrBadObject (rwlock))
+    {
+      rwlockInitializationLock.unlock ();
+      return EBUSY;
+    }
+
+  *rwlock = new pthread_rwlock (attr ? (*attr) : NULL);
+  if (!isGoodObject (rwlock))
+    {
+      delete (*rwlock);
+      *rwlock = NULL;
+      rwlockInitializationLock.unlock ();
+      return EAGAIN;
+    }
+  rwlockInitializationLock.unlock ();
+  return 0;
+}
+
+int
+__pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
+{
+  pthread_testcancel ();
+
+  if (pthread_rwlock::isGoodInitializer (rwlock))
+    pthread_rwlock::init (rwlock, NULL);
+  if (!pthread_rwlock::isGoodObject (rwlock))
+    return EINVAL;
+
+  return (*rwlock)->RdLock ();
+}
+
+int
+__pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
+{
+  if (pthread_rwlock::isGoodInitializer (rwlock))
+    pthread_rwlock::init (rwlock, NULL);
+  if (!pthread_rwlock::isGoodObject (rwlock))
+    return EINVAL;
+
+  return (*rwlock)->TryRdLock ();
+}
+
+int
+__pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
+{
+  pthread_testcancel ();
+
+  if (pthread_rwlock::isGoodInitializer (rwlock))
+    pthread_rwlock::init (rwlock, NULL);
+  if (!pthread_rwlock::isGoodObject (rwlock))
+    return EINVAL;
+
+  return (*rwlock)->WrLock ();
+}
+
+int
+__pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
+{
+  if (pthread_rwlock::isGoodInitializer (rwlock))
+    pthread_rwlock::init (rwlock, NULL);
+  if (!pthread_rwlock::isGoodObject (rwlock))
+    return EINVAL;
+
+  return (*rwlock)->TryWrLock ();
+}
+
+int
+__pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
+{
+  if (pthread_rwlock::isGoodInitializer (rwlock))
+    return 0;
+  if (!pthread_rwlock::isGoodObject (rwlock))
+    return EINVAL;
+
+  return (*rwlock)->UnLock ();
+}
+
+int
+__pthread_rwlockattr_init (pthread_rwlockattr_t *rwlockattr)
+{
+  if (check_valid_pointer (rwlockattr))
+    return EINVAL;
+  *rwlockattr = new pthread_rwlockattr;
+  if (!pthread_rwlockattr::isGoodObject (rwlockattr))
+    {
+      delete (*rwlockattr);
+      *rwlockattr = NULL;
+      return EAGAIN;
+    }
+  return 0;
+}
+
+int
+__pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared)
+{
+  if (!pthread_rwlockattr::isGoodObject (attr))
+    return EINVAL;
+  *pshared = (*attr)->shared;
+  return 0;
+}
+
+int
+__pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
+{
+  if (!pthread_rwlockattr::isGoodObject (attr))
+    return EINVAL;
+  if ((pshared < 0) || (pshared > 1))
+    return EINVAL;
+  /* shared rwlock vars not currently supported */
+  if (pshared != PTHREAD_PROCESS_PRIVATE)
+    return EINVAL;
+  (*attr)->shared = pshared;
+  return 0;
+}
+
+int
+__pthread_rwlockattr_destroy (pthread_rwlockattr_t *rwlockattr)
+{
+  if (!pthread_rwlockattr::isGoodObject (rwlockattr))
+    return EINVAL;
+  delete (*rwlockattr);
+  *rwlockattr = NULL;
+  return 0;
+}
+
 /* Thread signal */
 int
 __pthread_kill (pthread_t thread, int sig)
diff -urp src.old/winsup/cygwin/thread.h src/winsup/cygwin/thread.h
--- src.old/winsup/cygwin/thread.h	2003-02-27 09:31:55.000000000 +0100
+++ src/winsup/cygwin/thread.h	2003-02-27 09:32:18.000000000 +0100
@@ -163,6 +163,8 @@ private:
 #define PTHREAD_CONDATTR_MAGIC PTHREAD_MAGIC+6
 #define SEM_MAGIC PTHREAD_MAGIC+7
 #define PTHREAD_ONCE_MAGIC PTHREAD_MAGIC+8
+#define PTHREAD_RWLOCK_MAGIC PTHREAD_MAGIC+9
+#define PTHREAD_RWLOCKATTR_MAGIC PTHREAD_MAGIC+10
 
 #define MUTEX_OWNER_ANONYMOUS        ((pthread_t) -1)
 
@@ -517,6 +519,67 @@ private:
   static nativeMutex condInitializationLock;
 };
 
+class pthread_rwlockattr:public verifyable_object
+{
+public:
+  static bool isGoodObject(pthread_rwlockattr_t const *);
+  int shared;
+
+  pthread_rwlockattr ();
+  ~pthread_rwlockattr ();
+};
+
+class pthread_rwlock:public verifyable_object
+{
+public:
+  static bool isGoodObject (pthread_rwlock_t const *);
+  static bool isGoodInitializer (pthread_rwlock_t const *);
+  static bool isGoodInitializerOrObject (pthread_rwlock_t const *);
+  static bool isGoodInitializerOrBadObject (pthread_rwlock_t const *);
+  static void initMutex ();
+  static int init (pthread_rwlock_t *, const pthread_rwlockattr_t *);
+
+  int shared;
+
+  unsigned long waitingReaders;
+  unsigned long waitingWriters;
+  pthread_t writer;
+  struct RWLOCK_READER
+  {
+    struct RWLOCK_READER *next;
+    pthread_t thread;
+  } *readers;
+
+  int RdLock ();
+  int TryRdLock ();
+
+  int WrLock ();
+  int TryWrLock ();
+
+  int UnLock ();
+
+  pthread_mutex mtx;
+  pthread_cond condReaders;
+  pthread_cond condWriters;
+
+  class pthread_rwlock * next;
+
+  void fixup_after_fork ();
+
+  pthread_rwlock (pthread_rwlockattr *);
+  ~pthread_rwlock ();
+
+private:
+  void addReader (struct RWLOCK_READER *rd);
+  void removeReader (struct RWLOCK_READER *rd);
+  struct RWLOCK_READER *lookupReader (pthread_t thread);
+
+  static void RdLockCleanup (void *arg);
+  static void WrLockCleanup (void *arg);
+
+  static nativeMutex rwlockInitializationLock;
+};
+
 class pthread_once
 {
 public:
@@ -574,6 +637,7 @@ public:
   // lists of pthread objects. USE THREADSAFE INSERTS AND DELETES.
   class pthread_mutex * mutexs;
   class pthread_cond  * conds;
+  class pthread_rwlock * rwlocks;
   class semaphore     * semaphores;
 
   pthread_key reent_key;
@@ -586,7 +650,7 @@ public:
   MTinterface () :
     concurrency (0), threadcount (1),
     pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL),
-    mutexs (NULL), conds (NULL), semaphores (NULL),
+    mutexs (NULL), conds (NULL), rwlocks (NULL), semaphores (NULL),
     reent_key (NULL), thread_self_key (NULL)
   {
   }
@@ -632,6 +696,19 @@ int __pthread_condattr_getpshared (const
 				   int *pshared);
 int __pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared);
 
+/* RW locks */
+int __pthread_rwlock_destroy (pthread_rwlock_t *rwlock);
+int __pthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
+int __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock);
+int __pthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
+int __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock);
+int __pthread_rwlock_unlock (pthread_rwlock_t *rwlock);
+int __pthread_rwlockattr_init (pthread_rwlockattr_t *rwlockattr);
+int __pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr,
+                                     int *pshared);
+int __pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared);
+int __pthread_rwlockattr_destroy (pthread_rwlockattr_t *rwlockattr);
+
 /* Thread signal */
 int __pthread_kill (pthread_t thread, int sig);
 int __pthread_sigmask (int operation, const sigset_t * set,



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic