nsprpub/pr/src/threads/combined/prucv.c

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "primpl.h"
     8 #include "prinrval.h"
     9 #include "prtypes.h"
    11 #if defined(WIN95)
    12 /*
    13 ** Some local variables report warnings on Win95 because the code paths 
    14 ** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
    15 ** The pragma suppresses the warning.
    16 ** 
    17 */
    18 #pragma warning(disable : 4101)
    19 #endif
    22 /*
    23 ** Notify one thread that it has finished waiting on a condition variable
    24 ** Caller must hold the _PR_CVAR_LOCK(cv)
    25 */
    26 PRBool _PR_NotifyThread (PRThread *thread, PRThread *me)
    27 {
    28     PRBool rv;
    30     PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
    32     _PR_THREAD_LOCK(thread);
    33     PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
    34     if ( !_PR_IS_NATIVE_THREAD(thread) ) {
    35         if (thread->wait.cvar != NULL) {
    36             thread->wait.cvar = NULL;
    38             _PR_SLEEPQ_LOCK(thread->cpu);
    39             /* The notify and timeout can collide; in which case both may
    40              * attempt to delete from the sleepQ; only let one do it.
    41              */
    42             if (thread->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ))
    43                 _PR_DEL_SLEEPQ(thread, PR_TRUE);
    44             _PR_SLEEPQ_UNLOCK(thread->cpu);
    46 	    if (thread->flags & _PR_SUSPENDING) {
    47 		/*
    48 		 * set thread state to SUSPENDED; a Resume operation
    49 		 * on the thread will move it to the runQ
    50 		 */
    51             	thread->state = _PR_SUSPENDED;
    52 		_PR_MISCQ_LOCK(thread->cpu);
    53 		_PR_ADD_SUSPENDQ(thread, thread->cpu);
    54 		_PR_MISCQ_UNLOCK(thread->cpu);
    55             	_PR_THREAD_UNLOCK(thread);
    56 	    } else {
    57             	/* Make thread runnable */
    58             	thread->state = _PR_RUNNABLE;
    59             	_PR_THREAD_UNLOCK(thread);
    61                 _PR_AddThreadToRunQ(me, thread);
    62                 _PR_MD_WAKEUP_WAITER(thread);
    63             }
    65             rv = PR_TRUE;
    66         } else {
    67             /* Thread has already been notified */
    68             _PR_THREAD_UNLOCK(thread);
    69             rv = PR_FALSE;
    70         }
    71     } else { /* If the thread is a native thread */
    72         if (thread->wait.cvar) {
    73             thread->wait.cvar = NULL;
    75 	    if (thread->flags & _PR_SUSPENDING) {
    76 		/*
    77 		 * set thread state to SUSPENDED; a Resume operation
    78 		 * on the thread will enable the thread to run
    79 		 */
    80             	thread->state = _PR_SUSPENDED;
    81 	     } else
    82             	thread->state = _PR_RUNNING;
    83             _PR_THREAD_UNLOCK(thread);
    84             _PR_MD_WAKEUP_WAITER(thread);
    85             rv = PR_TRUE;
    86         } else {
    87             _PR_THREAD_UNLOCK(thread);
    88             rv = PR_FALSE;
    89         }    
    90     }    
    92     return rv;
    93 }
    95 /*
    96  * Notify thread waiting on cvar; called when thread is interrupted
    97  * 	The thread lock is held on entry and released before return
    98  */
    99 void _PR_NotifyLockedThread (PRThread *thread)
   100 {
   101     PRThread *me = _PR_MD_CURRENT_THREAD();
   102     PRCondVar *cvar;
   103     PRThreadPriority pri;
   105     if ( !_PR_IS_NATIVE_THREAD(me))
   106     	PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
   108     cvar = thread->wait.cvar;
   109     thread->wait.cvar = NULL;
   110     _PR_THREAD_UNLOCK(thread);
   112     _PR_CVAR_LOCK(cvar);
   113     _PR_THREAD_LOCK(thread);
   115     if (!_PR_IS_NATIVE_THREAD(thread)) {
   116             _PR_SLEEPQ_LOCK(thread->cpu);
   117             /* The notify and timeout can collide; in which case both may
   118              * attempt to delete from the sleepQ; only let one do it.
   119              */
   120             if (thread->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ))
   121                 _PR_DEL_SLEEPQ(thread, PR_TRUE);
   122             _PR_SLEEPQ_UNLOCK(thread->cpu);
   124 	    /* Make thread runnable */
   125 	    pri = thread->priority;
   126 	    thread->state = _PR_RUNNABLE;
   128 	    PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
   130             _PR_AddThreadToRunQ(me, thread);
   131             _PR_THREAD_UNLOCK(thread);
   133             _PR_MD_WAKEUP_WAITER(thread);
   134     } else {
   135 	    if (thread->flags & _PR_SUSPENDING) {
   136 		/*
   137 		 * set thread state to SUSPENDED; a Resume operation
   138 		 * on the thread will enable the thread to run
   139 		 */
   140             	thread->state = _PR_SUSPENDED;
   141 	     } else
   142             	thread->state = _PR_RUNNING;
   143             _PR_THREAD_UNLOCK(thread);
   144             _PR_MD_WAKEUP_WAITER(thread);
   145     }    
   147     _PR_CVAR_UNLOCK(cvar);
   148     return;
   149 }
   151 /*
   152 ** Make the given thread wait for the given condition variable
   153 */
   154 PRStatus _PR_WaitCondVar(
   155     PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout)
   156 {
   157     PRIntn is;
   158     PRStatus rv = PR_SUCCESS;
   160     PR_ASSERT(thread == _PR_MD_CURRENT_THREAD());
   161     PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
   163 #ifdef _PR_GLOBAL_THREADS_ONLY
   164     if (_PR_PENDING_INTERRUPT(thread)) {
   165         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   166         thread->flags &= ~_PR_INTERRUPT;
   167         return PR_FAILURE;
   168     }
   170     thread->wait.cvar = cvar;
   171     lock->owner = NULL;
   172     _PR_MD_WAIT_CV(&cvar->md,&lock->ilock, timeout);
   173     thread->wait.cvar = NULL;
   174     lock->owner = thread;
   175     if (_PR_PENDING_INTERRUPT(thread)) {
   176         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   177         thread->flags &= ~_PR_INTERRUPT;
   178         return PR_FAILURE;
   179     }
   181     return PR_SUCCESS;
   182 #else  /* _PR_GLOBAL_THREADS_ONLY */
   184     if ( !_PR_IS_NATIVE_THREAD(thread))
   185     	_PR_INTSOFF(is);
   187     _PR_CVAR_LOCK(cvar);
   188     _PR_THREAD_LOCK(thread);
   190     if (_PR_PENDING_INTERRUPT(thread)) {
   191         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   192         thread->flags &= ~_PR_INTERRUPT;
   193     	_PR_CVAR_UNLOCK(cvar);
   194     	_PR_THREAD_UNLOCK(thread);
   195     	if ( !_PR_IS_NATIVE_THREAD(thread))
   196     		_PR_INTSON(is);
   197         return PR_FAILURE;
   198     }
   200     thread->state = _PR_COND_WAIT;
   201     thread->wait.cvar = cvar;
   203     /*
   204     ** Put the caller thread on the condition variable's wait Q
   205     */
   206     PR_APPEND_LINK(&thread->waitQLinks, &cvar->condQ);
   208     /* Note- for global scope threads, we don't put them on the
   209      *       global sleepQ, so each global thread must put itself
   210      *       to sleep only for the time it wants to.
   211      */
   212     if ( !_PR_IS_NATIVE_THREAD(thread) ) {
   213         _PR_SLEEPQ_LOCK(thread->cpu);
   214         _PR_ADD_SLEEPQ(thread, timeout);
   215         _PR_SLEEPQ_UNLOCK(thread->cpu);
   216     }
   217     _PR_CVAR_UNLOCK(cvar);
   218     _PR_THREAD_UNLOCK(thread);
   220     /* 
   221     ** Release lock protecting the condition variable and thereby giving time 
   222     ** to the next thread which can potentially notify on the condition variable
   223     */
   224     PR_Unlock(lock);
   226     PR_LOG(_pr_cvar_lm, PR_LOG_MIN,
   227 	   ("PR_Wait: cvar=%p waiting for %d", cvar, timeout));
   229     rv = _PR_MD_WAIT(thread, timeout);
   231     _PR_CVAR_LOCK(cvar);
   232     PR_REMOVE_LINK(&thread->waitQLinks);
   233     _PR_CVAR_UNLOCK(cvar);
   235     PR_LOG(_pr_cvar_lm, PR_LOG_MIN,
   236 	   ("PR_Wait: cvar=%p done waiting", cvar));
   238     if ( !_PR_IS_NATIVE_THREAD(thread))
   239     	_PR_INTSON(is);
   241     /* Acquire lock again that we had just relinquished */
   242     PR_Lock(lock);
   244     if (_PR_PENDING_INTERRUPT(thread)) {
   245         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   246         thread->flags &= ~_PR_INTERRUPT;
   247         return PR_FAILURE;
   248     }
   250     return rv;
   251 #endif  /* _PR_GLOBAL_THREADS_ONLY */
   252 }
   254 void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me)
   255 {
   256 #ifdef _PR_GLOBAL_THREADS_ONLY
   257     _PR_MD_NOTIFY_CV(&cvar->md, &cvar->lock->ilock);
   258 #else  /* _PR_GLOBAL_THREADS_ONLY */
   260     PRCList *q;
   261     PRIntn is;
   263     if ( !_PR_IS_NATIVE_THREAD(me))
   264     	_PR_INTSOFF(is);
   265     PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
   267     _PR_CVAR_LOCK(cvar);
   268     q = cvar->condQ.next;
   269     while (q != &cvar->condQ) {
   270         PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("_PR_NotifyCondVar: cvar=%p", cvar));
   271         if (_PR_THREAD_CONDQ_PTR(q)->wait.cvar)  {
   272             if (_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me) == PR_TRUE)
   273                 break;
   274         }
   275         q = q->next;
   276     }
   277     _PR_CVAR_UNLOCK(cvar);
   279     if ( !_PR_IS_NATIVE_THREAD(me))
   280     	_PR_INTSON(is);
   282 #endif  /* _PR_GLOBAL_THREADS_ONLY */
   283 }
   285 /*
   286 ** Cndition variable debugging log info.
   287 */
   288 PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen)
   289 {
   290     PRUint32 nb;
   292     if (cvar->lock->owner) {
   293 	nb = PR_snprintf(buf, buflen, "[%p] owner=%ld[%p]",
   294 			 cvar, cvar->lock->owner->id, cvar->lock->owner);
   295     } else {
   296 	nb = PR_snprintf(buf, buflen, "[%p]", cvar);
   297     }
   298     return nb;
   299 }
   301 /*
   302 ** Expire condition variable waits that are ready to expire. "now" is the current
   303 ** time.
   304 */
   305 void _PR_ClockInterrupt(void)
   306 {
   307     PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
   308     _PRCPU *cpu = me->cpu;
   309     PRIntervalTime elapsed, now;
   311     PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
   312     /* Figure out how much time elapsed since the last clock tick */
   313     now = PR_IntervalNow();
   314     elapsed = now - cpu->last_clock;
   315     cpu->last_clock = now;
   317     PR_LOG(_pr_clock_lm, PR_LOG_MAX,
   318 	   ("ExpireWaits: elapsed=%lld usec", elapsed));
   320     while(1) {
   321         _PR_SLEEPQ_LOCK(cpu);
   322         if (_PR_SLEEPQ(cpu).next == &_PR_SLEEPQ(cpu)) {
   323             _PR_SLEEPQ_UNLOCK(cpu);
   324             break;
   325         }
   327         thread = _PR_THREAD_PTR(_PR_SLEEPQ(cpu).next);
   328         PR_ASSERT(thread->cpu == cpu);
   330         if (elapsed < thread->sleep) {
   331             thread->sleep -= elapsed;
   332             _PR_SLEEPQMAX(thread->cpu) -= elapsed;
   333             _PR_SLEEPQ_UNLOCK(cpu);
   334             break;
   335         }
   336         _PR_SLEEPQ_UNLOCK(cpu);
   338         PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));
   340         _PR_THREAD_LOCK(thread);
   342         if (thread->cpu != cpu) {
   343             /*
   344             ** The thread was switched to another CPU
   345             ** between the time we unlocked the sleep
   346             ** queue and the time we acquired the thread
   347             ** lock, so it is none of our business now.
   348             */
   349             _PR_THREAD_UNLOCK(thread);
   350             continue;
   351         }
   353         /*
   354         ** Consume this sleeper's amount of elapsed time from the elapsed
   355         ** time value. The next remaining piece of elapsed time will be
   356         ** available for the next sleeping thread's timer.
   357         */
   358         _PR_SLEEPQ_LOCK(cpu);
   359         PR_ASSERT(!(thread->flags & _PR_ON_PAUSEQ));
   360         if (thread->flags & _PR_ON_SLEEPQ) {
   361             _PR_DEL_SLEEPQ(thread, PR_FALSE);
   362             elapsed -= thread->sleep;
   363             _PR_SLEEPQ_UNLOCK(cpu);
   364         } else {
   365             /* Thread was already handled; Go get another one */
   366             _PR_SLEEPQ_UNLOCK(cpu);
   367             _PR_THREAD_UNLOCK(thread);
   368             continue;
   369         }
   371         /* Notify the thread waiting on the condition variable */
   372         if (thread->flags & _PR_SUSPENDING) {
   373 		PR_ASSERT((thread->state == _PR_IO_WAIT) ||
   374 				(thread->state == _PR_COND_WAIT));
   375             /*
   376             ** Thread is suspended and its condition timeout
   377             ** expired. Transfer thread from sleepQ to suspendQ.
   378             */
   379             thread->wait.cvar = NULL;
   380             _PR_MISCQ_LOCK(cpu);
   381             thread->state = _PR_SUSPENDED;
   382             _PR_ADD_SUSPENDQ(thread, cpu);
   383             _PR_MISCQ_UNLOCK(cpu);
   384         } else {
   385             if (thread->wait.cvar) {
   386                 PRThreadPriority pri;
   388                 /* Do work very similar to what _PR_NotifyThread does */
   389                 PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );
   391                 /* Make thread runnable */
   392                 pri = thread->priority;
   393                 thread->state = _PR_RUNNABLE;
   394                 PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
   396                 PR_ASSERT(thread->cpu == cpu);
   397                 _PR_RUNQ_LOCK(cpu);
   398                 _PR_ADD_RUNQ(thread, cpu, pri);
   399                 _PR_RUNQ_UNLOCK(cpu);
   401                 if (pri > me->priority)
   402                     _PR_SET_RESCHED_FLAG();
   404                 thread->wait.cvar = NULL;
   406                 _PR_MD_WAKEUP_WAITER(thread);
   408             } else if (thread->io_pending == PR_TRUE) {
   409                 /* Need to put IO sleeper back on runq */
   410                 int pri = thread->priority;
   412                 thread->io_suspended = PR_TRUE;
   413 #ifdef WINNT
   414 				/*
   415 				 * For NT, record the cpu on which I/O was issued
   416 				 * I/O cancellation is done on the same cpu
   417 				 */
   418                 thread->md.thr_bound_cpu = cpu;
   419 #endif
   421 				PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
   422                 PR_ASSERT(thread->cpu == cpu);
   423                 thread->state = _PR_RUNNABLE;
   424                 _PR_RUNQ_LOCK(cpu);
   425                 _PR_ADD_RUNQ(thread, cpu, pri);
   426                 _PR_RUNQ_UNLOCK(cpu);
   427             }
   428         }
   429         _PR_THREAD_UNLOCK(thread);
   430     }
   431 }
   433 /************************************************************************/
   435 /*
   436 ** Create a new condition variable.
   437 ** 	"lock" is the lock to use with the condition variable.
   438 **
   439 ** Condition variables are synchronization objects that threads can use
   440 ** to wait for some condition to occur.
   441 **
   442 ** This may fail if memory is tight or if some operating system resource
   443 ** is low.
   444 */
   445 PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
   446 {
   447     PRCondVar *cvar;
   449     cvar = PR_NEWZAP(PRCondVar);
   450     if (cvar) {
   451         if (_PR_InitCondVar(cvar, lock) != PR_SUCCESS) {
   452             PR_DELETE(cvar);
   453             return NULL;
   454         }
   455     } else {
   456         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   457     }
   458     return cvar;
   459 }
   461 PRStatus _PR_InitCondVar(PRCondVar *cvar, PRLock *lock)
   462 {
   463     PR_ASSERT(lock != NULL);
   465 #ifdef _PR_GLOBAL_THREADS_ONLY
   466     if(_PR_MD_NEW_CV(&cvar->md)) {
   467         PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
   468         return PR_FAILURE;
   469     }
   470 #endif
   471     if (_PR_MD_NEW_LOCK(&(cvar->ilock)) != PR_SUCCESS) {
   472         PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
   473         return PR_FAILURE;
   474     }
   475     cvar->lock = lock;
   476     PR_INIT_CLIST(&cvar->condQ);
   477     return PR_SUCCESS;
   478 }
   480 /*
   481 ** Destroy a condition variable. There must be no thread
   482 ** waiting on the condvar. The caller is responsible for guaranteeing
   483 ** that the condvar is no longer in use.
   484 **
   485 */
   486 PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
   487 {
   488     _PR_FreeCondVar(cvar);
   489     PR_DELETE(cvar);
   490 }
   492 void _PR_FreeCondVar(PRCondVar *cvar)
   493 {
   494     PR_ASSERT(cvar->condQ.next == &cvar->condQ);
   496 #ifdef _PR_GLOBAL_THREADS_ONLY
   497     _PR_MD_FREE_CV(&cvar->md);
   498 #endif
   499     _PR_MD_FREE_LOCK(&(cvar->ilock));
   500 }
   502 /*
   503 ** Wait for a notify on the condition variable. Sleep for "tiemout" amount
   504 ** of ticks (if "timeout" is zero then the sleep is indefinite). While
   505 ** the thread is waiting it unlocks lock. When the wait has
   506 ** finished the thread regains control of the condition variable after
   507 ** locking the associated lock.
   508 **
   509 ** The thread waiting on the condvar will be resumed when the condvar is
   510 ** notified (assuming the thread is the next in line to receive the
   511 ** notify) or when the timeout elapses.
   512 **
   513 ** Returns PR_FAILURE if the caller has not locked the lock associated
   514 ** with the condition variable or the thread has been interrupted.
   515 */
   516 extern PRThread *suspendAllThread;
   517 PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
   518 {
   519     PRThread *me = _PR_MD_CURRENT_THREAD();
   521 	PR_ASSERT(cvar->lock->owner == me);
   522 	PR_ASSERT(me != suspendAllThread);
   523     	if (cvar->lock->owner != me) return PR_FAILURE;
   525 	return _PR_WaitCondVar(me, cvar, cvar->lock, timeout);
   526 }
   528 /*
   529 ** Notify the highest priority thread waiting on the condition
   530 ** variable. If a thread is waiting on the condition variable (using
   531 ** PR_Wait) then it is awakened and begins waiting on the lock.
   532 */
   533 PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar)
   534 {
   535     PRThread *me = _PR_MD_CURRENT_THREAD();
   537     PR_ASSERT(cvar->lock->owner == me);
   538     PR_ASSERT(me != suspendAllThread);
   539     if (cvar->lock->owner != me) return PR_FAILURE;
   541     _PR_NotifyCondVar(cvar, me);
   542     return PR_SUCCESS;
   543 }
   545 /*
   546 ** Notify all of the threads waiting on the condition variable. All of
   547 ** threads are notified in turn. The highest priority thread will
   548 ** probably acquire the lock.
   549 */
   550 PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
   551 {
   552     PRCList *q;
   553     PRIntn is;
   554     PRThread *me = _PR_MD_CURRENT_THREAD();
   556     PR_ASSERT(cvar->lock->owner == me);
   557     if (cvar->lock->owner != me) return PR_FAILURE;
   559 #ifdef _PR_GLOBAL_THREADS_ONLY
   560     _PR_MD_NOTIFYALL_CV(&cvar->md, &cvar->lock->ilock);
   561     return PR_SUCCESS;
   562 #else  /* _PR_GLOBAL_THREADS_ONLY */
   563     if ( !_PR_IS_NATIVE_THREAD(me))
   564     	_PR_INTSOFF(is);
   565     _PR_CVAR_LOCK(cvar);
   566     q = cvar->condQ.next;
   567     while (q != &cvar->condQ) {
   568 		PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar));
   569 		_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
   570 		q = q->next;
   571     }
   572     _PR_CVAR_UNLOCK(cvar);
   573     if (!_PR_IS_NATIVE_THREAD(me))
   574     	_PR_INTSON(is);
   576     return PR_SUCCESS;
   577 #endif  /* _PR_GLOBAL_THREADS_ONLY */
   578 }
   581 /*********************************************************************/
   582 /*********************************************************************/
   583 /********************ROUTINES FOR DCE EMULATION***********************/
   584 /*********************************************************************/
   585 /*********************************************************************/
   586 #include "prpdce.h"
   588 PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)
   589 {
   590     PRCondVar *cvar = PR_NEWZAP(PRCondVar);
   591     if (NULL != cvar)
   592     {
   593         if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE)
   594         {
   595 		    PR_DELETE(cvar); cvar = NULL;
   596 	    }
   597 	    else
   598 	    {
   599 	        PR_INIT_CLIST(&cvar->condQ);
   600             cvar->lock = _PR_NAKED_CV_LOCK;
   601 	    }
   603     }
   604     return cvar;
   605 }
   607 PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar)
   608 {
   609     PR_ASSERT(cvar->condQ.next == &cvar->condQ);
   610     PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
   612     _PR_MD_FREE_LOCK(&(cvar->ilock));
   614     PR_DELETE(cvar);
   615 }
   617 PR_IMPLEMENT(PRStatus) PRP_NakedWait(
   618 	PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout)
   619 {
   620     PRThread *me = _PR_MD_CURRENT_THREAD();
   621     PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
   622 	return _PR_WaitCondVar(me, cvar, lock, timeout);
   623 }  /* PRP_NakedWait */
   625 PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar)
   626 {
   627     PRThread *me = _PR_MD_CURRENT_THREAD();
   628     PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
   630     _PR_NotifyCondVar(cvar, me);
   632     return PR_SUCCESS;
   633 }  /* PRP_NakedNotify */
   635 PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar)
   636 {
   637     PRCList *q;
   638     PRIntn is;
   639     PRThread *me = _PR_MD_CURRENT_THREAD();
   640     PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
   642     if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
   643 	_PR_MD_LOCK( &(cvar->ilock) );
   644     q = cvar->condQ.next;
   645     while (q != &cvar->condQ) {
   646 		PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar));
   647 		_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
   648 		q = q->next;
   649     }
   650 	_PR_MD_UNLOCK( &(cvar->ilock) );
   651     if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
   653     return PR_SUCCESS;
   654 }  /* PRP_NakedBroadcast */

mercurial