summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>2000-04-26 01:31:48 +0000
committerwtc%netscape.com <devnull@localhost>2000-04-26 01:31:48 +0000
commit0ff116471b40a6de7f8a106084acc5b2f964ea1c (patch)
tree594add31527aee8e90d341c37a60bf8df9a31195
parent743a4fa3fd904482151b17b8b8b628d20893d291 (diff)
downloadnspr-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.c64
-rw-r--r--pr/src/bthreads/btthread.c44
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)