diff options
author | wtc%netscape.com <devnull@localhost> | 2000-04-26 01:31:48 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 2000-04-26 01:31:48 +0000 |
commit | 0ff116471b40a6de7f8a106084acc5b2f964ea1c (patch) | |
tree | 594add31527aee8e90d341c37a60bf8df9a31195 | |
parent | 743a4fa3fd904482151b17b8b8b628d20893d291 (diff) | |
download | nspr-hg-0ff116471b40a6de7f8a106084acc5b2f964ea1c.tar.gz |
Bugzilla bug #36818: fixed bugs in PR_WaitCondVar, PR_NotifyAllCondVar,
and PR_Interrupt. Thanks to justin morey <justin@68k.org> for the bug
report and the patch.
Modified files: btcvar.c, btthread.c
-rw-r--r-- | pr/src/bthreads/btcvar.c | 64 | ||||
-rw-r--r-- | pr/src/bthreads/btthread.c | 44 |
2 files changed, 59 insertions, 49 deletions
diff --git a/pr/src/bthreads/btcvar.c b/pr/src/bthreads/btcvar.c index 9e77e27b..b151f332 100644 --- a/pr/src/bthreads/btcvar.c +++ b/pr/src/bthreads/btcvar.c @@ -88,34 +88,46 @@ PR_IMPLEMENT(PRStatus) PR_WaitCondVar (PRCondVar *cvar, PRIntervalTime timeout) { status_t result; - - /* - ** This is an entirely stupid bug, but... If you call - ** acquire_sem_etc with a timeout of exactly 1,000,000 microseconds - ** it returns immediately with B_NO_ERROR. 1,000,010 microseconds - ** returns as expected. Running BeOS/Intel R3.1 at this time. - ** Forwarded to Be, Inc. for resolution, Bug ID 980624-225956 - ** - ** Update: Be couldn't reproduce it, but removing timeout++ still - ** exhibits the problem on BeOS/Intel R4 and BeOS/PPC R4. - */ - - timeout++; + bigtime_t interval; PR_Unlock( cvar->lock ); - if( PR_INTERVAL_NO_WAIT != timeout ) - { - if( PR_INTERVAL_NO_TIMEOUT == timeout ) - { - if( acquire_sem( cvar->isem ) != B_NO_ERROR ) return PR_FAILURE; - - } else - { - result = acquire_sem_etc( cvar->isem, 1, B_TIMEOUT, PR_IntervalToMicroseconds( timeout ) ); - if( result != B_NO_ERROR && result != B_TIMED_OUT ) - return PR_FAILURE; - } + switch (timeout) { + case PR_INTERVAL_NO_WAIT: + /* nothing to do */ + break; + + case PR_INTERVAL_NO_TIMEOUT: + /* wait as long as necessary */ + if( acquire_sem( cvar->isem ) != B_NO_ERROR ) return PR_FAILURE; + break; + + default: + interval = (bigtime_t)PR_IntervalToMicroseconds(timeout); + + /* + ** in R5, this problem seems to have been resolved, so we + ** won't bother with it + */ +#if !defined(B_BEOS_VERSION_5) || (B_BEOS_VERSION < B_BEOS_VERSION_5) + /* + ** This is an entirely stupid bug, but... If you call + ** acquire_sem_etc with a timeout of exactly 1,000,000 microseconds + ** it returns immediately with B_NO_ERROR. 1,000,010 microseconds + ** returns as expected. Running BeOS/Intel R3.1 at this time. + ** Forwarded to Be, Inc. for resolution, Bug ID 980624-225956 + ** + ** Update: Be couldn't reproduce it, but removing timeout++ still + ** exhibits the problem on BeOS/Intel R4 and BeOS/PPC R4. + */ + if (interval == 1000000) + interval = 1000010; +#endif /* !defined(B_BEOS_VERSION_5) || (B_BEOS_VERSION < B_BEOS_VERSION_5) */ + + result = acquire_sem_etc( cvar->isem, 1, B_RELATIVE_TIMEOUT, interval); + if( result != B_NO_ERROR && result != B_TIMED_OUT ) + return PR_FAILURE; + break; } PR_Lock( cvar->lock ); @@ -162,4 +174,6 @@ PR_IMPLEMENT(PRStatus) if( release_sem_etc( cvar->isem, semInfo.count, 0 ) != B_NO_ERROR ) return PR_FAILURE; + + return PR_SUCCESS; } diff --git a/pr/src/bthreads/btthread.c b/pr/src/bthreads/btthread.c index fde9189a..e7e7997f 100644 --- a/pr/src/bthreads/btthread.c +++ b/pr/src/bthreads/btthread.c @@ -674,38 +674,34 @@ PR_IMPLEMENT(PRStatus) PRIntn rv; PR_ASSERT(thred != NULL); - rv = resume_thread( thred->md.tid ); - if( rv == B_BAD_THREAD_STATE ) - { - /* - ** We have a thread that's not suspended, but is - ** blocked. Suspend it THEN resume it. The - ** function call that's hanging will return - ** B_INTERRUPTED - */ + /* + ** there seems to be a bug in beos R5 in which calling + ** resume_thread() on a blocked thread returns B_OK instead + ** of B_BAD_THREAD_STATE (beos bug #20000422-19095). as such, + ** to interrupt a thread, we will simply suspend then resume it + ** (no longer call resume_thread(), check for B_BAD_THREAD_STATE, + ** the suspend/resume to wake up a blocked thread). this wakes + ** up blocked threads properly, and doesn't hurt unblocked threads + ** (they simply get stopped then re-started immediately) + */ - rv = suspend_thread( thred->md.tid ); - if( rv != B_NO_ERROR ) - { - PR_SetError( PR_UNKNOWN_ERROR, rv ); - return( PR_FAILURE ); - } - rv = resume_thread( thred->md.tid ); - if( rv != B_NO_ERROR ) - { - PR_SetError( PR_UNKNOWN_ERROR, rv ); - return( PR_FAILURE ); - } + rv = suspend_thread( thred->md.tid ); + if( rv != B_NO_ERROR ) + { + /* this doesn't appear to be a valid thread_id */ + PR_SetError( PR_UNKNOWN_ERROR, rv ); + return PR_FAILURE; } + rv = resume_thread( thred->md.tid ); if( rv != B_NO_ERROR ) { - PR_SetError( PR_UNKNOWN_ERROR, rv ); - return( PR_FAILURE ); + PR_SetError( PR_UNKNOWN_ERROR, rv ); + return PR_FAILURE; } - return( PR_SUCCESS ); + return PR_SUCCESS; } PR_IMPLEMENT(void) |