From c156eacc8b9c6f33f89c7563f2821320be79c2e1 Mon Sep 17 00:00:00 2001 From: rpj Date: Sun, 1 Jul 2001 14:35:49 +0000 Subject: 2001-07-01 Ross Johnson Contributed by - Alexander Terekhov. * condvar.c: Fixed lost signal bug reported by Timur Aydin (taydin@snet.net). [RPJ (me) didn't translate the original algorithm correctly.] * semaphore.c: Added sem_post_multiple; this is a useful routine, but it doesn't appear to be standard. For now it's not an exported function. --- condvar.c | 121 +++++++++++++++++++++----------------------------------------- 1 file changed, 40 insertions(+), 81 deletions(-) (limited to 'condvar.c') diff --git a/condvar.c b/condvar.c index 3607594..65d4e5f 100644 --- a/condvar.c +++ b/condvar.c @@ -693,7 +693,7 @@ ptw32_cond_wait_cleanup(void * args) pthread_cond_t cv = cleanup_args->cv; int * resultPtr = cleanup_args->resultPtr; int nSignalsWasLeft; - int nWaitersWasGone = 0; + int nWaitersWasGone = 0; /* Initialised to quell warnings. */ int result; /* @@ -701,17 +701,16 @@ ptw32_cond_wait_cleanup(void * args) * timeout on wait or thread cancellation we indicate that we are no * longer waiting. The waiter is responsible for adjusting waiters * (to)unblock(ed) counts (protected by unblock lock). - * Unblock lock/Sync.LEVEL-2 supports _timedwait and cancellation. */ if ((result = pthread_mutex_lock(&(cv->mtxUnblockLock))) != 0) { *resultPtr = result; - goto FAIL0; + return; } if ( 0 != (nSignalsWasLeft = cv->nWaitersToUnblock) ) { - if ( ! cleanup_args->signaled ) + if ( !cleanup_args->signaled ) { if ( 0 != cv->nWaitersBlocked ) { @@ -729,7 +728,8 @@ ptw32_cond_wait_cleanup(void * args) if (sem_post( &(cv->semBlockLock) ) != 0) { *resultPtr = errno; - goto FAIL1; + (void) pthread_mutex_unlock( &(cv->mtxUnblockLock) ); + return; } nSignalsWasLeft = 0; } @@ -744,64 +744,46 @@ ptw32_cond_wait_cleanup(void * args) if (sem_wait( &(cv->semBlockLock) ) != 0) { *resultPtr = errno; - goto FAIL1; + (void) pthread_mutex_unlock( &(cv->mtxUnblockLock) ); + return; } cv->nWaitersBlocked -= cv->nWaitersGone; if (sem_post( &(cv->semBlockLock) ) != 0) { *resultPtr = errno; - goto FAIL1; + (void) pthread_mutex_unlock( &(cv->mtxUnblockLock) ); + return; } cv->nWaitersGone = 0; } - /* - * No more LEVEL-2 access to waiters (to)unblock(ed) counts needed - */ if ((result = pthread_mutex_unlock(&(cv->mtxUnblockLock))) != 0) { *resultPtr = result; - goto FAIL0; + return; } - /* - * If last signal... - */ if ( 1 == nSignalsWasLeft ) { if ( 0 != nWaitersWasGone ) { // sem_adjust( &(cv->semBlockQueue), -nWaitersWasGone ); - while ( nWaitersWasGone-- ) { - if (sem_wait( &(cv->semBlockQueue)) != 0 ) - { - *resultPtr = errno; - goto FAIL0; - } - } + while ( nWaitersWasGone-- ) + { + if (sem_wait( &(cv->semBlockQueue)) != 0 ) + { + *resultPtr = errno; + return; + } + } } - /* - * ...it means that we have end of 'atomic' signal/broadcast - */ if (sem_post(&(cv->semBlockLock)) != 0) { *resultPtr = errno; - goto FAIL0; + return; } } - goto DONE; - - FAIL1: - if ((result = pthread_mutex_unlock(&(cv->mtxUnblockLock))) != 0) - { - *resultPtr = result; - } - - FAIL0: - return; - - DONE: /* * XSH: Upon successful return, the mutex has been locked and is owned * by the calling thread @@ -845,9 +827,6 @@ ptw32_cond_timedwait (pthread_cond_t * cond, cv = *cond; - /* - * Synchronize access to waiters blocked count (LEVEL-1) - */ if (sem_wait(&(cv->semBlockLock)) != 0) { return errno; @@ -855,9 +834,6 @@ ptw32_cond_timedwait (pthread_cond_t * cond, cv->nWaitersBlocked++; - /* - * Thats it. Counted means waiting, no more access needed - */ if (sem_post(&(cv->semBlockLock)) != 0) { return errno; @@ -948,9 +924,8 @@ ptw32_cond_unblock (pthread_cond_t * cond, */ { int result; - int result2; pthread_cond_t cv; - int nSignalsToIssue = 1; + int nSignalsToIssue; if (cond == NULL || *cond == NULL) { @@ -968,10 +943,6 @@ ptw32_cond_unblock (pthread_cond_t * cond, return 0; } - /* - * Synchronize access to waiters (to)unblock(ed) counts (LEVEL-2) - * This sync.level supports _timedwait and cancellation - */ if ((result = pthread_mutex_lock(&(cv->mtxUnblockLock))) != 0) { return result; @@ -981,7 +952,7 @@ ptw32_cond_unblock (pthread_cond_t * cond, { if ( 0 == cv->nWaitersBlocked ) { - goto FAIL1; + return pthread_mutex_unlock( &(cv->mtxUnblockLock) ); } if (unblockAll) { @@ -990,60 +961,48 @@ ptw32_cond_unblock (pthread_cond_t * cond, } else { + nSignalsToIssue = 1; cv->nWaitersToUnblock++; cv->nWaitersBlocked--; } } - else + else if ( cv->nWaitersBlocked > cv->nWaitersGone ) { if (sem_wait( &(cv->semBlockLock) ) != 0) { result = errno; - goto FAIL1; + (void) pthread_mutex_unlock( &(cv->mtxUnblockLock) ); + return result; } - if ( cv->nWaitersBlocked > cv->nWaitersGone ) + if ( 0 != cv->nWaitersGone ) { - if ( 0 != cv->nWaitersGone ) - { - cv->nWaitersBlocked -= cv->nWaitersGone; - cv->nWaitersGone = 0; - } - if (unblockAll) - { - nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked; - cv->nWaitersBlocked = 0; - } - else - { - nSignalsToIssue = cv->nWaitersToUnblock = 1; - cv->nWaitersBlocked--; - } + cv->nWaitersBlocked -= cv->nWaitersGone; + cv->nWaitersGone = 0; + } + if (unblockAll) + { + nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked; + cv->nWaitersBlocked = 0; } else { - if (sem_post( &(cv->semBlockLock) ) != 0) - { - result = errno; - goto FAIL1; - } + nSignalsToIssue = cv->nWaitersToUnblock = 1; + cv->nWaitersBlocked--; } } - - FAIL1: - if ((result2 = pthread_mutex_unlock( &(cv->mtxUnblockLock) )) != 0) + else { - result = result2; + return pthread_mutex_unlock( &(cv->mtxUnblockLock) ); } - while (0 != nSignalsToIssue--) + + if ((result = pthread_mutex_unlock( &(cv->mtxUnblockLock) )) == 0) { - if (sem_post( &(cv->semBlockQueue) ) != 0) + if (sem_post_multiple( &(cv->semBlockQueue), nSignalsToIssue ) != 0) { result = errno; - goto FAIL0; } } - FAIL0: return result; } /* ptw32_cond_unblock */ -- cgit v1.2.3