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:
Robert Collins 2001-05-06 22:23:43 +00:00
parent 2bfb966544
commit 68ebd3f6e2
3 changed files with 69 additions and 10 deletions

View File

@ -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>
* string.h (cygwin_strchr): Make 'static inline' so that things will

View File

@ -386,6 +386,7 @@ pthread_condattr::~pthread_condattr ()
pthread_cond::pthread_cond (pthread_condattr * attr):verifyable_object (PTHREAD_COND_MAGIC)
{
int temperr;
this->shared = attr ? attr->shared : PTHREAD_PROCESS_PRIVATE;
this->mutex = NULL;
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 ? */
false, /* start non signaled */
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)
magic = 0;
@ -402,27 +411,38 @@ pthread_cond::~pthread_cond ()
{
if (win32_obj_id)
CloseHandle (win32_obj_id);
pthread_mutex_destroy (&cond_access);
}
void
pthread_cond::BroadCast ()
{
// This potentially has an unfairness bug. We should
// consider preventing the wakeups from resuming until we finish signalling.
if (!verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC))
return;
PulseEvent (win32_obj_id);
while (InterlockedDecrement (&waiting) != 0)
if (pthread_mutex_lock (&cond_access))
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 (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;
}
while (count--)
PulseEvent (win32_obj_id);
mutex = NULL;
if (pthread_mutex_unlock (&cond_access))
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this);
}
void
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))
return;
PulseEvent (win32_obj_id);
if (pthread_mutex_unlock (&cond_access))
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this);
}
int
@ -1608,6 +1628,8 @@ int
__pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
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;
if (!abstime)
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))
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)->mutex && ((*cond)->mutex != (*themutex)))
return EINVAL;
{
if (pthread_mutex_unlock (&(*cond)->cond_access))
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond);
return EINVAL;
}
InterlockedIncrement (&((*cond)->waiting));
(*cond)->mutex = (*themutex);
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);
if (pthread_mutex_lock (&(*cond)->cond_access))
system_printf ("Failed to lock condition variable access mutex, this %0p\n", *cond);
(*cond)->mutex->Lock ();
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
(*cond)->mutex = NULL;
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;
}
@ -1642,6 +1677,7 @@ __pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
int
__pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
{
// see cond_timedwait for notes
int rv;
pthread_mutex_t *themutex = mutex;
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))
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)->mutex && ((*cond)->mutex != (*themutex)))
return EINVAL;
{
if (pthread_mutex_unlock (&(*cond)->cond_access))
system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond);
return EINVAL;
}
InterlockedIncrement (&((*cond)->waiting));
(*cond)->mutex = (*themutex);
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);
if (pthread_mutex_lock (&(*cond)->cond_access))
system_printf ("Failed to lock condition variable access mutex, this %0p\n", *cond);
(*cond)->mutex->Lock ();
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
(*cond)->mutex = NULL;
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;
}

View File

@ -290,6 +290,8 @@ public:
int shared;
LONG waiting;
pthread_mutex *mutex;
/* to allow atomic behaviour for cond_broadcast */
pthread_mutex_t cond_access;
HANDLE win32_obj_id;
int TimedWait (DWORD dwMilliseconds);
void BroadCast ();