Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorThomas Pfaff <tpfaff@gmx.net>2003-03-18 23:01:07 +0300
committerThomas Pfaff <tpfaff@gmx.net>2003-03-18 23:01:07 +0300
commit00d296a3f9528ab64f6efc3e9c45bbb823db4227 (patch)
tree8d1aad11ba90e0cccc2ffe29b0f48843a61f9a78 /winsup
parent5df14100282d6a302f44e0b06608b5d04aade3c1 (diff)
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog59
-rw-r--r--winsup/cygwin/cygwin.din11
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/include/pthread.h16
-rw-r--r--winsup/cygwin/pthread.cc68
-rw-r--r--winsup/cygwin/thread.cc528
-rw-r--r--winsup/cygwin/thread.h79
7 files changed, 761 insertions, 3 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 6903aaf64..af71f9bdd 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,64 @@
2003-03-18 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.
+
+2003-03-18 Thomas Pfaff <tpfaff@gmx.net>
+
* thread.h (pthread_cond::ExitingWait): Remove.
(pthread_cond::mutex): Ditto.
(pthread_cond::cond_access): Ditto.
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 131192376..df78b04b8 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -954,6 +954,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 --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index d667d8207..60cfd10b4 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -192,12 +192,13 @@ details. */
aclsort32 acltomode32 acltopbits32 acltotext32 facl32
fgetpos64 fopen64 freopen64 fseeko64 fsetpos64 ftello64
_open64 _lseek64 _fstat64 _stat64 mknod32
+ 80: 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 79
+#define CYGWIN_VERSION_API_MINOR 80
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h
index 7ac683487..5f12cbbda 100644
--- a/winsup/cygwin/include/pthread.h
+++ b/winsup/cygwin/include/pthread.h
@@ -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 (pthread_mutexattr_t *, int);
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 --git a/winsup/cygwin/pthread.cc b/winsup/cygwin/pthread.cc
index 2a15a3b63..8d629a969 100644
--- a/winsup/cygwin/pthread.cc
+++ b/winsup/cygwin/pthread.cc
@@ -388,6 +388,74 @@ pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared)
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 --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 125e7d38f..ab8214e1c 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -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_condattr_t *condattr)
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 --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 1f1afa19c..58be95c7e 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -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 pthread_condattr_t * attr,
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,