Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Unified Diff: nspr/pr/src/pthreads/ptsynch.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « nspr/pr/src/pthreads/ptmisc.c ('k') | nspr/pr/src/pthreads/ptthread.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: nspr/pr/src/pthreads/ptsynch.c
diff --git a/nspr/pr/src/pthreads/ptsynch.c b/nspr/pr/src/pthreads/ptsynch.c
deleted file mode 100644
index 8663a4c719770a92020719beffbb44edc6be36ed..0000000000000000000000000000000000000000
--- a/nspr/pr/src/pthreads/ptsynch.c
+++ /dev/null
@@ -1,1259 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
-** 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_mutexattr_t _pt_mattr;
-static pthread_condattr_t _pt_cvar_attr;
-
-#if defined(DEBUG)
-extern PTDebug pt_debug; /* this is shared between several modules */
-
-#if 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 /* defined(_PR_DCETHREADS) */
-#endif /* defined(DEBUG) */
-
-#if defined(FREEBSD)
-/*
- * On older versions of FreeBSD, pthread_mutex_trylock returns EDEADLK.
- * Newer versions return EBUSY. We still need to support both.
- */
-static int
-pt_pthread_mutex_is_locked(pthread_mutex_t *m)
-{
- int rv = pthread_mutex_trylock(m);
- return (EBUSY == rv || EDEADLK == rv);
-}
-#endif
-
-/**************************************************************/
-/**************************************************************/
-/*****************************LOCKS****************************/
-/**************************************************************/
-/**************************************************************/
-
-void _PR_InitLocks(void)
-{
- int rv;
- rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr);
- PR_ASSERT(0 == rv);
-
-#ifdef LINUX
-#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
- rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP);
- PR_ASSERT(0 == rv);
-#endif
-#endif
-
- rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
- PR_ASSERT(0 == rv);
-}
-
-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)
- {
- PRCondVar *cv = notified->cv[index].cv;
- PR_ASSERT(NULL != cv);
- PR_ASSERT(0 != notified->cv[index].times);
- if (-1 == notified->cv[index].times)
- {
- rv = pthread_cond_broadcast(&cv->cv);
- PR_ASSERT(0 == rv);
- }
- else
- {
- while (notified->cv[index].times-- > 0)
- {
- rv = pthread_cond_signal(&cv->cv);
- PR_ASSERT(0 == rv);
- }
- }
-#if defined(DEBUG)
- pt_debug.cvars_notified += 1;
- if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
- {
- pt_debug.delayed_cv_deletes += 1;
- PR_DestroyCondVar(cv);
- }
-#else /* defined(DEBUG) */
- if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
- PR_DestroyCondVar(cv);
-#endif /* defined(DEBUG) */
- }
- 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)
- {
- rv = _PT_PTHREAD_MUTEX_INIT(lock->mutex, _pt_mattr);
- PR_ASSERT(0 == rv);
- }
-#if defined(DEBUG)
- pt_debug.locks_created += 1;
-#endif
- return lock;
-} /* PR_NewLock */
-
-PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
-{
- PRIntn rv;
- PR_ASSERT(NULL != lock);
- PR_ASSERT(PR_FALSE == lock->locked);
- 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));
- pt_debug.locks_destroyed += 1;
-#endif
- PR_Free(lock);
-} /* PR_DestroyLock */
-
-PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
-{
- /* Nb: PR_Lock must not call PR_GetCurrentThread to access the |id| or
- * |tid| field of the current thread's PRThread structure because
- * _pt_root calls PR_Lock before setting thred->id and thred->tid. */
- 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(PR_FALSE == lock->locked);
- /* Nb: the order of the next two statements is not critical to
- * the correctness of PR_AssertCurrentThreadOwnsLock(), but
- * this particular order makes the assertion more likely to
- * catch errors. */
- lock->owner = pthread_self();
- lock->locked = PR_TRUE;
-#if defined(DEBUG)
- pt_debug.locks_acquired += 1;
-#endif
-} /* PR_Lock */
-
-PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
-{
- pthread_t self = pthread_self();
- PRIntn rv;
-
- PR_ASSERT(lock != NULL);
- PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
- PR_ASSERT(PR_TRUE == lock->locked);
- PR_ASSERT(pthread_equal(lock->owner, self));
-
- if (!lock->locked || !pthread_equal(lock->owner, self))
- return PR_FAILURE;
-
- lock->locked = PR_FALSE;
- if (0 == lock->notified.length) /* shortcut */
- {
- rv = pthread_mutex_unlock(&lock->mutex);
- PR_ASSERT(0 == rv);
- }
- else pt_PostNotifies(lock, PR_TRUE);
-
-#if defined(DEBUG)
- pt_debug.locks_released += 1;
-#endif
- return PR_SUCCESS;
-} /* PR_Unlock */
-
-PR_IMPLEMENT(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock)
-{
- /* Nb: the order of the |locked| and |owner==me| checks is not critical
- * to the correctness of PR_AssertCurrentThreadOwnsLock(), but
- * this particular order makes the assertion more likely to
- * catch errors. */
- PR_ASSERT(lock->locked && pthread_equal(lock->owner, pthread_self()));
-}
-
-/**************************************************************/
-/**************************************************************/
-/***************************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 ... */
- (void)GETTIMEOFDAY(&now);
- /* 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
- if (rv == -1) return (errno == EAGAIN) ? 0 : errno;
- else return rv;
-#else
- return (rv == ETIMEDOUT) ? 0 : rv;
-#endif
-} /* pt_TimedWait */
-
-
-/*
- * Notifies just get posted 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(PR_TRUE == cvar->lock->locked);
- PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
- PR_ASSERT(_PT_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;
- return; /* 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 */
- (void)PR_ATOMIC_INCREMENT(&cvar->notify_pending);
- notified->cv[index].times = (broadcast) ? -1 : 1;
- notified->cv[index].cv = cvar;
- notified->length += 1;
-} /* pt_PostNotifyToCvar */
-
-PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
-{
- PRCondVar *cv = PR_NEW(PRCondVar);
- PR_ASSERT(lock != NULL);
- if (cv != NULL)
- {
- int rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
- PR_ASSERT(0 == rv);
- if (0 == rv)
- {
- cv->lock = lock;
- cv->notify_pending = 0;
-#if defined(DEBUG)
- pt_debug.cvars_created += 1;
-#endif
- }
- else
- {
- PR_DELETE(cv);
- cv = NULL;
- }
- }
- return cv;
-} /* PR_NewCondVar */
-
-PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
-{
- if (0 > PR_ATOMIC_DECREMENT(&cvar->notify_pending))
- {
- PRIntn rv = pthread_cond_destroy(&cvar->cv);
-#if defined(DEBUG)
- PR_ASSERT(0 == rv);
- memset(cvar, 0xaf, sizeof(PRCondVar));
- pt_debug.cvars_destroyed += 1;
-#else
- (void)rv;
-#endif
- PR_Free(cvar);
- }
-} /* PR_DestroyCondVar */
-
-PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
-{
- PRIntn rv;
- PRThread *thred = PR_GetCurrentThread();
-
- PR_ASSERT(cvar != NULL);
- /* We'd better be locked */
- PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
- PR_ASSERT(PR_TRUE == cvar->lock->locked);
- /* and it better be by us */
- PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
-
- if (_PT_THREAD_INTERRUPTED(thred)) 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 locked field.
- */
- cvar->lock->locked = PR_FALSE;
-
- 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(PR_FALSE == cvar->lock->locked);
- cvar->lock->locked = PR_TRUE;
- cvar->lock->owner = pthread_self();
-
- PR_ASSERT(0 == cvar->lock->notified.length);
- thred->waiting = NULL; /* and now we're not */
- if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
- if (rv != 0)
- {
- _PR_MD_MAP_DEFAULT_ERROR(rv);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-
-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***************************/
-/**************************************************************/
-/**************************************************************/
-
-/*
- * Notifies just get posted to the monitor. The actual notification is done
- * when the monitor is fully exited so that MP systems don't contend for a
- * monitor that they can't enter.
- */
-static void pt_PostNotifyToMonitor(PRMonitor *mon, PRBool broadcast)
-{
- PR_ASSERT(NULL != mon);
- PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mon);
-
- /* mon->notifyTimes is protected by the monitor, so we don't need to
- * acquire mon->lock.
- */
- if (broadcast)
- mon->notifyTimes = -1;
- else if (-1 != mon->notifyTimes)
- mon->notifyTimes += 1;
-} /* pt_PostNotifyToMonitor */
-
-static void pt_PostNotifiesFromMonitor(pthread_cond_t *cv, PRIntn times)
-{
- PRIntn rv;
-
- /*
- * Time to actually notify any waits that were affected while the monitor
- * was entered.
- */
- PR_ASSERT(NULL != cv);
- PR_ASSERT(0 != times);
- if (-1 == times)
- {
- rv = pthread_cond_broadcast(cv);
- PR_ASSERT(0 == rv);
- }
- else
- {
- while (times-- > 0)
- {
- rv = pthread_cond_signal(cv);
- PR_ASSERT(0 == rv);
- }
- }
-} /* pt_PostNotifiesFromMonitor */
-
-PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
-{
- PRMonitor *mon;
- int rv;
-
- if (!_pr_initialized) _PR_ImplicitInitialization();
-
- mon = PR_NEWZAP(PRMonitor);
- if (mon == NULL)
- {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return NULL;
- }
-
- rv = _PT_PTHREAD_MUTEX_INIT(mon->lock, _pt_mattr);
- PR_ASSERT(0 == rv);
- if (0 != rv)
- goto error1;
-
- _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
-
- rv = _PT_PTHREAD_COND_INIT(mon->entryCV, _pt_cvar_attr);
- PR_ASSERT(0 == rv);
- if (0 != rv)
- goto error2;
-
- rv = _PT_PTHREAD_COND_INIT(mon->waitCV, _pt_cvar_attr);
- PR_ASSERT(0 == rv);
- if (0 != rv)
- goto error3;
-
- mon->notifyTimes = 0;
- mon->entryCount = 0;
- mon->refCount = 1;
- mon->name = NULL;
- return mon;
-
-error3:
- pthread_cond_destroy(&mon->entryCV);
-error2:
- pthread_mutex_destroy(&mon->lock);
-error1:
- PR_Free(mon);
- _PR_MD_MAP_DEFAULT_ERROR(rv);
- return NULL;
-} /* PR_NewMonitor */
-
-PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
-{
- PRMonitor* mon = PR_NewMonitor();
- if (mon)
- mon->name = name;
- return mon;
-}
-
-PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
-{
- int rv;
-
- PR_ASSERT(mon != NULL);
- if (PR_ATOMIC_DECREMENT(&mon->refCount) == 0)
- {
- rv = pthread_cond_destroy(&mon->waitCV); PR_ASSERT(0 == rv);
- rv = pthread_cond_destroy(&mon->entryCV); PR_ASSERT(0 == rv);
- rv = pthread_mutex_destroy(&mon->lock); PR_ASSERT(0 == rv);
-#if defined(DEBUG)
- memset(mon, 0xaf, sizeof(PRMonitor));
-#endif
- PR_Free(mon);
- }
-} /* PR_DestroyMonitor */
-
-/* The GC uses this; it is quite arguably a bad interface. I'm just
- * duplicating it for now - XXXMB
- */
-PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
-{
- pthread_t self = pthread_self();
- PRIntn rv;
- PRIntn count = 0;
-
- rv = pthread_mutex_lock(&mon->lock);
- PR_ASSERT(0 == rv);
- if (pthread_equal(mon->owner, self))
- count = mon->entryCount;
- rv = pthread_mutex_unlock(&mon->lock);
- PR_ASSERT(0 == rv);
- return count;
-}
-
-PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
-{
-#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
- PRIntn rv;
-
- rv = pthread_mutex_lock(&mon->lock);
- PR_ASSERT(0 == rv);
- PR_ASSERT(mon->entryCount != 0 &&
- pthread_equal(mon->owner, pthread_self()));
- rv = pthread_mutex_unlock(&mon->lock);
- PR_ASSERT(0 == rv);
-#endif
-}
-
-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(PRStatus) PR_ExitMonitor(PRMonitor *mon)
-{
- pthread_t self = pthread_self();
- PRIntn rv;
- PRBool notifyEntryWaiter = PR_FALSE;
- PRIntn notifyTimes = 0;
-
- PR_ASSERT(mon != NULL);
- rv = pthread_mutex_lock(&mon->lock);
- PR_ASSERT(0 == rv);
- /* the entries should be > 0 and we'd better be the owner */
- PR_ASSERT(mon->entryCount > 0);
- PR_ASSERT(pthread_equal(mon->owner, self));
- if (mon->entryCount == 0 || !pthread_equal(mon->owner, self))
- {
- rv = pthread_mutex_unlock(&mon->lock);
- PR_ASSERT(0 == rv);
- return PR_FAILURE;
- }
-
- mon->entryCount -= 1; /* reduce by one */
- if (mon->entryCount == 0)
- {
- /* and if it transitioned to zero - notify an entry waiter */
- /* make the owner unknown */
- _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
- notifyEntryWaiter = PR_TRUE;
- notifyTimes = mon->notifyTimes;
- mon->notifyTimes = 0;
- /* We will access the members of 'mon' after unlocking mon->lock.
- * Add a reference. */
- PR_ATOMIC_INCREMENT(&mon->refCount);
- }
- rv = pthread_mutex_unlock(&mon->lock);
- PR_ASSERT(0 == rv);
- if (notifyEntryWaiter)
- {
- if (notifyTimes)
- pt_PostNotifiesFromMonitor(&mon->waitCV, notifyTimes);
- rv = pthread_cond_signal(&mon->entryCV);
- PR_ASSERT(0 == rv);
- /* We are done accessing the members of 'mon'. Release the
- * reference. */
- PR_DestroyMonitor(mon);
- }
- return PR_SUCCESS;
-} /* PR_ExitMonitor */
-
-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(PRStatus) PR_Notify(PRMonitor *mon)
-{
- pt_PostNotifyToMonitor(mon, PR_FALSE);
- return PR_SUCCESS;
-} /* PR_Notify */
-
-PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
-{
- pt_PostNotifyToMonitor(mon, 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_Free(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_Free(semaphore);
- }
- return NULL;
-}
-
-/*
- * Define the interprocess named semaphore functions.
- * There are three implementations:
- * 1. POSIX semaphore based;
- * 2. System V semaphore based;
- * 3. unsupported (fails with PR_NOT_IMPLEMENTED_ERROR).
- */
-
-#ifdef _PR_HAVE_POSIX_SEMAPHORES
-#include <fcntl.h>
-
-PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
- const char *name,
- PRIntn flags,
- PRIntn mode,
- PRUintn value)
-{
- PRSem *sem;
- char osname[PR_IPC_NAME_SIZE];
-
- if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
- == PR_FAILURE)
- {
- return NULL;
- }
-
- sem = PR_NEW(PRSem);
- if (NULL == sem)
- {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return NULL;
- }
-
- if (flags & PR_SEM_CREATE)
- {
- int oflag = O_CREAT;
-
- if (flags & PR_SEM_EXCL) oflag |= O_EXCL;
- sem->sem = sem_open(osname, oflag, mode, value);
- }
- else
- {
-#ifdef HPUX
- /* Pass 0 as the mode and value arguments to work around a bug. */
- sem->sem = sem_open(osname, 0, 0, 0);
-#else
- sem->sem = sem_open(osname, 0);
-#endif
- }
- if ((sem_t *) -1 == sem->sem)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- PR_Free(sem);
- return NULL;
- }
- return sem;
-}
-
-PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
-{
- int rv;
- rv = sem_wait(sem->sem);
- if (0 != rv)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-}
-
-PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
-{
- int rv;
- rv = sem_post(sem->sem);
- if (0 != rv)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-}
-
-PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
-{
- int rv;
- rv = sem_close(sem->sem);
- if (0 != rv)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- PR_Free(sem);
- return PR_SUCCESS;
-}
-
-PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
-{
- int rv;
- char osname[PR_IPC_NAME_SIZE];
-
- if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
- == PR_FAILURE)
- {
- return PR_FAILURE;
- }
- rv = sem_unlink(osname);
- if (0 != rv)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-}
-
-#elif defined(_PR_HAVE_SYSV_SEMAPHORES)
-
-#include <fcntl.h>
-#include <sys/sem.h>
-
-/*
- * From the semctl(2) man page in glibc 2.0
- */
-#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \
- || defined(FREEBSD) || defined(OPENBSD) || defined(BSDI) \
- || defined(DARWIN) || defined(SYMBIAN)
-/* union semun is defined by including <sys/sem.h> */
-#else
-/* according to X/OPEN we have to define it ourselves */
-union semun {
- int val;
- struct semid_ds *buf;
- unsigned short *array;
-};
-#endif
-
-/*
- * 'a' (97) is the final closing price of NSCP stock.
- */
-#define NSPR_IPC_KEY_ID 'a' /* the id argument for ftok() */
-
-#define NSPR_SEM_MODE 0666
-
-PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
- const char *name,
- PRIntn flags,
- PRIntn mode,
- PRUintn value)
-{
- PRSem *sem;
- key_t key;
- union semun arg;
- struct sembuf sop;
- struct semid_ds seminfo;
-#define MAX_TRIES 60
- PRIntn i;
- char osname[PR_IPC_NAME_SIZE];
-
- if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
- == PR_FAILURE)
- {
- return NULL;
- }
-
- /* Make sure the file exists before calling ftok. */
- if (flags & PR_SEM_CREATE)
- {
- int osfd = open(osname, O_RDWR|O_CREAT, mode);
- if (-1 == osfd)
- {
- _PR_MD_MAP_OPEN_ERROR(errno);
- return NULL;
- }
- if (close(osfd) == -1)
- {
- _PR_MD_MAP_CLOSE_ERROR(errno);
- return NULL;
- }
- }
- key = ftok(osname, NSPR_IPC_KEY_ID);
- if ((key_t)-1 == key)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return NULL;
- }
-
- sem = PR_NEW(PRSem);
- if (NULL == sem)
- {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return NULL;
- }
-
- if (flags & PR_SEM_CREATE)
- {
- sem->semid = semget(key, 1, mode|IPC_CREAT|IPC_EXCL);
- if (sem->semid >= 0)
- {
- /* creator of a semaphore is responsible for initializing it */
- arg.val = 0;
- if (semctl(sem->semid, 0, SETVAL, arg) == -1)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- PR_Free(sem);
- return NULL;
- }
- /* call semop to set sem_otime to nonzero */
- sop.sem_num = 0;
- sop.sem_op = value;
- sop.sem_flg = 0;
- if (semop(sem->semid, &sop, 1) == -1)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- PR_Free(sem);
- return NULL;
- }
- return sem;
- }
-
- if (errno != EEXIST || flags & PR_SEM_EXCL)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- PR_Free(sem);
- return NULL;
- }
- }
-
- sem->semid = semget(key, 1, NSPR_SEM_MODE);
- if (sem->semid == -1)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- PR_Free(sem);
- return NULL;
- }
- for (i = 0; i < MAX_TRIES; i++)
- {
- arg.buf = &seminfo;
- semctl(sem->semid, 0, IPC_STAT, arg);
- if (seminfo.sem_otime != 0) break;
- sleep(1);
- }
- if (i == MAX_TRIES)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- PR_Free(sem);
- return NULL;
- }
- return sem;
-}
-
-PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
-{
- struct sembuf sop;
-
- sop.sem_num = 0;
- sop.sem_op = -1;
- sop.sem_flg = 0;
- if (semop(sem->semid, &sop, 1) == -1)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-}
-
-PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
-{
- struct sembuf sop;
-
- sop.sem_num = 0;
- sop.sem_op = 1;
- sop.sem_flg = 0;
- if (semop(sem->semid, &sop, 1) == -1)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-}
-
-PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
-{
- PR_Free(sem);
- return PR_SUCCESS;
-}
-
-PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
-{
- key_t key;
- int semid;
- /* On some systems (e.g., glibc 2.0) semctl requires a fourth argument */
- union semun unused;
- char osname[PR_IPC_NAME_SIZE];
-
- if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
- == PR_FAILURE)
- {
- return PR_FAILURE;
- }
- key = ftok(osname, NSPR_IPC_KEY_ID);
- if ((key_t) -1 == key)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- if (unlink(osname) == -1)
- {
- _PR_MD_MAP_UNLINK_ERROR(errno);
- return PR_FAILURE;
- }
- semid = semget(key, 1, NSPR_SEM_MODE);
- if (-1 == semid)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- unused.val = 0;
- if (semctl(semid, 0, IPC_RMID, unused) == -1)
- {
- _PR_MD_MAP_DEFAULT_ERROR(errno);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-}
-
-#else /* neither POSIX nor System V semaphores are available */
-
-PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
- const char *name,
- PRIntn flags,
- PRIntn mode,
- PRUintn value)
-{
- PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
- return NULL;
-}
-
-PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
-{
- PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
- return PR_FAILURE;
-}
-
-PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
-{
- PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
- return PR_FAILURE;
-}
-
-PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
-{
- PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
- return PR_FAILURE;
-}
-
-PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
-{
- PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
- return PR_FAILURE;
-}
-
-#endif /* end of interprocess named semaphore functions */
-
-/**************************************************************/
-/**************************************************************/
-/******************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(PR_FALSE == lock->locked);
- lock->locked = PR_TRUE;
- lock->owner = pthread_self();
- }
- /* XXX set error code? */
- return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE;
-} /* PRP_TryLock */
-
-PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)
-{
- PRCondVar *cv;
-
- if (!_pr_initialized) _PR_ImplicitInitialization();
-
- cv = PR_NEW(PRCondVar);
- if (cv != NULL)
- {
- int rv;
- rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
- PR_ASSERT(0 == rv);
- if (0 == rv)
- {
- cv->lock = _PR_NAKED_CV_LOCK;
- }
- else
- {
- PR_DELETE(cv);
- cv = NULL;
- }
- }
- 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_Free(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(_PT_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);
- if (rv != 0)
- {
- _PR_MD_MAP_DEFAULT_ERROR(rv);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
-} /* 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 */
« no previous file with comments | « nspr/pr/src/pthreads/ptmisc.c ('k') | nspr/pr/src/pthreads/ptthread.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698