зеркало из https://github.com/mozilla/pjs.git
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
This commit is contained in:
Родитель
6622635cab
Коммит
d9438beee9
|
@ -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;
|
||||
switch (timeout) {
|
||||
case PR_INTERVAL_NO_WAIT:
|
||||
/* nothing to do */
|
||||
break;
|
||||
|
||||
} 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 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 );
|
||||
/* this doesn't appear to be a valid thread_id */
|
||||
PR_SetError( PR_UNKNOWN_ERROR, rv );
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
return( PR_SUCCESS );
|
||||
rv = resume_thread( thred->md.tid );
|
||||
if( rv != B_NO_ERROR )
|
||||
{
|
||||
PR_SetError( PR_UNKNOWN_ERROR, rv );
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
|
|
Загрузка…
Ссылка в новой задаче