Add PR_Block/Unblock_Interrupt functions. Bugzilla 17055
git-svn-id: svn://10.0.0.236/trunk@52041 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
dbcd581b59
commit
bc406e3e1e
@ -166,6 +166,12 @@ struct _PT_Notified
|
||||
#define PT_THREAD_FOREIGN 0x80 /* thread is not one of ours */
|
||||
#define PT_THREAD_BOUND 0x100 /* a bound-global thread */
|
||||
|
||||
#define _PT_THREAD_INTERRUPTED(thr) \
|
||||
(!(thr->interrupt_blocked) && (thr->state & PT_THREAD_ABORTED))
|
||||
#define _PT_THREAD_BLOCK_INTERRUPT(thr) \
|
||||
(thr->interrupt_blocked = 1)
|
||||
#define _PT_THREAD_UNBLOCK_INTERRUPT(thr) \
|
||||
(thr->interrupt_blocked = 0)
|
||||
/*
|
||||
** Possible values for thread's suspend field
|
||||
** Note that the first two can be the same as they are really mutually exclusive,
|
||||
@ -575,6 +581,7 @@ typedef struct _PRPerThreadExit {
|
||||
#define _PR_IDLE_THREAD 0x200 /* this is an idle thread */
|
||||
#define _PR_GCABLE_THREAD 0x400 /* this is a collectable thread */
|
||||
#define _PR_BOUND_THREAD 0x800 /* a bound thread */
|
||||
#define _PR_INTERRUPT_BLOCKED 0x1000 /* interrupts blocked */
|
||||
|
||||
/* PRThread.state */
|
||||
#define _PR_UNBORN 0
|
||||
@ -617,7 +624,12 @@ typedef struct _PRPerThreadExit {
|
||||
#define _PR_ADJUST_STACKSIZE(stackSize)
|
||||
#endif
|
||||
|
||||
#define _PR_PENDING_INTERRUPT(_thread) ((_thread)->flags & _PR_INTERRUPT)
|
||||
#define _PR_PENDING_INTERRUPT(thr) \
|
||||
(!((thr)->flags & _PR_INTERRUPT_BLOCKED) && ((thr)->flags & _PR_INTERRUPT))
|
||||
#define _PR_THREAD_BLOCK_INTERRUPT(thr) \
|
||||
(thr->flags |= _PR_INTERRUPT_BLOCKED)
|
||||
#define _PR_THREAD_UNBLOCK_INTERRUPT(thr) \
|
||||
(thr->flags &= ~_PR_INTERRUPT_BLOCKED)
|
||||
|
||||
#define _PR_THREAD_PTR(_qp) \
|
||||
((PRThread*) ((char*) (_qp) - offsetof(PRThread,links)))
|
||||
@ -1424,6 +1436,7 @@ struct PRThread {
|
||||
pthread_mutex_t suspendResumeMutex;
|
||||
pthread_cond_t suspendResumeCV;
|
||||
#endif
|
||||
PRUint32 interrupt_blocked; /* interrupt blocked */
|
||||
#elif defined(_PR_BTHREADS)
|
||||
PRUint32 flags;
|
||||
_MDThread md;
|
||||
|
||||
@ -226,6 +226,16 @@ PR_EXTERN(PRStatus) PR_Interrupt(PRThread *thread);
|
||||
*/
|
||||
PR_EXTERN(void) PR_ClearInterrupt(void);
|
||||
|
||||
/*
|
||||
** Block the interrupt for the calling thread.
|
||||
*/
|
||||
PR_EXTERN(void) PR_BlockInterrupt(void);
|
||||
|
||||
/*
|
||||
** Unblock the interrupt for the calling thread.
|
||||
*/
|
||||
PR_EXTERN(void) PR_UnblockInterrupt(void);
|
||||
|
||||
/*
|
||||
** Make the current thread sleep until "ticks" time amount of time
|
||||
** has expired. If "ticks" is PR_INTERVAL_NO_WAIT then the call is
|
||||
|
||||
@ -642,7 +642,7 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
|
||||
** (perhaps) resetting it are safe 'cause it's the only modifiable
|
||||
** bit in that word.
|
||||
*/
|
||||
if (tqp->thread->state & PT_THREAD_ABORTED)
|
||||
if (_PT_THREAD_INTERRUPTED(tqp->thread))
|
||||
{
|
||||
my_op->status = pt_continuation_abort;
|
||||
tqp->thread->state &= ~PT_THREAD_ABORTED;
|
||||
@ -1383,7 +1383,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd)
|
||||
static PRBool pt_TestAbort(void)
|
||||
{
|
||||
PRThread *me = PR_CurrentThread();
|
||||
if(me->state & PT_THREAD_ABORTED)
|
||||
if(_PT_THREAD_INTERRUPTED(me))
|
||||
{
|
||||
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
me->state &= ~PT_THREAD_ABORTED;
|
||||
|
||||
@ -333,7 +333,7 @@ PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
|
||||
/* and it better be by us */
|
||||
PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
|
||||
|
||||
if (thred->state & PT_THREAD_ABORTED) goto aborted;
|
||||
if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
|
||||
|
||||
/*
|
||||
* The thread waiting is used for PR_Interrupt
|
||||
@ -367,7 +367,7 @@ PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
|
||||
|
||||
PR_ASSERT(0 == cvar->lock->notified.length);
|
||||
thred->waiting = NULL; /* and now we're not */
|
||||
if (thred->state & PT_THREAD_ABORTED) goto aborted;
|
||||
if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
|
||||
return (rv == 0) ? PR_SUCCESS : PR_FAILURE;
|
||||
|
||||
aborted:
|
||||
|
||||
@ -719,6 +719,18 @@ PR_IMPLEMENT(void) PR_ClearInterrupt()
|
||||
me->state &= ~PT_THREAD_ABORTED;
|
||||
} /* PR_ClearInterrupt */
|
||||
|
||||
PR_IMPLEMENT(void) PR_BlockInterrupt()
|
||||
{
|
||||
PRThread *me = PR_CurrentThread();
|
||||
_PT_THREAD_BLOCK_INTERRUPT(me);
|
||||
} /* PR_BlockInterrupt */
|
||||
|
||||
PR_IMPLEMENT(void) PR_UnblockInterrupt()
|
||||
{
|
||||
PRThread *me = PR_CurrentThread();
|
||||
_PT_THREAD_UNBLOCK_INTERRUPT(me);
|
||||
} /* PR_UnblockInterrupt */
|
||||
|
||||
PR_IMPLEMENT(PRStatus) PR_Yield()
|
||||
{
|
||||
static PRBool warning = PR_TRUE;
|
||||
|
||||
@ -258,6 +258,30 @@ PR_IMPLEMENT(void) PR_ClearInterrupt()
|
||||
if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PR_BlockInterrupt()
|
||||
{
|
||||
PRIntn is;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
|
||||
_PR_THREAD_LOCK(me);
|
||||
_PR_THREAD_BLOCK_INTERRUPT(me);
|
||||
_PR_THREAD_UNLOCK(me);
|
||||
if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
|
||||
} /* PR_BlockInterrupt */
|
||||
|
||||
PR_IMPLEMENT(void) PR_UnblockInterrupt()
|
||||
{
|
||||
PRIntn is;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
|
||||
_PR_THREAD_LOCK(me);
|
||||
_PR_THREAD_UNBLOCK_INTERRUPT(me);
|
||||
_PR_THREAD_UNLOCK(me);
|
||||
if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
|
||||
} /* PR_UnblockInterrupt */
|
||||
|
||||
/*
|
||||
** Return the thread stack pointer of the given thread.
|
||||
*/
|
||||
|
||||
@ -42,6 +42,8 @@
|
||||
extern void SetupMacPrintfLog(char *logFile);
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TCP_PORT 12500
|
||||
|
||||
static PRLock *ml = NULL;
|
||||
static PRCondVar *cv = NULL;
|
||||
|
||||
@ -149,13 +151,90 @@ static void PR_CALLBACK AbortJoin(void *arg)
|
||||
{
|
||||
} /* AbortJoin */
|
||||
|
||||
static void setup_listen_socket(PRFileDesc **listner, PRNetAddr *netaddr)
|
||||
{
|
||||
PRStatus rv;
|
||||
PRInt16 port = DEFAULT_TCP_PORT;
|
||||
|
||||
*listner = PR_NewTCPSocket();
|
||||
PR_ASSERT(*listner != NULL);
|
||||
memset(netaddr, 0, sizeof(*netaddr));
|
||||
(*netaddr).inet.ip = PR_htonl(PR_INADDR_ANY);
|
||||
(*netaddr).inet.family = PR_AF_INET;
|
||||
do
|
||||
{
|
||||
(*netaddr).inet.port = PR_htons(port);
|
||||
rv = PR_Bind(*listner, netaddr);
|
||||
port += 1;
|
||||
PR_ASSERT(port < (DEFAULT_TCP_PORT + 10));
|
||||
} while (PR_FAILURE == rv);
|
||||
|
||||
rv = PR_Listen(*listner, 5);
|
||||
|
||||
if (PR_GetSockName(*listner, netaddr) < 0) {
|
||||
if (debug_mode) printf("intrupt: ERROR - PR_GetSockName failed\n");
|
||||
passed = PR_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void PR_CALLBACK IntrBlock(void *arg)
|
||||
{
|
||||
PRStatus rv;
|
||||
PRNetAddr netaddr;
|
||||
PRFileDesc *listner;
|
||||
|
||||
/* some other thread (main) is doing the interrupt */
|
||||
/* block the interrupt */
|
||||
PR_BlockInterrupt();
|
||||
PR_Lock(ml);
|
||||
rv = PR_WaitCondVar(cv, PR_SecondsToInterval(4));
|
||||
PR_Unlock(ml);
|
||||
if (debug_mode)
|
||||
{
|
||||
printf("Expected success on wait CV and ");
|
||||
if (PR_FAILURE == rv)
|
||||
{
|
||||
printf(
|
||||
"%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
|
||||
"got interrupted" : "got a random failure");
|
||||
} else
|
||||
printf("got it\n");
|
||||
}
|
||||
passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
setup_listen_socket(&listner, &netaddr);
|
||||
PR_UnblockInterrupt();
|
||||
if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
|
||||
{
|
||||
PRInt32 error = PR_GetError();
|
||||
if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
|
||||
if (PR_PENDING_INTERRUPT_ERROR == error)
|
||||
{
|
||||
if (debug_mode) printf("got it\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug_mode) printf("failed\n");
|
||||
passed = PR_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
|
||||
passed = PR_FALSE;
|
||||
}
|
||||
|
||||
(void)PR_Close(listner); listner = NULL;
|
||||
} /* TestIntrBlock */
|
||||
|
||||
void PR_CALLBACK Intrupt(void *arg)
|
||||
{
|
||||
PRStatus rv;
|
||||
PRNetAddr netaddr;
|
||||
PRFileDesc *listner;
|
||||
PRInt16 port = 12848;
|
||||
PRThread *abortCV, *abortIO, *abortJoin;
|
||||
PRThread *abortCV, *abortIO, *abortJoin, *intrBlock;
|
||||
|
||||
ml = PR_NewLock();
|
||||
cv = PR_NewCondVar(ml);
|
||||
@ -192,26 +271,7 @@ void PR_CALLBACK Intrupt(void *arg)
|
||||
|
||||
/* Part III */
|
||||
if (debug_mode) printf("Part III\n");
|
||||
listner = PR_NewTCPSocket();
|
||||
memset(&netaddr, 0, sizeof(netaddr));
|
||||
netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
|
||||
netaddr.inet.family = PR_AF_INET;
|
||||
do
|
||||
{
|
||||
netaddr.inet.port = PR_htons(port);
|
||||
rv = PR_Bind(listner, &netaddr);
|
||||
port += 1;
|
||||
PR_ASSERT(port < (12848 + 10));
|
||||
} while (PR_FAILURE == rv);
|
||||
|
||||
rv = PR_Listen(listner, 5);
|
||||
|
||||
if (PR_GetSockName(listner, &netaddr) < 0) {
|
||||
if (debug_mode) printf("intrupt: ERROR - PR_GetSockName failed\n");
|
||||
passed = PR_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
setup_listen_socket(&listner, &netaddr);
|
||||
abortIO = PR_CreateThread(
|
||||
PR_USER_THREAD, AbortIO, PR_CurrentThread(), PR_PRIORITY_NORMAL,
|
||||
thread_scope, PR_JOINABLE_THREAD, 0);
|
||||
@ -240,6 +300,17 @@ void PR_CALLBACK Intrupt(void *arg)
|
||||
|
||||
rv = PR_JoinThread(abortIO);
|
||||
PR_ASSERT(PR_SUCCESS == rv);
|
||||
/* Part VI */
|
||||
if (debug_mode) printf("Part VI\n");
|
||||
intrBlock = PR_CreateThread(
|
||||
PR_USER_THREAD, IntrBlock, 0, PR_PRIORITY_NORMAL,
|
||||
thread_scope, PR_JOINABLE_THREAD, 0);
|
||||
|
||||
PR_Sleep(PR_SecondsToInterval(2));
|
||||
rv = PR_Interrupt(intrBlock);
|
||||
PR_ASSERT(PR_SUCCESS == rv);
|
||||
rv = PR_JoinThread(intrBlock);
|
||||
PR_ASSERT(PR_SUCCESS == rv);
|
||||
|
||||
PR_DestroyCondVar(cv);
|
||||
PR_DestroyLock(ml);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user