LCOV - app.info - nsprpub/pr/src/pthreads/ptsynch.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/pthreads - ptsynch.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 440 | 241 | 54.8 %
| Date: | 2012-04-21 | Functions: | 39 | 24 | 61.5 %

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

Generated by: LCOV version 1.7