home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- /*
- ** File: ptsynch.c
- ** Descritpion: Implemenation for thread synchronization using pthreads
- ** Exports: prlock.h, prcvar.h, prmon.h, prcmon.h
- */
-
- #if defined(_PR_PTHREADS)
-
- #include "primpl.h"
- #include "obsolete/prsem.h"
-
- #include <string.h>
- #include <pthread.h>
- #include <sys/time.h>
-
- static pthread_condattr_t _pt_cvar_attr;
-
- #if defined(DEBUG) && defined(_PR_DCETHREADS)
- static pthread_t pt_zero_tid; /* a null pthread_t (pthread_t is a struct
- * in DCE threads) to compare with */
- #endif
-
- /**************************************************************/
- /**************************************************************/
- /*****************************LOCKS****************************/
- /**************************************************************/
- /**************************************************************/
-
- void _PR_InitLocks(void)
- {
- int rv = PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
- PR_ASSERT(0 == rv);
- _PR_MD_INIT_LOCKS();
- }
-
- static void pt_PostNotifies(PRLock *lock, PRBool unlock)
- {
- PRIntn index, rv;
- _PT_Notified post;
- _PT_Notified *notified, *prev = NULL;
- /*
- * Time to actually notify any conditions that were affected
- * while the lock was held. Get a copy of the list that's in
- * the lock structure and then zero the original. If it's
- * linked to other such structures, we own that storage.
- */
- post = lock->notified; /* a safe copy; we own the lock */
-
- #if defined(DEBUG)
- memset(&lock->notified, 0, sizeof(_PT_Notified)); /* reset */
- #else
- lock->notified.length = 0; /* these are really sufficient */
- lock->notified.link = NULL;
- #endif
-
- /* should (may) we release lock before notifying? */
- if (unlock)
- {
- rv = pthread_mutex_unlock(&lock->mutex);
- PR_ASSERT(0 == rv);
- }
-
- notified = &post; /* this is where we start */
- do
- {
- for (index = 0; index < notified->length; ++index)
- {
- PR_ASSERT(NULL != notified->cv[index].cv);
- PR_ASSERT(0 != notified->cv[index].times);
- if (-1 == notified->cv[index].times)
- {
- rv = pthread_cond_broadcast(¬ified->cv[index].cv->cv);
- PR_ASSERT(0 == rv);
- }
- else
- {
- while (notified->cv[index].times-- > 0)
- {
- rv = pthread_cond_signal(¬ified->cv[index].cv->cv);
- PR_ASSERT(0 == rv);
- }
- }
- }
- prev = notified;
- notified = notified->link;
- if (&post != prev) PR_DELETE(prev);
- } while (NULL != notified);
- } /* pt_PostNotifies */
-
- PR_IMPLEMENT(PRLock*) PR_NewLock(void)
- {
- PRIntn rv;
- PRLock *lock;
-
- if (!_pr_initialized) _PR_ImplicitInitialization();
-
- lock = PR_NEWZAP(PRLock);
- if (lock != NULL)
- {
- pthread_mutexattr_t mattr;
- rv = PTHREAD_MUTEXATTR_INIT(&mattr);
- PR_ASSERT(0 == rv);
- rv = PTHREAD_MUTEX_INIT(lock->mutex, mattr);
- PR_ASSERT(0 == rv);
- rv = PTHREAD_MUTEXATTR_DESTROY(&mattr);
- PR_ASSERT(0 == rv);
- }
- return lock;
- } /* PR_NewLock */
-
- PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
- {
- PRIntn rv;
- PR_ASSERT(NULL != lock);
- PR_ASSERT(PTHREAD_THR_HANDLE_IS_ZERO(lock->owner));
- PR_ASSERT(0 == lock->notified.length);
- PR_ASSERT(NULL == lock->notified.link);
- rv = pthread_mutex_destroy(&lock->mutex);
- PR_ASSERT(0 == rv);
- #if defined(DEBUG)
- memset(lock, 0xaf, sizeof(PRLock));
- #endif
- PR_DELETE(lock);
- } /* PR_DestroyLock */
-
- PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
- {
- PRIntn rv;
- PR_ASSERT(lock != NULL);
- rv = pthread_mutex_lock(&lock->mutex);
- PR_ASSERT(0 == rv);
- PR_ASSERT(0 == lock->notified.length);
- PR_ASSERT(NULL == lock->notified.link);
- PR_ASSERT(PTHREAD_THR_HANDLE_IS_ZERO(lock->owner));
- PTHREAD_COPY_THR_HANDLE(pthread_self(), lock->owner);
- } /* PR_Lock */
-
- PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
- {
- PRIntn rv;
-
- PR_ASSERT(lock != NULL);
- PR_ASSERT(PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
- PR_ASSERT(pthread_equal(lock->owner, pthread_self()));
-
- if (!pthread_equal(lock->owner, pthread_self()))
- return PR_FAILURE;
-
- PTHREAD_ZERO_THR_HANDLE(lock->owner);
- if (0 == lock->notified.length) /* shortcut */
- {
- rv = pthread_mutex_unlock(&lock->mutex);
- PR_ASSERT(0 == rv);
- }
- else pt_PostNotifies(lock, PR_TRUE);
-
- return PR_SUCCESS;
- } /* PR_Unlock */
-
-
- /**************************************************************/
- /**************************************************************/
- /***************************CONDITIONS*************************/
- /**************************************************************/
- /**************************************************************/
-
-
- /*
- * This code is used to compute the absolute time for the wakeup.
- * It's moderately ugly, so it's defined here and called in a
- * couple of places.
- */
- #define PT_NANOPERMICRO 1000UL
- #define PT_BILLION 1000000000UL
-
- static PRIntn pt_TimedWait(
- pthread_cond_t *cv, pthread_mutex_t *ml, PRIntervalTime timeout)
- {
- int rv;
- struct timeval now;
- struct timespec tmo;
- PRUint32 ticks = PR_TicksPerSecond();
-
- tmo.tv_sec = (PRInt32)(timeout / ticks);
- tmo.tv_nsec = (PRInt32)(timeout - (tmo.tv_sec * ticks));
- tmo.tv_nsec = (PRInt32)PR_IntervalToMicroseconds(PT_NANOPERMICRO * tmo.tv_nsec);
-
- /* pthreads wants this in absolute time, off we go ... */
- #if defined(SOLARIS) && defined(_SVID_GETTOD)
- (void)gettimeofday(&now);
- #else
- (void)gettimeofday(&now, NULL);
- #endif
- /* that one's usecs, this one's nsecs - grrrr! */
- tmo.tv_sec += now.tv_sec;
- tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec);
- tmo.tv_sec += tmo.tv_nsec / PT_BILLION;
- tmo.tv_nsec %= PT_BILLION;
-
- rv = pthread_cond_timedwait(cv, ml, &tmo);
-
- /* NSPR doesn't report timeouts */
- #ifdef _PR_DCETHREADS
- return (rv == -1 && errno == EAGAIN) ? 0 : rv;
- #else
- return (rv == ETIMEDOUT) ? 0 : rv;
- #endif
- } /* pt_TimedWait */
-
-
- /*
- * Notifies just get posted to the to the protecting mutex. The
- * actual notification is done when the lock is released so that
- * MP systems don't contend for a lock that they can't have.
- */
- static void pt_PostNotifyToCvar(PRCondVar *cvar, PRBool broadcast)
- {
- PRIntn index = 0;
- _PT_Notified *notified = &cvar->lock->notified;
-
- PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
- PR_ASSERT(PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
-
- while (1)
- {
- for (index = 0; index < notified->length; ++index)
- {
- if (notified->cv[index].cv == cvar)
- {
- if (broadcast)
- notified->cv[index].times = -1;
- else if (-1 != notified->cv[index].times)
- notified->cv[index].times += 1;
- goto finished; /* we're finished */
- }
- }
- /* if not full, enter new CV in this array */
- if (notified->length < PT_CV_NOTIFIED_LENGTH) break;
-
- /* if there's no link, create an empty array and link it */
- if (NULL == notified->link)
- notified->link = PR_NEWZAP(_PT_Notified);
- notified = notified->link;
- }
-
- /* A brand new entry in the array */
- notified->cv[index].times = (broadcast) ? -1 : 1;
- notified->cv[index].cv = cvar;
- notified->length += 1;
-
- finished:
- PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
- } /* pt_PostNotifyToCvar */
-
- PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
- {
- PRCondVar *cv = PR_NEW(PRCondVar);
- PR_ASSERT(lock != NULL);
- if (cv != NULL)
- {
- int rv = PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
- PR_ASSERT(0 == rv);
- cv->lock = lock;
- }
- return cv;
- } /* PR_NewCondVar */
-
- PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
- {
- int rv;
- rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
- #if defined(DEBUG)
- memset(cvar, 0xaf, sizeof(PRCondVar));
- #endif
- PR_DELETE(cvar);
- } /* PR_DestroyCondVar */
-
- PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
- {
- PRIntn rv;
- PRThread *thred = PR_CurrentThread();
-
- PR_ASSERT(cvar != NULL);
- /* We'd better be locked */
- PR_ASSERT(PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
- /* and it better be by us */
- PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
-
- if (thred->state & PT_THREAD_ABORTED) goto aborted;
-
- /*
- * The thread waiting is used for PR_Interrupt
- */
- thred->waiting = cvar; /* this is where we're waiting */
-
- /*
- * 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 != cvar->lock->notified.length)
- pt_PostNotifies(cvar->lock, PR_FALSE);
-
- /*
- * We're surrendering the lock, so clear out the owner field.
- */
- PTHREAD_ZERO_THR_HANDLE(cvar->lock->owner);
-
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- rv = pthread_cond_wait(&cvar->cv, &cvar->lock->mutex);
- else
- rv = pt_TimedWait(&cvar->cv, &cvar->lock->mutex, timeout);
-
- /* We just got the lock back - this better be empty */
- PR_ASSERT(PTHREAD_THR_HANDLE_IS_ZERO(cvar->lock->owner));
- PTHREAD_COPY_THR_HANDLE(pthread_self(), cvar->lock->owner);
-
- PR_ASSERT(0 == cvar->lock->notified.length);
- thred->waiting = NULL; /* and now we're not */
- if (thred->state & PT_THREAD_ABORTED) goto aborted;
- return (rv == 0) ? PR_SUCCESS : PR_FAILURE;
-
- aborted:
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- thred->state &= ~PT_THREAD_ABORTED;
- return PR_FAILURE;
- } /* PR_WaitCondVar */
-
- PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar)
- {
- PR_ASSERT(cvar != NULL);
- pt_PostNotifyToCvar(cvar, PR_FALSE);
- return PR_SUCCESS;
- } /* PR_NotifyCondVar */
-
- PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
- {
- PR_ASSERT(cvar != NULL);
- pt_PostNotifyToCvar(cvar, PR_TRUE);
- return PR_SUCCESS;
- } /* PR_NotifyAllCondVar */
-
- /**************************************************************/
- /**************************************************************/
- /***************************MONITORS***************************/
- /**************************************************************/
- /**************************************************************/
-
- PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
- {
- PRMonitor *ml;
-
- if (!_pr_initialized) _PR_ImplicitInitialization();
-
- ml = PR_NEWZAP(PRMonitor);
- if (ml != NULL)
- {
- int rv;
- pthread_mutexattr_t mattr;
- rv = PTHREAD_MUTEXATTR_INIT(&mattr);
- PR_ASSERT(0 == rv);
- rv += PTHREAD_MUTEX_INIT(ml->lock.mutex, mattr);
- PR_ASSERT(0 == rv);
- rv += PTHREAD_MUTEXATTR_DESTROY(&mattr);
- PR_ASSERT(0 == rv);
-
- rv += PTHREAD_COND_INIT(ml->cvar.cv, _pt_cvar_attr);
- PR_ASSERT(0 == rv);
- ml->entryCount = 0;
- ml->cvar.lock = &ml->lock;
- if (0 != rv)
- {
- PR_DELETE(ml);
- ml = NULL;
- }
- }
- return ml;
- } /* PR_NewMonitor */
-
- PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
- {
- PRMonitor* mon = PR_NewMonitor();
- mon->name = name;
- return mon;
- }
-
- PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
- {
- int rv;
- PR_ASSERT(mon != NULL);
- rv = pthread_cond_destroy(&mon->cvar.cv); PR_ASSERT(0 == rv);
- rv = pthread_mutex_destroy(&mon->lock.mutex); PR_ASSERT(0 == rv);
- #if defined(DEBUG)
- memset(mon, 0xaf, sizeof(PRMonitor));
- #endif
- PR_DELETE(mon);
- } /* PR_DestroyMonitor */
-
-
- /* The GC uses this; it is quite arguably a bad interface. I'm just
- * duplicating it for now - XXXMB
- */
- PR_IMPLEMENT(PRInt32) PR_GetMonitorEntryCount(PRMonitor *mon)
- {
- pthread_t self = pthread_self();
- if (pthread_equal(mon->owner, self))
- return mon->entryCount;
- return 0;
- }
-
- PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
- {
- int rv;
- pthread_t self = pthread_self();
-
- PR_ASSERT(mon != NULL);
- rv = pthread_mutex_trylock(&mon->lock.mutex);
- #ifdef _PR_DCETHREADS
- if (1 == rv)
- #else
- if (0 == rv)
- #endif
- {
- /* I now have the lock - I can play in the sandbox */
- /* could/should/would not have gotten lock if entries != 0 */
- PR_ASSERT(0 == mon->entryCount);
- PR_ASSERT(PTHREAD_THR_HANDLE_IS_ZERO(mon->lock.owner));
- PTHREAD_COPY_THR_HANDLE(pthread_self(), mon->lock.owner);
- PTHREAD_COPY_THR_HANDLE(self, mon->owner);
- }
- else
- {
- PR_ASSERT(PT_TRYLOCK_BUSY == rv); /* and if it isn't? */
- /* somebody has it locked - is it me? */
- if (!pthread_equal(mon->owner, self))
- {
- /* it's not me - this should block */
- PR_Lock(&mon->lock);
- /* and now I have the lock */
- PR_ASSERT(0 == mon->entryCount);
- PTHREAD_COPY_THR_HANDLE(self, mon->owner);
- }
- }
- mon->entryCount += 1;
- } /* PR_EnterMonitor */
-
- PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
- {
- pthread_t self = pthread_self();
-
- PR_ASSERT(mon != NULL);
- /* The lock better be that - locked */
- PR_ASSERT(PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
- /* we'd better be the owner */
- PR_ASSERT(pthread_equal(mon->owner, self));
- if (!pthread_equal(mon->owner, self))
- return PR_FAILURE;
-
- /* if it's locked and we have it, then the entries should be > 0 */
- PR_ASSERT(mon->entryCount > 0);
- mon->entryCount -= 1; /* reduce by one */
- if (mon->entryCount == 0)
- {
- /* and if it transitioned to zero - unlock */
- PTHREAD_ZERO_THR_HANDLE(mon->owner); /* make the owner unknown */
- PR_Unlock(&mon->lock);
- }
- return PR_SUCCESS;
- } /* PR_ExitMonitor */
-
- 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(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;
- PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
- PTHREAD_ZERO_THR_HANDLE(mon->owner);
-
- rv = PR_WaitCondVar(&mon->cvar, timeout);
-
- /* reinstate the intresting information */
- mon->entryCount = saved_entries;
- PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);
-
- return rv;
- } /* PR_Wait */
-
- PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
- {
- PR_ASSERT(NULL != mon);
- /* we'd better be locked */
- PR_ASSERT(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()));
-
- pt_PostNotifyToCvar(&mon->cvar, PR_FALSE);
-
- return PR_SUCCESS;
- } /* PR_Notify */
-
- PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
- {
- PR_ASSERT(mon != NULL);
- /* we'd better be locked */
- PR_ASSERT(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()));
-
- pt_PostNotifyToCvar(&mon->cvar, PR_TRUE);
-
- return PR_SUCCESS;
- } /* PR_NotifyAll */
-
- /**************************************************************/
- /**************************************************************/
- /**************************SEMAPHORES**************************/
- /**************************************************************/
- /**************************************************************/
- PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *semaphore)
- {
- static PRBool unwarned = PR_TRUE;
- if (unwarned) unwarned = _PR_Obsolete(
- "PR_PostSem", "locks & condition variables");
- PR_Lock(semaphore->cvar->lock);
- PR_NotifyCondVar(semaphore->cvar);
- semaphore->count += 1;
- PR_Unlock(semaphore->cvar->lock);
- } /* PR_PostSem */
-
- PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *semaphore)
- {
- PRStatus status = PR_SUCCESS;
- static PRBool unwarned = PR_TRUE;
- if (unwarned) unwarned = _PR_Obsolete(
- "PR_WaitSem", "locks & condition variables");
- PR_Lock(semaphore->cvar->lock);
- while ((semaphore->count == 0) && (PR_SUCCESS == status))
- status = PR_WaitCondVar(semaphore->cvar, PR_INTERVAL_NO_TIMEOUT);
- if (PR_SUCCESS == status) semaphore->count -= 1;
- PR_Unlock(semaphore->cvar->lock);
- return status;
- } /* PR_WaitSem */
-
- PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *semaphore)
- {
- static PRBool unwarned = PR_TRUE;
- if (unwarned) unwarned = _PR_Obsolete(
- "PR_DestroySem", "locks & condition variables");
- PR_DestroyLock(semaphore->cvar->lock);
- PR_DestroyCondVar(semaphore->cvar);
- PR_DELETE(semaphore);
- } /* PR_DestroySem */
-
- PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value)
- {
- PRSemaphore *semaphore;
- static PRBool unwarned = PR_TRUE;
- if (!_pr_initialized) _PR_ImplicitInitialization();
-
- if (unwarned) unwarned = _PR_Obsolete(
- "PR_NewSem", "locks & condition variables");
-
- semaphore = PR_NEWZAP(PRSemaphore);
- if (NULL != semaphore)
- {
- PRLock *lock = PR_NewLock();
- if (NULL != lock)
- {
- semaphore->cvar = PR_NewCondVar(lock);
- if (NULL != semaphore->cvar)
- {
- semaphore->count = value;
- return semaphore;
- }
- PR_DestroyLock(lock);
- }
- PR_DELETE(semaphore);
- }
- return NULL;
- }
-
- /**************************************************************/
- /**************************************************************/
- /******************ROUTINES FOR DCE EMULATION******************/
- /**************************************************************/
- /**************************************************************/
-
- #include "prpdce.h"
-
- PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock)
- {
- PRIntn rv = pthread_mutex_trylock(&lock->mutex);
- if (rv == PT_TRYLOCK_SUCCESS)
- {
- PR_ASSERT(PTHREAD_THR_HANDLE_IS_ZERO(lock->owner));
- PTHREAD_COPY_THR_HANDLE(pthread_self(), lock->owner);
- }
- else
- PR_ASSERT(!PTHREAD_THR_HANDLE_IS_ZERO(lock->owner));
- /* XXX set error code? */
- return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE;
- } /* PRP_TryLock */
-
- PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar()
- {
- PRCondVar *cv;
-
- if (!_pr_initialized) _PR_ImplicitInitialization();
-
- cv = PR_NEW(PRCondVar);
- if (cv != NULL)
- {
- int rv;
- rv = PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
- PR_ASSERT(0 == rv);
- cv->lock = _PR_NAKED_CV_LOCK;
- }
- return cv;
- } /* PRP_NewNakedCondVar */
-
- PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar)
- {
- int rv;
- rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
- #if defined(DEBUG)
- memset(cvar, 0xaf, sizeof(PRCondVar));
- #endif
- PR_DELETE(cvar);
- } /* PRP_DestroyNakedCondVar */
-
- PR_IMPLEMENT(PRStatus) PRP_NakedWait(
- PRCondVar *cvar, PRLock *ml, PRIntervalTime timeout)
- {
- PRIntn rv;
- PR_ASSERT(cvar != NULL);
- /* XXX do we really want to assert this in a naked wait? */
- PR_ASSERT(PTHREAD_MUTEX_IS_LOCKED(ml->mutex));
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- rv = pthread_cond_wait(&cvar->cv, &ml->mutex);
- else
- rv = pt_TimedWait(&cvar->cv, &ml->mutex, timeout);
- return (rv == 0) ? PR_SUCCESS : PR_FAILURE;
- } /* PRP_NakedWait */
-
- PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar)
- {
- int rv;
- PR_ASSERT(cvar != NULL);
- rv = pthread_cond_signal(&cvar->cv);
- PR_ASSERT(0 == rv);
- return PR_SUCCESS;
- } /* PRP_NakedNotify */
-
- PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar)
- {
- int rv;
- PR_ASSERT(cvar != NULL);
- rv = pthread_cond_broadcast(&cvar->cv);
- PR_ASSERT(0 == rv);
- return PR_SUCCESS;
- } /* PRP_NakedBroadcast */
-
- #endif /* defined(_PR_PTHREADS) */
-
- /* ptsynch.c */
-