* 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.
This commit is contained in:
parent
5df1410028
commit
00d296a3f9
@ -1,3 +1,62 @@
|
|||||||
|
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>
|
2003-03-18 Thomas Pfaff <tpfaff@gmx.net>
|
||||||
|
|
||||||
* thread.h (pthread_cond::ExitingWait): Remove.
|
* thread.h (pthread_cond::ExitingWait): Remove.
|
||||||
|
@ -954,6 +954,17 @@ pthread_mutexattr_setprotocol
|
|||||||
pthread_mutexattr_setpshared
|
pthread_mutexattr_setpshared
|
||||||
pthread_mutexattr_settype
|
pthread_mutexattr_settype
|
||||||
pthread_once
|
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_self
|
||||||
pthread_setcancelstate
|
pthread_setcancelstate
|
||||||
pthread_setcanceltype
|
pthread_setcanceltype
|
||||||
|
@ -192,12 +192,13 @@ details. */
|
|||||||
aclsort32 acltomode32 acltopbits32 acltotext32 facl32
|
aclsort32 acltomode32 acltopbits32 acltotext32 facl32
|
||||||
fgetpos64 fopen64 freopen64 fseeko64 fsetpos64 ftello64
|
fgetpos64 fopen64 freopen64 fseeko64 fsetpos64 ftello64
|
||||||
_open64 _lseek64 _fstat64 _stat64 mknod32
|
_open64 _lseek64 _fstat64 _stat64 mknod32
|
||||||
|
80: Export pthread_rwlock stuff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
||||||
|
|
||||||
#define CYGWIN_VERSION_API_MAJOR 0
|
#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
|
/* There is also a compatibity version number associated with the
|
||||||
shared memory regions. It is incremented when incompatible
|
shared memory regions. It is incremented when incompatible
|
||||||
|
@ -62,7 +62,7 @@ extern "C"
|
|||||||
#define PTHREAD_PRIO_PROTECT
|
#define PTHREAD_PRIO_PROTECT
|
||||||
#define PTHREAD_PROCESS_SHARED 1
|
#define PTHREAD_PROCESS_SHARED 1
|
||||||
#define PTHREAD_PROCESS_PRIVATE 0
|
#define PTHREAD_PROCESS_PRIVATE 0
|
||||||
#define PTHREAD_RWLOCK_INITIALIZER
|
#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t)22
|
||||||
/* process is the default */
|
/* process is the default */
|
||||||
#define PTHREAD_SCOPE_PROCESS 0
|
#define PTHREAD_SCOPE_PROCESS 0
|
||||||
#define PTHREAD_SCOPE_SYSTEM 1
|
#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_setpshared (pthread_mutexattr_t *, int);
|
||||||
int pthread_mutexattr_settype (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));
|
int pthread_once (pthread_once_t *, void (*)(void));
|
||||||
|
|
||||||
/* Concurrency levels - X/Open interface */
|
/* Concurrency levels - X/Open interface */
|
||||||
|
@ -388,6 +388,74 @@ pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared)
|
|||||||
return __pthread_condattr_setpshared (attr, 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 */
|
/* Scheduling */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -199,6 +199,7 @@ MTinterface::Init (int forked)
|
|||||||
|
|
||||||
pthread_mutex::initMutex ();
|
pthread_mutex::initMutex ();
|
||||||
pthread_cond::initMutex ();
|
pthread_cond::initMutex ();
|
||||||
|
pthread_rwlock::initMutex ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -230,6 +231,13 @@ MTinterface::fixup_after_fork (void)
|
|||||||
cond->fixup_after_fork ();
|
cond->fixup_after_fork ();
|
||||||
cond = cond->next;
|
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;
|
semaphore *sem = semaphores;
|
||||||
debug_printf ("semaphores is %x",semaphores);
|
debug_printf ("semaphores is %x",semaphores);
|
||||||
while (sem)
|
while (sem)
|
||||||
@ -998,6 +1006,341 @@ pthread_cond::fixup_after_fork ()
|
|||||||
api_fatal ("pthread_cond::fixup_after_fork () failed to recreate win32 semaphore");
|
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 */
|
/* pthread_key */
|
||||||
/* static members */
|
/* static members */
|
||||||
/* This stores pthread_key information across fork() boundaries */
|
/* This stores pthread_key information across fork() boundaries */
|
||||||
@ -2292,6 +2635,191 @@ __pthread_condattr_destroy (pthread_condattr_t *condattr)
|
|||||||
return 0;
|
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 */
|
/* Thread signal */
|
||||||
int
|
int
|
||||||
__pthread_kill (pthread_t thread, int sig)
|
__pthread_kill (pthread_t thread, int sig)
|
||||||
|
@ -163,6 +163,8 @@ private:
|
|||||||
#define PTHREAD_CONDATTR_MAGIC PTHREAD_MAGIC+6
|
#define PTHREAD_CONDATTR_MAGIC PTHREAD_MAGIC+6
|
||||||
#define SEM_MAGIC PTHREAD_MAGIC+7
|
#define SEM_MAGIC PTHREAD_MAGIC+7
|
||||||
#define PTHREAD_ONCE_MAGIC PTHREAD_MAGIC+8
|
#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)
|
#define MUTEX_OWNER_ANONYMOUS ((pthread_t) -1)
|
||||||
|
|
||||||
@ -517,6 +519,67 @@ private:
|
|||||||
static nativeMutex condInitializationLock;
|
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
|
class pthread_once
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -574,6 +637,7 @@ public:
|
|||||||
// lists of pthread objects. USE THREADSAFE INSERTS AND DELETES.
|
// lists of pthread objects. USE THREADSAFE INSERTS AND DELETES.
|
||||||
class pthread_mutex * mutexs;
|
class pthread_mutex * mutexs;
|
||||||
class pthread_cond * conds;
|
class pthread_cond * conds;
|
||||||
|
class pthread_rwlock * rwlocks;
|
||||||
class semaphore * semaphores;
|
class semaphore * semaphores;
|
||||||
|
|
||||||
pthread_key reent_key;
|
pthread_key reent_key;
|
||||||
@ -586,7 +650,7 @@ public:
|
|||||||
MTinterface () :
|
MTinterface () :
|
||||||
concurrency (0), threadcount (1),
|
concurrency (0), threadcount (1),
|
||||||
pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL),
|
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)
|
reent_key (NULL), thread_self_key (NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -632,6 +696,19 @@ int __pthread_condattr_getpshared (const pthread_condattr_t * attr,
|
|||||||
int *pshared);
|
int *pshared);
|
||||||
int __pthread_condattr_setpshared (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 */
|
/* Thread signal */
|
||||||
int __pthread_kill (pthread_t thread, int sig);
|
int __pthread_kill (pthread_t thread, int sig);
|
||||||
int __pthread_sigmask (int operation, const sigset_t * set,
|
int __pthread_sigmask (int operation, const sigset_t * set,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user