Sun May 6 17:05:00 2001 Robert Collins <rbtcollins@hotmail.com>
* thread.h (pthread_cond): New element cond_access to allow atomic broadcasts. * thread.cc (pthread_cond::pthread_cond): Initialise cond_access. (pthread_cond::~pthread_cond): Destroy cond_access. (pthread_cond::Broadcast): Use cond_access. (pthread_cond::Signal): Use cond_access. (pthread_cond_wait): Use cond_access. (pthread_cond_timedwait): Use cond_access.
This commit is contained in:
parent
2bfb966544
commit
68ebd3f6e2
|
@ -1,3 +1,12 @@
|
||||||
|
Sun May 6 17:05:00 2001 Robert Collins <rbtcollins@hotmail.com>
|
||||||
|
* thread.h (pthread_cond): New element cond_access to allow atomic broadcasts.
|
||||||
|
* thread.cc (pthread_cond::pthread_cond): Initialise cond_access.
|
||||||
|
(pthread_cond::~pthread_cond): Destroy cond_access.
|
||||||
|
(pthread_cond::Broadcast): Use cond_access.
|
||||||
|
(pthread_cond::Signal): Use cond_access.
|
||||||
|
(pthread_cond_wait): Use cond_access.
|
||||||
|
(pthread_cond_timedwait): Use cond_access.
|
||||||
|
|
||||||
Sun May 6 11:55:40 2001 Christopher Faylor <cgf@cygnus.com>
|
Sun May 6 11:55:40 2001 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
* string.h (cygwin_strchr): Make 'static inline' so that things will
|
* string.h (cygwin_strchr): Make 'static inline' so that things will
|
||||||
|
|
|
@ -386,6 +386,7 @@ pthread_condattr::~pthread_condattr ()
|
||||||
|
|
||||||
pthread_cond::pthread_cond (pthread_condattr * attr):verifyable_object (PTHREAD_COND_MAGIC)
|
pthread_cond::pthread_cond (pthread_condattr * attr):verifyable_object (PTHREAD_COND_MAGIC)
|
||||||
{
|
{
|
||||||
|
int temperr;
|
||||||
this->shared = attr ? attr->shared : PTHREAD_PROCESS_PRIVATE;
|
this->shared = attr ? attr->shared : PTHREAD_PROCESS_PRIVATE;
|
||||||
this->mutex = NULL;
|
this->mutex = NULL;
|
||||||
this->waiting = 0;
|
this->waiting = 0;
|
||||||
|
@ -393,6 +394,14 @@ pthread_cond::pthread_cond (pthread_condattr * attr):verifyable_object (PTHREAD_
|
||||||
this->win32_obj_id =::CreateEvent (&sec_none_nih, false, /* auto signal reset - which I think is pthreads like ? */
|
this->win32_obj_id =::CreateEvent (&sec_none_nih, false, /* auto signal reset - which I think is pthreads like ? */
|
||||||
false, /* start non signaled */
|
false, /* start non signaled */
|
||||||
NULL /* no name */);
|
NULL /* no name */);
|
||||||
|
/* TODO: make a shared mem mutex if out attributes request shared mem cond */
|
||||||
|
cond_access=NULL;
|
||||||
|
if ((temperr = pthread_mutex_init (&this->cond_access, NULL)))
|
||||||
|
{
|
||||||
|
system_printf ("couldn't init mutex, this %0p errno=%d\n", this, temperr);
|
||||||
|
/* we need the mutex for correct behaviour */
|
||||||
|
magic = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->win32_obj_id)
|
if (!this->win32_obj_id)
|
||||||
magic = 0;
|
magic = 0;
|
||||||
|
@ -402,27 +411,38 @@ pthread_cond::~pthread_cond ()
|
||||||
{
|
{
|
||||||
if (win32_obj_id)
|
if (win32_obj_id)
|
||||||
CloseHandle (win32_obj_id);
|
CloseHandle (win32_obj_id);
|
||||||
|
pthread_mutex_destroy (&cond_access);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread_cond::BroadCast ()
|
pthread_cond::BroadCast ()
|
||||||
{
|
{
|
||||||
// This potentially has an unfairness bug. We should
|
if (pthread_mutex_lock (&cond_access))
|
||||||
// consider preventing the wakeups from resuming until we finish signalling.
|
system_printf ("Failed to lock condition variable access mutex, this %0p\n", this);
|
||||||
|
int count = waiting;
|
||||||
if (!verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC))
|
if (!verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC))
|
||||||
|
{
|
||||||
|
if (pthread_mutex_unlock (&cond_access))
|
||||||
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this);
|
||||||
|
system_printf ("Broadcast called with invalid mutex\n");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
while (count--)
|
||||||
PulseEvent (win32_obj_id);
|
PulseEvent (win32_obj_id);
|
||||||
while (InterlockedDecrement (&waiting) != 0)
|
if (pthread_mutex_unlock (&cond_access))
|
||||||
PulseEvent (win32_obj_id);
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this);
|
||||||
mutex = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread_cond::Signal ()
|
pthread_cond::Signal ()
|
||||||
{
|
{
|
||||||
|
if (pthread_mutex_lock (&cond_access))
|
||||||
|
system_printf ("Failed to lock condition variable access mutex, this %0p\n", this);
|
||||||
if (!verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC))
|
if (!verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC))
|
||||||
return;
|
return;
|
||||||
PulseEvent (win32_obj_id);
|
PulseEvent (win32_obj_id);
|
||||||
|
if (pthread_mutex_unlock (&cond_access))
|
||||||
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1608,6 +1628,8 @@ int
|
||||||
__pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
|
__pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||||
const struct timespec *abstime)
|
const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
|
// and yes cond_access here is still open to a race. (we increment, context swap,
|
||||||
|
// broadcast occurs - we miss the broadcast. the functions aren't split properly.
|
||||||
int rv;
|
int rv;
|
||||||
if (!abstime)
|
if (!abstime)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
@ -1623,18 +1645,31 @@ __pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||||
if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC))
|
if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
if (pthread_mutex_lock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to lock condition variable access mutex, this %0p\n", *cond);
|
||||||
|
|
||||||
if ((*cond)->waiting)
|
if ((*cond)->waiting)
|
||||||
if ((*cond)->mutex && ((*cond)->mutex != (*themutex)))
|
if ((*cond)->mutex && ((*cond)->mutex != (*themutex)))
|
||||||
|
{
|
||||||
|
if (pthread_mutex_unlock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
}
|
||||||
InterlockedIncrement (&((*cond)->waiting));
|
InterlockedIncrement (&((*cond)->waiting));
|
||||||
|
|
||||||
(*cond)->mutex = (*themutex);
|
(*cond)->mutex = (*themutex);
|
||||||
InterlockedIncrement (&((*themutex)->condwaits));
|
InterlockedIncrement (&((*themutex)->condwaits));
|
||||||
|
if (pthread_mutex_unlock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond);
|
||||||
rv = (*cond)->TimedWait (abstime->tv_sec * 1000);
|
rv = (*cond)->TimedWait (abstime->tv_sec * 1000);
|
||||||
|
if (pthread_mutex_lock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to lock condition variable access mutex, this %0p\n", *cond);
|
||||||
(*cond)->mutex->Lock ();
|
(*cond)->mutex->Lock ();
|
||||||
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
|
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
|
||||||
(*cond)->mutex = NULL;
|
(*cond)->mutex = NULL;
|
||||||
InterlockedDecrement (&((*themutex)->condwaits));
|
InterlockedDecrement (&((*themutex)->condwaits));
|
||||||
|
if (pthread_mutex_unlock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -1642,6 +1677,7 @@ __pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||||
int
|
int
|
||||||
__pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
|
__pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
|
||||||
{
|
{
|
||||||
|
// see cond_timedwait for notes
|
||||||
int rv;
|
int rv;
|
||||||
pthread_mutex_t *themutex = mutex;
|
pthread_mutex_t *themutex = mutex;
|
||||||
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
|
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
|
||||||
|
@ -1654,19 +1690,31 @@ __pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
|
||||||
if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC))
|
if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
if (pthread_mutex_lock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to lock condition variable access mutex, this %0p\n", *cond);
|
||||||
|
|
||||||
if ((*cond)->waiting)
|
if ((*cond)->waiting)
|
||||||
if ((*cond)->mutex && ((*cond)->mutex != (*themutex)))
|
if ((*cond)->mutex && ((*cond)->mutex != (*themutex)))
|
||||||
|
{
|
||||||
|
if (pthread_mutex_unlock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
}
|
||||||
InterlockedIncrement (&((*cond)->waiting));
|
InterlockedIncrement (&((*cond)->waiting));
|
||||||
|
|
||||||
(*cond)->mutex = (*themutex);
|
(*cond)->mutex = (*themutex);
|
||||||
InterlockedIncrement (&((*themutex)->condwaits));
|
InterlockedIncrement (&((*themutex)->condwaits));
|
||||||
|
if (pthread_mutex_unlock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond);
|
||||||
rv = (*cond)->TimedWait (INFINITE);
|
rv = (*cond)->TimedWait (INFINITE);
|
||||||
|
if (pthread_mutex_lock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to lock condition variable access mutex, this %0p\n", *cond);
|
||||||
(*cond)->mutex->Lock ();
|
(*cond)->mutex->Lock ();
|
||||||
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
|
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
|
||||||
(*cond)->mutex = NULL;
|
(*cond)->mutex = NULL;
|
||||||
InterlockedDecrement (&((*themutex)->condwaits));
|
InterlockedDecrement (&((*themutex)->condwaits));
|
||||||
|
if (pthread_mutex_unlock (&(*cond)->cond_access))
|
||||||
|
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -290,6 +290,8 @@ public:
|
||||||
int shared;
|
int shared;
|
||||||
LONG waiting;
|
LONG waiting;
|
||||||
pthread_mutex *mutex;
|
pthread_mutex *mutex;
|
||||||
|
/* to allow atomic behaviour for cond_broadcast */
|
||||||
|
pthread_mutex_t cond_access;
|
||||||
HANDLE win32_obj_id;
|
HANDLE win32_obj_id;
|
||||||
int TimedWait (DWORD dwMilliseconds);
|
int TimedWait (DWORD dwMilliseconds);
|
||||||
void BroadCast ();
|
void BroadCast ();
|
||||||
|
|
Loading…
Reference in New Issue