LCOV - code coverage report
Current view: top level - nsprpub/pr/src/pthreads - ptsynch.c (source / functions) Hit Total Coverage
Test: output.info Lines: 251 473 53.1 %
Date: 2017-07-14 16:53:18 Functions: 7 12 58.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : /*
       7             : ** File:            ptsynch.c
       8             : ** Descritpion:        Implemenation for thread synchronization using pthreads
       9             : ** Exports:            prlock.h, prcvar.h, prmon.h, prcmon.h
      10             : */
      11             : 
      12             : #if defined(_PR_PTHREADS)
      13             : 
      14             : #include "primpl.h"
      15             : #include "obsolete/prsem.h"
      16             : 
      17             : #include <string.h>
      18             : #include <pthread.h>
      19             : #include <sys/time.h>
      20             : 
      21             : static pthread_mutexattr_t _pt_mattr;
      22             : static pthread_condattr_t _pt_cvar_attr;
      23             : 
      24             : #if defined(DEBUG)
      25             : extern PTDebug pt_debug;  /* this is shared between several modules */
      26             : 
      27             : #if defined(_PR_DCETHREADS)
      28             : static pthread_t pt_zero_tid;  /* a null pthread_t (pthread_t is a struct
      29             :                                 * in DCE threads) to compare with */
      30             : #endif  /* defined(_PR_DCETHREADS) */
      31             : #endif  /* defined(DEBUG) */
      32             : 
      33             : #if defined(FREEBSD)
      34             : /*
      35             :  * On older versions of FreeBSD, pthread_mutex_trylock returns EDEADLK.
      36             :  * Newer versions return EBUSY.  We still need to support both.
      37             :  */
      38             : static int
      39             : pt_pthread_mutex_is_locked(pthread_mutex_t *m)
      40             : {
      41             :     int rv = pthread_mutex_trylock(m);
      42             :     return (EBUSY == rv || EDEADLK == rv);
      43             : }
      44             : #endif
      45             : 
      46             : /**************************************************************/
      47             : /**************************************************************/
      48             : /*****************************LOCKS****************************/
      49             : /**************************************************************/
      50             : /**************************************************************/
      51             : 
      52           3 : void _PR_InitLocks(void)
      53             : {
      54             :     int rv;
      55           3 :     rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr); 
      56           3 :     PR_ASSERT(0 == rv);
      57             : 
      58             : #ifdef LINUX
      59             : #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
      60           3 :     rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP);
      61           3 :     PR_ASSERT(0 == rv);
      62             : #endif
      63             : #endif
      64             : 
      65           3 :     rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
      66           3 :     PR_ASSERT(0 == rv);
      67           3 : }
      68             : 
      69         105 : static void pt_PostNotifies(PRLock *lock, PRBool unlock)
      70             : {
      71             :     PRIntn index, rv;
      72             :     _PT_Notified post;
      73         105 :     _PT_Notified *notified, *prev = NULL;
      74             :     /*
      75             :      * Time to actually notify any conditions that were affected
      76             :      * while the lock was held. Get a copy of the list that's in
      77             :      * the lock structure and then zero the original. If it's
      78             :      * linked to other such structures, we own that storage.
      79             :      */
      80         105 :     post = lock->notified;  /* a safe copy; we own the lock */
      81             : 
      82             : #if defined(DEBUG)
      83         105 :     memset(&lock->notified, 0, sizeof(_PT_Notified));  /* reset */
      84             : #else
      85             :     lock->notified.length = 0;  /* these are really sufficient */
      86             :     lock->notified.link = NULL;
      87             : #endif
      88             : 
      89             :     /* should (may) we release lock before notifying? */
      90         105 :     if (unlock)
      91             :     {
      92         105 :         rv = pthread_mutex_unlock(&lock->mutex);
      93         105 :         PR_ASSERT(0 == rv);
      94             :     }
      95             : 
      96         105 :     notified = &post;  /* this is where we start */
      97             :     do
      98             :     {
      99         210 :         for (index = 0; index < notified->length; ++index)
     100             :         {
     101         105 :             PRCondVar *cv = notified->cv[index].cv;
     102         105 :             PR_ASSERT(NULL != cv);
     103         105 :             PR_ASSERT(0 != notified->cv[index].times);
     104         105 :             if (-1 == notified->cv[index].times)
     105             :             {
     106         105 :                 rv = pthread_cond_broadcast(&cv->cv);
     107         105 :                 PR_ASSERT(0 == rv);
     108             :             }
     109             :             else
     110             :             {
     111           0 :                 while (notified->cv[index].times-- > 0)
     112             :                 {
     113           0 :                     rv = pthread_cond_signal(&cv->cv);
     114           0 :                     PR_ASSERT(0 == rv);
     115             :                 }
     116             :             }
     117             : #if defined(DEBUG)
     118         105 :             pt_debug.cvars_notified += 1;
     119         105 :             if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
     120             :             {
     121           0 :                 pt_debug.delayed_cv_deletes += 1;
     122           0 :                 PR_DestroyCondVar(cv);
     123             :             }
     124             : #else  /* defined(DEBUG) */
     125             :             if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
     126             :                 PR_DestroyCondVar(cv);
     127             : #endif  /* defined(DEBUG) */
     128             :         }
     129         105 :         prev = notified;
     130         105 :         notified = notified->link;
     131         105 :         if (&post != prev) PR_DELETE(prev);
     132         105 :     } while (NULL != notified);
     133         105 : }  /* pt_PostNotifies */
     134             : 
     135             : PR_IMPLEMENT(PRLock*) PR_NewLock(void)
     136             : {
     137             :     PRIntn rv;
     138             :     PRLock *lock;
     139             : 
     140        2193 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     141             : 
     142        2193 :     lock = PR_NEWZAP(PRLock);
     143        2193 :     if (lock != NULL)
     144             :     {
     145        2193 :         rv = _PT_PTHREAD_MUTEX_INIT(lock->mutex, _pt_mattr); 
     146        2193 :         PR_ASSERT(0 == rv);
     147             :     }
     148             : #if defined(DEBUG)
     149        2193 :     pt_debug.locks_created += 1;
     150             : #endif
     151        2193 :     return lock;
     152             : }  /* PR_NewLock */
     153             : 
     154             : PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
     155             : {
     156             :     PRIntn rv;
     157        1725 :     PR_ASSERT(NULL != lock);
     158        1725 :     PR_ASSERT(PR_FALSE == lock->locked);
     159        1725 :     PR_ASSERT(0 == lock->notified.length);
     160        1725 :     PR_ASSERT(NULL == lock->notified.link);
     161        1725 :     rv = pthread_mutex_destroy(&lock->mutex);
     162        1725 :     PR_ASSERT(0 == rv);
     163             : #if defined(DEBUG)
     164        1725 :     memset(lock, 0xaf, sizeof(PRLock));
     165        1725 :     pt_debug.locks_destroyed += 1;
     166             : #endif
     167        1725 :     PR_Free(lock);
     168        1725 : }  /* PR_DestroyLock */
     169             : 
     170             : PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
     171             : {
     172             :     /* Nb: PR_Lock must not call PR_GetCurrentThread to access the |id| or
     173             :      * |tid| field of the current thread's PRThread structure because
     174             :      * _pt_root calls PR_Lock before setting thred->id and thred->tid. */
     175             :     PRIntn rv;
     176       57343 :     PR_ASSERT(lock != NULL);
     177       57343 :     rv = pthread_mutex_lock(&lock->mutex);
     178       57353 :     PR_ASSERT(0 == rv);
     179       57353 :     PR_ASSERT(0 == lock->notified.length);
     180       57353 :     PR_ASSERT(NULL == lock->notified.link);
     181       57353 :     PR_ASSERT(PR_FALSE == lock->locked);
     182             :     /* Nb: the order of the next two statements is not critical to
     183             :      * the correctness of PR_AssertCurrentThreadOwnsLock(), but 
     184             :      * this particular order makes the assertion more likely to
     185             :      * catch errors. */
     186       57353 :     lock->owner = pthread_self();
     187       57353 :     lock->locked = PR_TRUE;
     188             : #if defined(DEBUG)
     189       57353 :     pt_debug.locks_acquired += 1;
     190             : #endif
     191       57353 : }  /* PR_Lock */
     192             : 
     193             : PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
     194             : {
     195       57350 :     pthread_t self = pthread_self();
     196             :     PRIntn rv;
     197             : 
     198       57350 :     PR_ASSERT(lock != NULL);
     199       57350 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
     200       57350 :     PR_ASSERT(PR_TRUE == lock->locked);
     201       57350 :     PR_ASSERT(pthread_equal(lock->owner, self));
     202             : 
     203       57350 :     if (!lock->locked || !pthread_equal(lock->owner, self))
     204           0 :         return PR_FAILURE;
     205             : 
     206       57350 :     lock->locked = PR_FALSE;
     207       57350 :     if (0 == lock->notified.length)  /* shortcut */
     208             :     {
     209       57245 :         rv = pthread_mutex_unlock(&lock->mutex);
     210       57245 :         PR_ASSERT(0 == rv);
     211             :     }
     212         105 :     else pt_PostNotifies(lock, PR_TRUE);
     213             : 
     214             : #if defined(DEBUG)
     215       57350 :     pt_debug.locks_released += 1;
     216             : #endif
     217       57350 :     return PR_SUCCESS;
     218             : }  /* PR_Unlock */
     219             : 
     220             : PR_IMPLEMENT(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock)
     221             : {
     222             :     /* Nb: the order of the |locked| and |owner==me| checks is not critical 
     223             :      * to the correctness of PR_AssertCurrentThreadOwnsLock(), but 
     224             :      * this particular order makes the assertion more likely to
     225             :      * catch errors. */
     226           0 :     PR_ASSERT(lock->locked && pthread_equal(lock->owner, pthread_self()));
     227           0 : }
     228             : 
     229             : /**************************************************************/
     230             : /**************************************************************/
     231             : /***************************CONDITIONS*************************/
     232             : /**************************************************************/
     233             : /**************************************************************/
     234             : 
     235             : 
     236             : /*
     237             :  * This code is used to compute the absolute time for the wakeup.
     238             :  * It's moderately ugly, so it's defined here and called in a
     239             :  * couple of places.
     240             :  */
     241             : #define PT_NANOPERMICRO 1000UL
     242             : #define PT_BILLION 1000000000UL
     243             : 
     244          32 : static PRIntn pt_TimedWait(
     245             :     pthread_cond_t *cv, pthread_mutex_t *ml, PRIntervalTime timeout)
     246             : {
     247             :     int rv;
     248             :     struct timeval now;
     249             :     struct timespec tmo;
     250          32 :     PRUint32 ticks = PR_TicksPerSecond();
     251             : 
     252          32 :     tmo.tv_sec = (PRInt32)(timeout / ticks);
     253          32 :     tmo.tv_nsec = (PRInt32)(timeout - (tmo.tv_sec * ticks));
     254          32 :     tmo.tv_nsec = (PRInt32)PR_IntervalToMicroseconds(PT_NANOPERMICRO * tmo.tv_nsec);
     255             : 
     256             :     /* pthreads wants this in absolute time, off we go ... */
     257          32 :     (void)GETTIMEOFDAY(&now);
     258             :     /* that one's usecs, this one's nsecs - grrrr! */
     259          32 :     tmo.tv_sec += now.tv_sec;
     260          32 :     tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec);
     261          32 :     tmo.tv_sec += tmo.tv_nsec / PT_BILLION;
     262          32 :     tmo.tv_nsec %= PT_BILLION;
     263             : 
     264          32 :     rv = pthread_cond_timedwait(cv, ml, &tmo);
     265             : 
     266             :     /* NSPR doesn't report timeouts */
     267             : #ifdef _PR_DCETHREADS
     268             :     if (rv == -1) return (errno == EAGAIN) ? 0 : errno;
     269             :     else return rv;
     270             : #else
     271          29 :     return (rv == ETIMEDOUT) ? 0 : rv;
     272             : #endif
     273             : }  /* pt_TimedWait */
     274             : 
     275             : 
     276             : /*
     277             :  * Notifies just get posted to the protecting mutex. The
     278             :  * actual notification is done when the lock is released so that
     279             :  * MP systems don't contend for a lock that they can't have.
     280             :  */
     281         105 : static void pt_PostNotifyToCvar(PRCondVar *cvar, PRBool broadcast)
     282             : {
     283         105 :     PRIntn index = 0;
     284         105 :     _PT_Notified *notified = &cvar->lock->notified;
     285             : 
     286         105 :     PR_ASSERT(PR_TRUE == cvar->lock->locked);
     287         105 :     PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
     288         105 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
     289             : 
     290             :     while (1)
     291             :     {
     292         105 :         for (index = 0; index < notified->length; ++index)
     293             :         {
     294           0 :             if (notified->cv[index].cv == cvar)
     295             :             {
     296           0 :                 if (broadcast)
     297           0 :                     notified->cv[index].times = -1;
     298           0 :                 else if (-1 != notified->cv[index].times)
     299           0 :                     notified->cv[index].times += 1;
     300           0 :                 return;  /* we're finished */
     301             :             }
     302             :         }
     303             :         /* if not full, enter new CV in this array */
     304         105 :         if (notified->length < PT_CV_NOTIFIED_LENGTH) break;
     305             : 
     306             :         /* if there's no link, create an empty array and link it */
     307           0 :         if (NULL == notified->link)
     308           0 :             notified->link = PR_NEWZAP(_PT_Notified);
     309           0 :         notified = notified->link;
     310             :     }
     311             : 
     312             :     /* A brand new entry in the array */
     313         105 :     (void)PR_ATOMIC_INCREMENT(&cvar->notify_pending);
     314         105 :     notified->cv[index].times = (broadcast) ? -1 : 1;
     315         105 :     notified->cv[index].cv = cvar;
     316         105 :     notified->length += 1;
     317             : }  /* pt_PostNotifyToCvar */
     318             : 
     319             : PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
     320             : {
     321          29 :     PRCondVar *cv = PR_NEW(PRCondVar);
     322          29 :     PR_ASSERT(lock != NULL);
     323          29 :     if (cv != NULL)
     324             :     {
     325          29 :         int rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
     326          29 :         PR_ASSERT(0 == rv);
     327          29 :         if (0 == rv)
     328             :         {
     329          29 :             cv->lock = lock;
     330          29 :             cv->notify_pending = 0;
     331             : #if defined(DEBUG)
     332          29 :             pt_debug.cvars_created += 1;
     333             : #endif
     334             :         }
     335             :         else
     336             :         {
     337           0 :             PR_DELETE(cv);
     338           0 :             cv = NULL;
     339             :         }
     340             :     }
     341          29 :     return cv;
     342             : }  /* PR_NewCondVar */
     343             : 
     344             : PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
     345             : {
     346           1 :     if (0 > PR_ATOMIC_DECREMENT(&cvar->notify_pending))
     347             :     {
     348           1 :         PRIntn rv = pthread_cond_destroy(&cvar->cv);
     349             : #if defined(DEBUG)
     350           1 :         PR_ASSERT(0 == rv);
     351           1 :         memset(cvar, 0xaf, sizeof(PRCondVar));
     352           1 :         pt_debug.cvars_destroyed += 1;
     353             : #else
     354             :         (void)rv;
     355             : #endif
     356           1 :         PR_Free(cvar);
     357             :     }
     358           1 : }  /* PR_DestroyCondVar */
     359             : 
     360             : PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
     361             : {
     362             :     PRIntn rv;
     363          32 :     PRThread *thred = PR_GetCurrentThread();
     364             : 
     365          32 :     PR_ASSERT(cvar != NULL);
     366             :     /* We'd better be locked */
     367          32 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
     368          32 :     PR_ASSERT(PR_TRUE == cvar->lock->locked);
     369             :     /* and it better be by us */
     370          32 :     PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
     371             : 
     372          32 :     if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
     373             : 
     374             :     /*
     375             :      * The thread waiting is used for PR_Interrupt
     376             :      */
     377          32 :     thred->waiting = cvar;  /* this is where we're waiting */
     378             : 
     379             :     /*
     380             :      * If we have pending notifies, post them now.
     381             :      *
     382             :      * This is not optimal. We're going to post these notifies
     383             :      * while we're holding the lock. That means on MP systems
     384             :      * that they are going to collide for the lock that we will
     385             :      * hold until we actually wait.
     386             :      */
     387          32 :     if (0 != cvar->lock->notified.length)
     388           0 :         pt_PostNotifies(cvar->lock, PR_FALSE);
     389             : 
     390             :     /*
     391             :      * We're surrendering the lock, so clear out the locked field.
     392             :      */
     393          32 :     cvar->lock->locked = PR_FALSE;
     394             : 
     395          32 :     if (timeout == PR_INTERVAL_NO_TIMEOUT)
     396           0 :         rv = pthread_cond_wait(&cvar->cv, &cvar->lock->mutex);
     397             :     else
     398          32 :         rv = pt_TimedWait(&cvar->cv, &cvar->lock->mutex, timeout);
     399             : 
     400             :     /* We just got the lock back - this better be empty */
     401          29 :     PR_ASSERT(PR_FALSE == cvar->lock->locked);
     402          29 :     cvar->lock->locked = PR_TRUE;
     403          29 :     cvar->lock->owner = pthread_self();
     404             : 
     405          29 :     PR_ASSERT(0 == cvar->lock->notified.length);
     406          29 :     thred->waiting = NULL;  /* and now we're not */
     407          29 :     if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
     408          29 :     if (rv != 0)
     409             :     {
     410           0 :         _PR_MD_MAP_DEFAULT_ERROR(rv);
     411           0 :         return PR_FAILURE;
     412             :     }
     413          29 :     return PR_SUCCESS;
     414             : 
     415             : aborted:
     416           0 :     PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
     417           0 :     thred->state &= ~PT_THREAD_ABORTED;
     418           0 :     return PR_FAILURE;
     419             : }  /* PR_WaitCondVar */
     420             : 
     421             : PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar)
     422             : {
     423           0 :     PR_ASSERT(cvar != NULL);   
     424           0 :     pt_PostNotifyToCvar(cvar, PR_FALSE);
     425           0 :     return PR_SUCCESS;
     426             : }  /* PR_NotifyCondVar */
     427             : 
     428             : PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
     429             : {
     430         105 :     PR_ASSERT(cvar != NULL);
     431         105 :     pt_PostNotifyToCvar(cvar, PR_TRUE);
     432         105 :     return PR_SUCCESS;
     433             : }  /* PR_NotifyAllCondVar */
     434             : 
     435             : /**************************************************************/
     436             : /**************************************************************/
     437             : /***************************MONITORS***************************/
     438             : /**************************************************************/
     439             : /**************************************************************/
     440             : 
     441             : /*
     442             :  * Notifies just get posted to the monitor. The actual notification is done
     443             :  * when the monitor is fully exited so that MP systems don't contend for a
     444             :  * monitor that they can't enter.
     445             :  */
     446          56 : static void pt_PostNotifyToMonitor(PRMonitor *mon, PRBool broadcast)
     447             : {
     448          56 :     PR_ASSERT(NULL != mon);
     449          56 :     PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mon);
     450             : 
     451             :     /* mon->notifyTimes is protected by the monitor, so we don't need to
     452             :      * acquire mon->lock.
     453             :      */
     454          56 :     if (broadcast)
     455           0 :         mon->notifyTimes = -1;
     456          56 :     else if (-1 != mon->notifyTimes)
     457          56 :         mon->notifyTimes += 1;
     458          56 : }  /* pt_PostNotifyToMonitor */
     459             : 
     460          56 : static void pt_PostNotifiesFromMonitor(pthread_cond_t *cv, PRIntn times)
     461             : {
     462             :     PRIntn rv;
     463             : 
     464             :     /*
     465             :      * Time to actually notify any waits that were affected while the monitor
     466             :      * was entered.
     467             :      */
     468          56 :     PR_ASSERT(NULL != cv);
     469          56 :     PR_ASSERT(0 != times);
     470          56 :     if (-1 == times)
     471             :     {
     472           0 :         rv = pthread_cond_broadcast(cv);
     473           0 :         PR_ASSERT(0 == rv);
     474             :     }
     475             :     else
     476             :     {
     477         168 :         while (times-- > 0)
     478             :         {
     479          56 :             rv = pthread_cond_signal(cv);
     480          56 :             PR_ASSERT(0 == rv);
     481             :         }
     482             :     }
     483          56 : }  /* pt_PostNotifiesFromMonitor */
     484             : 
     485             : PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
     486             : {
     487             :     PRMonitor *mon;
     488             :     int rv;
     489             : 
     490         393 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     491             : 
     492         393 :     mon = PR_NEWZAP(PRMonitor);
     493         393 :     if (mon == NULL)
     494             :     {
     495           0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     496           0 :         return NULL;
     497             :     }
     498             : 
     499         393 :     rv = _PT_PTHREAD_MUTEX_INIT(mon->lock, _pt_mattr);
     500         393 :     PR_ASSERT(0 == rv);
     501         393 :     if (0 != rv)
     502           0 :         goto error1;
     503             : 
     504         393 :     _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
     505             : 
     506         393 :     rv = _PT_PTHREAD_COND_INIT(mon->entryCV, _pt_cvar_attr);
     507         393 :     PR_ASSERT(0 == rv);
     508         393 :     if (0 != rv)
     509           0 :         goto error2;
     510             : 
     511         393 :     rv = _PT_PTHREAD_COND_INIT(mon->waitCV, _pt_cvar_attr);
     512         393 :     PR_ASSERT(0 == rv);
     513         393 :     if (0 != rv)
     514           0 :         goto error3;
     515             : 
     516         393 :     mon->notifyTimes = 0;
     517         393 :     mon->entryCount = 0;
     518         393 :     mon->refCount = 1;
     519         393 :     mon->name = NULL;
     520         393 :     return mon;
     521             : 
     522             : error3:
     523           0 :     pthread_cond_destroy(&mon->entryCV);
     524             : error2:
     525           0 :     pthread_mutex_destroy(&mon->lock);
     526             : error1:
     527           0 :     PR_Free(mon);
     528           0 :     _PR_MD_MAP_DEFAULT_ERROR(rv);
     529           0 :     return NULL;
     530             : }  /* PR_NewMonitor */
     531             : 
     532           3 : PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
     533             : {
     534           3 :     PRMonitor* mon = PR_NewMonitor();
     535           3 :     if (mon)
     536           3 :         mon->name = name;
     537           3 :     return mon;
     538             : }
     539             : 
     540             : PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
     541             : {
     542             :     int rv;
     543             : 
     544        8809 :     PR_ASSERT(mon != NULL);
     545        8809 :     if (PR_ATOMIC_DECREMENT(&mon->refCount) == 0)
     546             :     {
     547         315 :         rv = pthread_cond_destroy(&mon->waitCV); PR_ASSERT(0 == rv);
     548         315 :         rv = pthread_cond_destroy(&mon->entryCV); PR_ASSERT(0 == rv);
     549         315 :         rv = pthread_mutex_destroy(&mon->lock); PR_ASSERT(0 == rv);
     550             : #if defined(DEBUG)
     551         315 :         memset(mon, 0xaf, sizeof(PRMonitor));
     552             : #endif
     553         315 :         PR_Free(mon);
     554             :     }
     555        8809 : }  /* PR_DestroyMonitor */
     556             : 
     557             : /* The GC uses this; it is quite arguably a bad interface.  I'm just 
     558             :  * duplicating it for now - XXXMB
     559             :  */
     560           0 : PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
     561             : {
     562           0 :     pthread_t self = pthread_self();
     563             :     PRIntn rv;
     564           0 :     PRIntn count = 0;
     565             : 
     566           0 :     rv = pthread_mutex_lock(&mon->lock);
     567           0 :     PR_ASSERT(0 == rv);
     568           0 :     if (pthread_equal(mon->owner, self))
     569           0 :         count = mon->entryCount;
     570           0 :     rv = pthread_mutex_unlock(&mon->lock);
     571           0 :     PR_ASSERT(0 == rv);
     572           0 :     return count;
     573             : }
     574             : 
     575             : PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
     576             : {
     577             : #if defined(DEBUG) || defined(FORCE_PR_ASSERT)
     578             :     PRIntn rv;
     579             : 
     580        6741 :     rv = pthread_mutex_lock(&mon->lock);
     581        6741 :     PR_ASSERT(0 == rv);
     582        6741 :     PR_ASSERT(mon->entryCount != 0 &&
     583             :               pthread_equal(mon->owner, pthread_self()));
     584        6741 :     rv = pthread_mutex_unlock(&mon->lock);
     585        6741 :     PR_ASSERT(0 == rv);
     586             : #endif
     587        6741 : }
     588             : 
     589             : PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
     590             : {
     591        9064 :     pthread_t self = pthread_self();
     592             :     PRIntn rv;
     593             : 
     594        9064 :     PR_ASSERT(mon != NULL);
     595        9064 :     rv = pthread_mutex_lock(&mon->lock);
     596        9064 :     PR_ASSERT(0 == rv);
     597        9064 :     if (mon->entryCount != 0)
     598             :     {
     599         576 :         if (pthread_equal(mon->owner, self))
     600         570 :             goto done;
     601          18 :         while (mon->entryCount != 0)
     602             :         {
     603           6 :             rv = pthread_cond_wait(&mon->entryCV, &mon->lock);
     604           6 :             PR_ASSERT(0 == rv);
     605             :         }
     606             :     }
     607             :     /* and now I have the monitor */
     608        8494 :     PR_ASSERT(0 == mon->notifyTimes);
     609        8494 :     PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
     610        8494 :     _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
     611             : 
     612             : done:
     613        9064 :     mon->entryCount += 1;
     614        9064 :     rv = pthread_mutex_unlock(&mon->lock);
     615        9064 :     PR_ASSERT(0 == rv);
     616        9064 : }  /* PR_EnterMonitor */
     617             : 
     618             : PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
     619             : {
     620        9064 :     pthread_t self = pthread_self();
     621             :     PRIntn rv;
     622        9064 :     PRBool notifyEntryWaiter = PR_FALSE;
     623        9064 :     PRIntn notifyTimes = 0;
     624             : 
     625        9064 :     PR_ASSERT(mon != NULL);
     626        9064 :     rv = pthread_mutex_lock(&mon->lock);
     627        9064 :     PR_ASSERT(0 == rv);
     628             :     /* the entries should be > 0 and we'd better be the owner */
     629        9064 :     PR_ASSERT(mon->entryCount > 0);
     630        9064 :     PR_ASSERT(pthread_equal(mon->owner, self));
     631        9064 :     if (mon->entryCount == 0 || !pthread_equal(mon->owner, self))
     632             :     {
     633           0 :         rv = pthread_mutex_unlock(&mon->lock);
     634           0 :         PR_ASSERT(0 == rv);
     635           0 :         return PR_FAILURE;
     636             :     }
     637             : 
     638        9064 :     mon->entryCount -= 1;  /* reduce by one */
     639        9064 :     if (mon->entryCount == 0)
     640             :     {
     641             :         /* and if it transitioned to zero - notify an entry waiter */
     642             :         /* make the owner unknown */
     643        8494 :         _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
     644        8494 :         notifyEntryWaiter = PR_TRUE;
     645        8494 :         notifyTimes = mon->notifyTimes;
     646        8494 :         mon->notifyTimes = 0;
     647             :         /* We will access the members of 'mon' after unlocking mon->lock.
     648             :          * Add a reference. */
     649        8494 :         PR_ATOMIC_INCREMENT(&mon->refCount);
     650             :     }
     651        9064 :     rv = pthread_mutex_unlock(&mon->lock);
     652        9064 :     PR_ASSERT(0 == rv);
     653        9064 :     if (notifyEntryWaiter)
     654             :     {
     655        8494 :         if (notifyTimes)
     656          56 :             pt_PostNotifiesFromMonitor(&mon->waitCV, notifyTimes);
     657        8494 :         rv = pthread_cond_signal(&mon->entryCV);
     658        8494 :         PR_ASSERT(0 == rv);
     659             :         /* We are done accessing the members of 'mon'. Release the
     660             :          * reference. */
     661        8494 :         PR_DestroyMonitor(mon);
     662             :     }
     663        9064 :     return PR_SUCCESS;
     664             : }  /* PR_ExitMonitor */
     665             : 
     666             : PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
     667             : {
     668             :     PRStatus rv;
     669             :     PRUint32 saved_entries;
     670             :     pthread_t saved_owner;
     671             : 
     672          56 :     PR_ASSERT(mon != NULL);
     673          56 :     rv = pthread_mutex_lock(&mon->lock);
     674          56 :     PR_ASSERT(0 == rv);
     675             :     /* the entries better be positive */
     676          56 :     PR_ASSERT(mon->entryCount > 0);
     677             :     /* and it better be owned by us */
     678          56 :     PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
     679             : 
     680             :     /* tuck these away 'till later */
     681          56 :     saved_entries = mon->entryCount; 
     682          56 :     mon->entryCount = 0;
     683          56 :     _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
     684          56 :     _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
     685             :     /*
     686             :      * If we have pending notifies, post them now.
     687             :      *
     688             :      * This is not optimal. We're going to post these notifies
     689             :      * while we're holding the lock. That means on MP systems
     690             :      * that they are going to collide for the lock that we will
     691             :      * hold until we actually wait.
     692             :      */
     693          56 :     if (0 != mon->notifyTimes)
     694             :     {
     695           0 :         pt_PostNotifiesFromMonitor(&mon->waitCV, mon->notifyTimes);
     696           0 :         mon->notifyTimes = 0;
     697             :     }
     698          56 :     rv = pthread_cond_signal(&mon->entryCV);
     699          56 :     PR_ASSERT(0 == rv);
     700             : 
     701          56 :     if (timeout == PR_INTERVAL_NO_TIMEOUT)
     702          56 :         rv = pthread_cond_wait(&mon->waitCV, &mon->lock);
     703             :     else
     704           0 :         rv = pt_TimedWait(&mon->waitCV, &mon->lock, timeout);
     705          56 :     PR_ASSERT(0 == rv);
     706             : 
     707         112 :     while (mon->entryCount != 0)
     708             :     {
     709           0 :         rv = pthread_cond_wait(&mon->entryCV, &mon->lock);
     710           0 :         PR_ASSERT(0 == rv);
     711             :     }
     712          56 :     PR_ASSERT(0 == mon->notifyTimes);
     713             :     /* reinstate the interesting information */
     714          56 :     mon->entryCount = saved_entries;
     715          56 :     _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);
     716             : 
     717          56 :     rv = pthread_mutex_unlock(&mon->lock);
     718          56 :     PR_ASSERT(0 == rv);
     719          56 :     return rv;
     720             : }  /* PR_Wait */
     721             : 
     722             : PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
     723             : {
     724          56 :     pt_PostNotifyToMonitor(mon, PR_FALSE);
     725          56 :     return PR_SUCCESS;
     726             : }  /* PR_Notify */
     727             : 
     728             : PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
     729             : {
     730           0 :     pt_PostNotifyToMonitor(mon, PR_TRUE);
     731           0 :     return PR_SUCCESS;
     732             : }  /* PR_NotifyAll */
     733             : 
     734             : /**************************************************************/
     735             : /**************************************************************/
     736             : /**************************SEMAPHORES**************************/
     737             : /**************************************************************/
     738             : /**************************************************************/
     739           0 : PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *semaphore)
     740             : {
     741             :     static PRBool unwarned = PR_TRUE;
     742           0 :     if (unwarned) unwarned = _PR_Obsolete(
     743             :         "PR_PostSem", "locks & condition variables");
     744           0 :         PR_Lock(semaphore->cvar->lock);
     745           0 :         PR_NotifyCondVar(semaphore->cvar);
     746           0 :         semaphore->count += 1;
     747           0 :         PR_Unlock(semaphore->cvar->lock);
     748           0 : }  /* PR_PostSem */
     749             : 
     750           0 : PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *semaphore)
     751             : {
     752           0 :         PRStatus status = PR_SUCCESS;
     753             :     static PRBool unwarned = PR_TRUE;
     754           0 :     if (unwarned) unwarned = _PR_Obsolete(
     755             :         "PR_WaitSem", "locks & condition variables");
     756           0 :         PR_Lock(semaphore->cvar->lock);
     757           0 :         while ((semaphore->count == 0) && (PR_SUCCESS == status))
     758           0 :                 status = PR_WaitCondVar(semaphore->cvar, PR_INTERVAL_NO_TIMEOUT);
     759           0 :         if (PR_SUCCESS == status) semaphore->count -= 1;
     760           0 :         PR_Unlock(semaphore->cvar->lock);
     761           0 :         return status;
     762             : }  /* PR_WaitSem */
     763             : 
     764           0 : PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *semaphore)
     765             : {
     766             :     static PRBool unwarned = PR_TRUE;
     767           0 :     if (unwarned) unwarned = _PR_Obsolete(
     768             :         "PR_DestroySem", "locks & condition variables");
     769           0 :     PR_DestroyLock(semaphore->cvar->lock);
     770           0 :     PR_DestroyCondVar(semaphore->cvar);
     771           0 :     PR_Free(semaphore);
     772           0 : }  /* PR_DestroySem */
     773             : 
     774           0 : PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value)
     775             : {
     776             :     PRSemaphore *semaphore;
     777             :     static PRBool unwarned = PR_TRUE;
     778           0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     779             : 
     780           0 :     if (unwarned) unwarned = _PR_Obsolete(
     781             :         "PR_NewSem", "locks & condition variables");
     782             : 
     783           0 :     semaphore = PR_NEWZAP(PRSemaphore);
     784           0 :     if (NULL != semaphore)
     785             :     {
     786           0 :         PRLock *lock = PR_NewLock();
     787           0 :         if (NULL != lock)
     788             :         {
     789           0 :             semaphore->cvar = PR_NewCondVar(lock);
     790           0 :             if (NULL != semaphore->cvar)
     791             :             {
     792           0 :                 semaphore->count = value;
     793           0 :                 return semaphore;
     794             :             }
     795           0 :             PR_DestroyLock(lock);
     796             :         }
     797           0 :         PR_Free(semaphore);
     798             :     }
     799           0 :     return NULL;
     800             : }
     801             : 
     802             : /*
     803             :  * Define the interprocess named semaphore functions.
     804             :  * There are three implementations:
     805             :  * 1. POSIX semaphore based;
     806             :  * 2. System V semaphore based;
     807             :  * 3. unsupported (fails with PR_NOT_IMPLEMENTED_ERROR).
     808             :  */
     809             : 
     810             : #ifdef _PR_HAVE_POSIX_SEMAPHORES
     811             : #include <fcntl.h>
     812             : 
     813             : PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
     814             :     const char *name,
     815             :     PRIntn flags,
     816             :     PRIntn mode,
     817             :     PRUintn value)
     818             : {
     819             :     PRSem *sem;
     820             :     char osname[PR_IPC_NAME_SIZE];
     821             : 
     822             :     if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
     823             :         == PR_FAILURE)
     824             :     {
     825             :         return NULL;
     826             :     }
     827             : 
     828             :     sem = PR_NEW(PRSem);
     829             :     if (NULL == sem)
     830             :     {
     831             :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     832             :         return NULL;
     833             :     }
     834             : 
     835             :     if (flags & PR_SEM_CREATE)
     836             :     {
     837             :         int oflag = O_CREAT;
     838             : 
     839             :         if (flags & PR_SEM_EXCL) oflag |= O_EXCL;
     840             :         sem->sem = sem_open(osname, oflag, mode, value);
     841             :     }
     842             :     else
     843             :     {
     844             : #ifdef HPUX
     845             :         /* Pass 0 as the mode and value arguments to work around a bug. */
     846             :         sem->sem = sem_open(osname, 0, 0, 0);
     847             : #else
     848             :         sem->sem = sem_open(osname, 0);
     849             : #endif
     850             :     }
     851             :     if ((sem_t *) -1 == sem->sem)
     852             :     {
     853             :         _PR_MD_MAP_DEFAULT_ERROR(errno);
     854             :         PR_Free(sem);
     855             :         return NULL;
     856             :     }
     857             :     return sem;
     858             : }
     859             : 
     860             : PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
     861             : {
     862             :     int rv;
     863             :     rv = sem_wait(sem->sem);
     864             :     if (0 != rv)
     865             :     {
     866             :         _PR_MD_MAP_DEFAULT_ERROR(errno);
     867             :         return PR_FAILURE;
     868             :     }
     869             :     return PR_SUCCESS;
     870             : }
     871             : 
     872             : PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
     873             : {
     874             :     int rv;
     875             :     rv = sem_post(sem->sem);
     876             :     if (0 != rv)
     877             :     {
     878             :         _PR_MD_MAP_DEFAULT_ERROR(errno);
     879             :         return PR_FAILURE;
     880             :     }
     881             :     return PR_SUCCESS;
     882             : }
     883             : 
     884             : PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
     885             : {
     886             :     int rv;
     887             :     rv = sem_close(sem->sem);
     888             :     if (0 != rv)
     889             :     {
     890             :         _PR_MD_MAP_DEFAULT_ERROR(errno);
     891             :         return PR_FAILURE;
     892             :     }
     893             :     PR_Free(sem);
     894             :     return PR_SUCCESS;
     895             : }
     896             : 
     897             : PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
     898             : {
     899             :     int rv;
     900             :     char osname[PR_IPC_NAME_SIZE];
     901             : 
     902             :     if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
     903             :         == PR_FAILURE)
     904             :     {
     905             :         return PR_FAILURE;
     906             :     }
     907             :     rv = sem_unlink(osname);
     908             :     if (0 != rv)
     909             :     {
     910             :         _PR_MD_MAP_DEFAULT_ERROR(errno);
     911             :         return PR_FAILURE;
     912             :     }
     913             :     return PR_SUCCESS;
     914             : }
     915             :     
     916             : #elif defined(_PR_HAVE_SYSV_SEMAPHORES)
     917             : 
     918             : #include <fcntl.h>
     919             : #include <sys/sem.h>
     920             : 
     921             : /*
     922             :  * From the semctl(2) man page in glibc 2.0
     923             :  */
     924             : #if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \
     925             :     || defined(FREEBSD) || defined(OPENBSD) || defined(BSDI) \
     926             :     || defined(DARWIN) || defined(SYMBIAN)
     927             : /* union semun is defined by including <sys/sem.h> */
     928             : #else
     929             : /* according to X/OPEN we have to define it ourselves */
     930             : union semun {
     931             :     int val;
     932             :     struct semid_ds *buf;
     933             :     unsigned short  *array;
     934             : };
     935             : #endif
     936             : 
     937             : /*
     938             :  * 'a' (97) is the final closing price of NSCP stock.
     939             :  */
     940             : #define NSPR_IPC_KEY_ID 'a'  /* the id argument for ftok() */
     941             : 
     942             : #define NSPR_SEM_MODE 0666
     943             : 
     944             : PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
     945             :     const char *name,
     946             :     PRIntn flags,
     947             :     PRIntn mode,
     948             :     PRUintn value)
     949             : {
     950             :     PRSem *sem;
     951             :     key_t key;
     952             :     union semun arg;
     953             :     struct sembuf sop;
     954             :     struct semid_ds seminfo;
     955             : #define MAX_TRIES 60
     956             :     PRIntn i;
     957             :     char osname[PR_IPC_NAME_SIZE];
     958             : 
     959           0 :     if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
     960             :         == PR_FAILURE)
     961             :     {
     962           0 :         return NULL;
     963             :     }
     964             : 
     965             :     /* Make sure the file exists before calling ftok. */
     966           0 :     if (flags & PR_SEM_CREATE)
     967             :     {
     968           0 :         int osfd = open(osname, O_RDWR|O_CREAT, mode);
     969           0 :         if (-1 == osfd)
     970             :         {
     971           0 :             _PR_MD_MAP_OPEN_ERROR(errno);
     972           0 :             return NULL;
     973             :         }
     974           0 :         if (close(osfd) == -1)
     975             :         {
     976           0 :             _PR_MD_MAP_CLOSE_ERROR(errno);
     977           0 :             return NULL;
     978             :         }
     979             :     }
     980           0 :     key = ftok(osname, NSPR_IPC_KEY_ID);
     981           0 :     if ((key_t)-1 == key)
     982             :     {
     983           0 :         _PR_MD_MAP_DEFAULT_ERROR(errno);
     984           0 :         return NULL;
     985             :     }
     986             : 
     987           0 :     sem = PR_NEW(PRSem);
     988           0 :     if (NULL == sem)
     989             :     {
     990           0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     991           0 :         return NULL;
     992             :     }
     993             : 
     994           0 :     if (flags & PR_SEM_CREATE)
     995             :     {
     996           0 :         sem->semid = semget(key, 1, mode|IPC_CREAT|IPC_EXCL);
     997           0 :         if (sem->semid >= 0)
     998             :         {
     999             :             /* creator of a semaphore is responsible for initializing it */
    1000           0 :             arg.val = 0;
    1001           0 :             if (semctl(sem->semid, 0, SETVAL, arg) == -1)
    1002             :             {
    1003           0 :                 _PR_MD_MAP_DEFAULT_ERROR(errno);
    1004           0 :                 PR_Free(sem);
    1005           0 :                 return NULL;
    1006             :             }
    1007             :             /* call semop to set sem_otime to nonzero */
    1008           0 :             sop.sem_num = 0;
    1009           0 :             sop.sem_op = value;
    1010           0 :             sop.sem_flg = 0;
    1011           0 :             if (semop(sem->semid, &sop, 1) == -1)
    1012             :             {
    1013           0 :                 _PR_MD_MAP_DEFAULT_ERROR(errno);
    1014           0 :                 PR_Free(sem);
    1015           0 :                 return NULL;
    1016             :             }
    1017           0 :             return sem;
    1018             :         }
    1019             : 
    1020           0 :         if (errno != EEXIST || flags & PR_SEM_EXCL)
    1021             :         {
    1022           0 :             _PR_MD_MAP_DEFAULT_ERROR(errno);
    1023           0 :             PR_Free(sem);
    1024           0 :             return NULL;
    1025             :         }
    1026             :     }
    1027             : 
    1028           0 :     sem->semid = semget(key, 1, NSPR_SEM_MODE);
    1029           0 :     if (sem->semid == -1)
    1030             :     {
    1031           0 :         _PR_MD_MAP_DEFAULT_ERROR(errno);
    1032           0 :         PR_Free(sem);
    1033           0 :         return NULL;
    1034             :     }
    1035           0 :     for (i = 0; i < MAX_TRIES; i++)
    1036             :     {
    1037           0 :         arg.buf = &seminfo;
    1038           0 :         semctl(sem->semid, 0, IPC_STAT, arg);
    1039           0 :         if (seminfo.sem_otime != 0) break;
    1040           0 :         sleep(1);
    1041             :     }
    1042           0 :     if (i == MAX_TRIES)
    1043             :     {
    1044           0 :         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
    1045           0 :         PR_Free(sem);
    1046           0 :         return NULL;
    1047             :     }
    1048           0 :     return sem;
    1049             : }
    1050             : 
    1051             : PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
    1052             : {
    1053             :     struct sembuf sop;
    1054             : 
    1055           0 :     sop.sem_num = 0;
    1056           0 :     sop.sem_op = -1;
    1057           0 :     sop.sem_flg = 0;
    1058           0 :     if (semop(sem->semid, &sop, 1) == -1)
    1059             :     {
    1060           0 :         _PR_MD_MAP_DEFAULT_ERROR(errno);
    1061           0 :         return PR_FAILURE;
    1062             :     }
    1063           0 :     return PR_SUCCESS;
    1064             : }
    1065             : 
    1066             : PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
    1067             : {
    1068             :     struct sembuf sop;
    1069             : 
    1070           0 :     sop.sem_num = 0;
    1071           0 :     sop.sem_op = 1;
    1072           0 :     sop.sem_flg = 0;
    1073           0 :     if (semop(sem->semid, &sop, 1) == -1)
    1074             :     {
    1075           0 :         _PR_MD_MAP_DEFAULT_ERROR(errno);
    1076           0 :         return PR_FAILURE;
    1077             :     }
    1078           0 :     return PR_SUCCESS;
    1079             : }
    1080             : 
    1081             : PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
    1082             : {
    1083           0 :     PR_Free(sem);
    1084           0 :     return PR_SUCCESS;
    1085             : }
    1086             : 
    1087             : PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
    1088             : {
    1089             :     key_t key;
    1090             :     int semid;
    1091             :     /* On some systems (e.g., glibc 2.0) semctl requires a fourth argument */
    1092             :     union semun unused;
    1093             :     char osname[PR_IPC_NAME_SIZE];
    1094             : 
    1095           0 :     if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
    1096             :         == PR_FAILURE)
    1097             :     {
    1098           0 :         return PR_FAILURE;
    1099             :     }
    1100           0 :     key = ftok(osname, NSPR_IPC_KEY_ID);
    1101           0 :     if ((key_t) -1 == key)
    1102             :     {
    1103           0 :         _PR_MD_MAP_DEFAULT_ERROR(errno);
    1104           0 :         return PR_FAILURE;
    1105             :     }
    1106           0 :     if (unlink(osname) == -1)
    1107             :     {
    1108           0 :         _PR_MD_MAP_UNLINK_ERROR(errno);
    1109           0 :         return PR_FAILURE;
    1110             :     }
    1111           0 :     semid = semget(key, 1, NSPR_SEM_MODE);
    1112           0 :     if (-1 == semid)
    1113             :     {
    1114           0 :         _PR_MD_MAP_DEFAULT_ERROR(errno);
    1115           0 :         return PR_FAILURE;
    1116             :     }
    1117           0 :     unused.val = 0;
    1118           0 :     if (semctl(semid, 0, IPC_RMID, unused) == -1)
    1119             :     { 
    1120           0 :         _PR_MD_MAP_DEFAULT_ERROR(errno);
    1121           0 :         return PR_FAILURE;
    1122             :     }
    1123           0 :     return PR_SUCCESS;
    1124             : }
    1125             : 
    1126             : #else /* neither POSIX nor System V semaphores are available */
    1127             : 
    1128             : PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
    1129             :     const char *name,
    1130             :     PRIntn flags,
    1131             :     PRIntn mode,
    1132             :     PRUintn value)
    1133             : {
    1134             :     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    1135             :     return NULL;
    1136             : }
    1137             : 
    1138             : PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
    1139             : {
    1140             :     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    1141             :     return PR_FAILURE;
    1142             : }
    1143             : 
    1144             : PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
    1145             : {
    1146             :     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    1147             :     return PR_FAILURE;
    1148             : }
    1149             : 
    1150             : PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
    1151             : {
    1152             :     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    1153             :     return PR_FAILURE;
    1154             : }
    1155             : 
    1156             : PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
    1157             : {
    1158             :     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    1159             :     return PR_FAILURE;
    1160             : }
    1161             : 
    1162             : #endif /* end of interprocess named semaphore functions */
    1163             : 
    1164             : /**************************************************************/
    1165             : /**************************************************************/
    1166             : /******************ROUTINES FOR DCE EMULATION******************/
    1167             : /**************************************************************/
    1168             : /**************************************************************/
    1169             : 
    1170             : #include "prpdce.h"
    1171             : 
    1172             : PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock)
    1173             : {
    1174           0 :     PRIntn rv = pthread_mutex_trylock(&lock->mutex);
    1175           0 :     if (rv == PT_TRYLOCK_SUCCESS)
    1176             :     {
    1177           0 :         PR_ASSERT(PR_FALSE == lock->locked);
    1178           0 :         lock->locked = PR_TRUE;
    1179           0 :         lock->owner = pthread_self();
    1180             :     }
    1181             :     /* XXX set error code? */
    1182           0 :     return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE;
    1183             : }  /* PRP_TryLock */
    1184             : 
    1185             : PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)
    1186             : {
    1187             :     PRCondVar *cv;
    1188             : 
    1189           0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
    1190             : 
    1191           0 :     cv = PR_NEW(PRCondVar);
    1192           0 :     if (cv != NULL)
    1193             :     {
    1194             :         int rv;
    1195           0 :         rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
    1196           0 :         PR_ASSERT(0 == rv);
    1197           0 :         if (0 == rv)
    1198             :         {
    1199           0 :             cv->lock = _PR_NAKED_CV_LOCK;
    1200             :         }
    1201             :         else
    1202             :         {
    1203           0 :             PR_DELETE(cv);
    1204           0 :             cv = NULL;
    1205             :         }
    1206             :     }
    1207           0 :     return cv;
    1208             : }  /* PRP_NewNakedCondVar */
    1209             : 
    1210             : PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar)
    1211             : {
    1212             :     int rv;
    1213           0 :     rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
    1214             : #if defined(DEBUG)
    1215           0 :         memset(cvar, 0xaf, sizeof(PRCondVar));
    1216             : #endif
    1217           0 :     PR_Free(cvar);
    1218           0 : }  /* PRP_DestroyNakedCondVar */
    1219             : 
    1220             : PR_IMPLEMENT(PRStatus) PRP_NakedWait(
    1221             :     PRCondVar *cvar, PRLock *ml, PRIntervalTime timeout)
    1222             : {
    1223             :     PRIntn rv;
    1224           0 :     PR_ASSERT(cvar != NULL);
    1225             :     /* XXX do we really want to assert this in a naked wait? */
    1226           0 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(ml->mutex));
    1227           0 :     if (timeout == PR_INTERVAL_NO_TIMEOUT)
    1228           0 :         rv = pthread_cond_wait(&cvar->cv, &ml->mutex);
    1229             :     else
    1230           0 :         rv = pt_TimedWait(&cvar->cv, &ml->mutex, timeout);
    1231           0 :     if (rv != 0)
    1232             :     {
    1233           0 :         _PR_MD_MAP_DEFAULT_ERROR(rv);
    1234           0 :         return PR_FAILURE;
    1235             :     }
    1236           0 :     return PR_SUCCESS;
    1237             : }  /* PRP_NakedWait */
    1238             : 
    1239             : PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar)
    1240             : {
    1241             :     int rv;
    1242           0 :     PR_ASSERT(cvar != NULL);
    1243           0 :     rv = pthread_cond_signal(&cvar->cv);
    1244           0 :     PR_ASSERT(0 == rv);
    1245           0 :     return PR_SUCCESS;
    1246             : }  /* PRP_NakedNotify */
    1247             : 
    1248             : PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar)
    1249             : {
    1250             :     int rv;
    1251           0 :     PR_ASSERT(cvar != NULL);
    1252           0 :     rv = pthread_cond_broadcast(&cvar->cv);
    1253           0 :     PR_ASSERT(0 == rv);
    1254           0 :     return PR_SUCCESS;
    1255             : }  /* PRP_NakedBroadcast */
    1256             : 
    1257             : #endif  /* defined(_PR_PTHREADS) */
    1258             : 
    1259             : /* ptsynch.c */

Generated by: LCOV version 1.13