PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout) { PRStatus rv; PRInt16 saved_entries; pthread_t saved_owner; PR_ASSERT(mon != NULL); /* we'd better be locked */ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex)); /* and the entries better be positive */ PR_ASSERT(mon->entryCount > 0); /* and it better be by us */ PR_ASSERT(pthread_equal(mon->owner, pthread_self())); /* tuck these away 'till later */ saved_entries = mon->entryCount; mon->entryCount = 0; _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner); _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); rv = PR_WaitCondVar(mon->cvar, timeout); /* reinstate the intresting information */ mon->entryCount = saved_entries; _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner); return rv; } /* PR_Wait */
PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout) { PRStatus rv; PRUint32 saved_entries; pthread_t saved_owner; PR_ASSERT(mon != NULL); rv = pthread_mutex_lock(&mon->lock); PR_ASSERT(0 == rv); /* the entries better be positive */ PR_ASSERT(mon->entryCount > 0); /* and it better be owned by us */ PR_ASSERT(pthread_equal(mon->owner, pthread_self())); /* tuck these away 'till later */ saved_entries = mon->entryCount; mon->entryCount = 0; _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner); _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); /* * If we have pending notifies, post them now. * * This is not optimal. We're going to post these notifies * while we're holding the lock. That means on MP systems * that they are going to collide for the lock that we will * hold until we actually wait. */ if (0 != mon->notifyTimes) { pt_PostNotifiesFromMonitor(&mon->waitCV, mon->notifyTimes); mon->notifyTimes = 0; } rv = pthread_cond_signal(&mon->entryCV); PR_ASSERT(0 == rv); if (timeout == PR_INTERVAL_NO_TIMEOUT) rv = pthread_cond_wait(&mon->waitCV, &mon->lock); else rv = pt_TimedWait(&mon->waitCV, &mon->lock, timeout); PR_ASSERT(0 == rv); while (mon->entryCount != 0) { rv = pthread_cond_wait(&mon->entryCV, &mon->lock); PR_ASSERT(0 == rv); } PR_ASSERT(0 == mon->notifyTimes); /* reinstate the interesting information */ mon->entryCount = saved_entries; _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner); rv = pthread_mutex_unlock(&mon->lock); PR_ASSERT(0 == rv); return rv; } /* PR_Wait */
PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon) { pthread_t self = pthread_self(); PRIntn rv; PR_ASSERT(mon != NULL); rv = pthread_mutex_lock(&mon->lock); PR_ASSERT(0 == rv); if (mon->entryCount != 0) { if (pthread_equal(mon->owner, self)) goto done; while (mon->entryCount != 0) { rv = pthread_cond_wait(&mon->entryCV, &mon->lock); PR_ASSERT(0 == rv); } } /* and now I have the monitor */ PR_ASSERT(0 == mon->notifyTimes); PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner)); _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner); done: mon->entryCount += 1; rv = pthread_mutex_unlock(&mon->lock); PR_ASSERT(0 == rv); } /* PR_EnterMonitor */
PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon) { pthread_t self = pthread_self(); PR_ASSERT(mon != NULL); /* * This is safe only if mon->owner (a pthread_t) can be * read in one instruction. Perhaps mon->owner should be * a "PRThread *"? */ if (!pthread_equal(mon->owner, self)) { PR_Lock(&mon->lock); /* and now I have the lock */ PR_ASSERT(0 == mon->entryCount); PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner)); _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner); } mon->entryCount += 1; } /* PR_EnterMonitor */