summaryrefslogtreecommitdiff
path: root/pthread_cond_wait.c
diff options
context:
space:
mode:
authorrpj <rpj>2002-07-30 17:18:25 +0000
committerrpj <rpj>2002-07-30 17:18:25 +0000
commitd9bad66cbb8823ad786ac480330db1c05e85557a (patch)
tree512085bea583cab23c9f32646921fbda66aa447d /pthread_cond_wait.c
parentccd0f86e370fa71acd47c17cb9579877403c81d1 (diff)
* pthread_cond_wait.c (ptw32_cond_wait_cleanup):
Remove code designed to avoid/prevent spurious wakeup problems. It is believed that the sem_timedwait() call is consuming a CV signal that it shouldn't and this is breaking the avoidance logic.
Diffstat (limited to 'pthread_cond_wait.c')
-rw-r--r--pthread_cond_wait.c145
1 files changed, 98 insertions, 47 deletions
diff --git a/pthread_cond_wait.c b/pthread_cond_wait.c
index d1f5155..f3b4f03 100644
--- a/pthread_cond_wait.c
+++ b/pthread_cond_wait.c
@@ -160,12 +160,107 @@
* }
* -------------------------------------------------------------
*
+ * Algorithm 9 / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
+ *
+ * presented below in pseudo-code; basically 8a...
+ * ...BUT W/O "spurious wakes" prevention:
+ *
+ *
+ * given:
+ * semBlockLock - bin.semaphore
+ * semBlockQueue - semaphore
+ * mtxExternal - mutex or CS
+ * mtxUnblockLock - mutex or CS
+ * nWaitersGone - int
+ * nWaitersBlocked - int
+ * nWaitersToUnblock - int
+ *
+ * wait( timeout ) {
+ *
+ * [auto: register int result ] // error checking omitted
+ * [auto: register int nSignalsWasLeft ]
+ *
+ * sem_wait( semBlockLock );
+ * ++nWaitersBlocked;
+ * sem_post( semBlockLock );
+ *
+ * unlock( mtxExternal );
+ * bTimedOut = sem_wait( semBlockQueue,timeout );
+ *
+ * lock( mtxUnblockLock );
+ * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+ * --nWaitersToUnblock;
+ * }
+ * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
+ * // spurious semaphore :-)
+ * sem_wait( semBlockLock );
+ * nWaitersBlocked -= nWaitersGone; // something is going on here
+ * // - test of timeouts? :-)
+ * sem_post( semBlockLock );
+ * nWaitersGone = 0;
+ * }
+ * unlock( mtxUnblockLock );
+ *
+ * if ( 1 == nSignalsWasLeft ) {
+ * sem_post( semBlockLock ); // open the gate
+ * }
+ *
+ * lock( mtxExternal );
+ *
+ * return ( bTimedOut ) ? ETIMEOUT : 0;
+ * }
+ *
+ * signal(bAll) {
+ *
+ * [auto: register int result ]
+ * [auto: register int nSignalsToIssue]
+ *
+ * lock( mtxUnblockLock );
+ *
+ * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+ * if ( 0 == nWaitersBlocked ) { // NO-OP
+ * return unlock( mtxUnblockLock );
+ * }
+ * if (bAll) {
+ * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+ * nWaitersBlocked = 0;
+ * }
+ * else {
+ * nSignalsToIssue = 1;
+ * ++nWaitersToUnblock;
+ * --nWaitersBlocked;
+ * }
+ * }
+ * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+ * sem_wait( semBlockLock ); // close the gate
+ * if ( 0 != nWaitersGone ) {
+ * nWaitersBlocked -= nWaitersGone;
+ * nWaitersGone = 0;
+ * }
+ * if (bAll) {
+ * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+ * nWaitersBlocked = 0;
+ * }
+ * else {
+ * nSignalsToIssue = nWaitersToUnblock = 1;
+ * --nWaitersBlocked;
+ * }
+ * }
+ * else { // NO-OP
+ * return unlock( mtxUnblockLock );
+ * }
+ *
+ * unlock( mtxUnblockLock );
+ * sem_post( semBlockQueue,nSignalsToIssue );
+ * return result;
+ * }
+ * -------------------------------------------------------------
+ *
*/
#include "pthread.h"
#include "implement.h"
-
/*
* Arguments for cond_wait_cleanup, since we can only pass a
* single void * to it.
@@ -184,7 +279,6 @@ ptw32_cond_wait_cleanup(void * args)
pthread_cond_t cv = cleanup_args->cv;
int * resultPtr = cleanup_args->resultPtr;
int nSignalsWasLeft;
- int nWaitersWasGone = 0; /* Initialised to quell warnings. */
int result;
/*
@@ -201,38 +295,7 @@ ptw32_cond_wait_cleanup(void * args)
if ( 0 != (nSignalsWasLeft = cv->nWaitersToUnblock) )
{
- if ( !cleanup_args->signaled )
- {
- if ( 0 != cv->nWaitersBlocked )
- {
- (cv->nWaitersBlocked)--;
- }
- else
- {
- (cv->nWaitersGone)++;
- }
- }
- if ( 0 == --(cv->nWaitersToUnblock) )
- {
- if ( 0 != cv->nWaitersBlocked )
- {
- if (sem_post( &(cv->semBlockLock) ) != 0)
- {
- *resultPtr = errno;
- /*
- * This is a fatal error for this CV,
- * so we deliberately don't unlock
- * cv->mtxUnblockLock before returning.
- */
- return;
- }
- nSignalsWasLeft = 0;
- }
- else if ( 0 != (nWaitersWasGone = cv->nWaitersGone) )
- {
- cv->nWaitersGone = 0;
- }
- }
+ --(cv->nWaitersToUnblock);
}
else if ( INT_MAX/2 == ++(cv->nWaitersGone) )
{
@@ -268,18 +331,6 @@ ptw32_cond_wait_cleanup(void * args)
if ( 1 == nSignalsWasLeft )
{
- if ( 0 != nWaitersWasGone )
- {
- // sem_adjust( &(cv->semBlockQueue), -nWaitersWasGone );
- while ( nWaitersWasGone-- )
- {
- if (sem_wait( &(cv->semBlockQueue)) != 0 )
- {
- *resultPtr = errno;
- return;
- }
- }
- }
if (sem_post(&(cv->semBlockLock)) != 0)
{
*resultPtr = errno;
@@ -335,7 +386,7 @@ ptw32_cond_timedwait (pthread_cond_t * cond,
return errno;
}
- cv->nWaitersBlocked++;
+ ++(cv->nWaitersBlocked);
if (sem_post(&(cv->semBlockLock)) != 0)
{