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:
srinivas%netscape.com 1999-10-28 02:48:01 +00:00
parent dbcd581b59
commit bc406e3e1e
7 changed files with 157 additions and 27 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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;

View File

@ -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.
*/

View File

@ -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);