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-06-02 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           20034 : void _PR_InitLocks(void)
      85                 : {
      86                 :     int rv;
      87           20034 :     rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr); 
      88           20034 :     PR_ASSERT(0 == rv);
      89                 : 
      90                 : #ifdef LINUX
      91                 : #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
      92           20034 :     rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP);
      93           20034 :     PR_ASSERT(0 == rv);
      94                 : #endif
      95                 : #endif
      96                 : 
      97           20034 :     rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
      98           20034 :     PR_ASSERT(0 == rv);
      99           20034 : }
     100                 : 
     101          609115 : static void pt_PostNotifies(PRLock *lock, PRBool unlock)
     102                 : {
     103                 :     PRIntn index, rv;
     104                 :     _PT_Notified post;
     105          609115 :     _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          609115 :     post = lock->notified;  /* a safe copy; we own the lock */
     113                 : 
     114                 : #if defined(DEBUG)
     115          609115 :     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          609115 :     if (unlock)
     123                 :     {
     124          575092 :         rv = pthread_mutex_unlock(&lock->mutex);
     125          575092 :         PR_ASSERT(0 == rv);
     126                 :     }
     127                 : 
     128          609115 :     notified = &post;  /* this is where we start */
     129                 :     do
     130                 :     {
     131         1218231 :         for (index = 0; index < notified->length; ++index)
     132                 :         {
     133          609115 :             PRCondVar *cv = notified->cv[index].cv;
     134          609115 :             PR_ASSERT(NULL != cv);
     135          609114 :             PR_ASSERT(0 != notified->cv[index].times);
     136          609114 :             if (-1 == notified->cv[index].times)
     137                 :             {
     138          497062 :                 rv = pthread_cond_broadcast(&cv->cv);
     139          497064 :                 PR_ASSERT(0 == rv);
     140                 :             }
     141                 :             else
     142                 :             {
     143          336156 :                 while (notified->cv[index].times-- > 0)
     144                 :                 {
     145          112052 :                     rv = pthread_cond_signal(&cv->cv);
     146          112052 :                     PR_ASSERT(0 == rv);
     147                 :                 }
     148                 :             }
     149                 : #if defined(DEBUG)
     150          609115 :             pt_debug.cvars_notified += 1;
     151          609115 :             if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
     152                 :             {
     153             472 :                 pt_debug.delayed_cv_deletes += 1;
     154             472 :                 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          609116 :         prev = notified;
     162          609116 :         notified = notified->link;
     163          609116 :         if (&post != prev) PR_DELETE(prev);
     164          609116 :     } while (NULL != notified);
     165          609115 : }  /* pt_PostNotifies */
     166                 : 
     167          958182 : PR_IMPLEMENT(PRLock*) PR_NewLock(void)
     168                 : {
     169                 :     PRIntn rv;
     170                 :     PRLock *lock;
     171                 : 
     172          958182 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     173                 : 
     174          958182 :     lock = PR_NEWZAP(PRLock);
     175          958182 :     if (lock != NULL)
     176                 :     {
     177          958182 :         rv = _PT_PTHREAD_MUTEX_INIT(lock->mutex, _pt_mattr); 
     178          958182 :         PR_ASSERT(0 == rv);
     179                 :     }
     180                 : #if defined(DEBUG)
     181          958182 :     pt_debug.locks_created += 1;
     182                 : #endif
     183          958182 :     return lock;
     184                 : }  /* PR_NewLock */
     185                 : 
     186          613801 : PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
     187                 : {
     188                 :     PRIntn rv;
     189          613801 :     PR_ASSERT(NULL != lock);
     190          613801 :     PR_ASSERT(PR_FALSE == lock->locked);
     191          613801 :     PR_ASSERT(0 == lock->notified.length);
     192          613801 :     PR_ASSERT(NULL == lock->notified.link);
     193          613801 :     rv = pthread_mutex_destroy(&lock->mutex);
     194          613801 :     PR_ASSERT(0 == rv);
     195                 : #if defined(DEBUG)
     196          613801 :     memset(lock, 0xaf, sizeof(PRLock));
     197          613801 :     pt_debug.locks_destroyed += 1;
     198                 : #endif
     199          613801 :     PR_Free(lock);
     200          613801 : }  /* PR_DestroyLock */
     201                 : 
     202       277847110 : PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
     203                 : {
     204                 :     PRIntn rv;
     205       277847110 :     PR_ASSERT(lock != NULL);
     206       277847110 :     rv = pthread_mutex_lock(&lock->mutex);
     207       277868845 :     PR_ASSERT(0 == rv);
     208       277868334 :     PR_ASSERT(0 == lock->notified.length);
     209       277868334 :     PR_ASSERT(NULL == lock->notified.link);
     210       277868334 :     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       277868334 :     lock->owner = pthread_self();
     216       277869580 :     lock->locked = PR_TRUE;
     217                 : #if defined(DEBUG)
     218       277869580 :     pt_debug.locks_acquired += 1;
     219                 : #endif
     220       277869580 : }  /* PR_Lock */
     221                 : 
     222       277869646 : PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
     223                 : {
     224                 :     PRIntn rv;
     225                 : 
     226       277869646 :     PR_ASSERT(lock != NULL);
     227       277869646 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
     228       277871731 :     PR_ASSERT(PR_TRUE == lock->locked);
     229       277871731 :     PR_ASSERT(pthread_equal(lock->owner, pthread_self()));
     230                 : 
     231       277869320 :     if (!lock->locked || !pthread_equal(lock->owner, pthread_self()))
     232               0 :         return PR_FAILURE;
     233                 : 
     234       277868281 :     lock->locked = PR_FALSE;
     235       277868281 :     if (0 == lock->notified.length)  /* shortcut */
     236                 :     {
     237       277293189 :         rv = pthread_mutex_unlock(&lock->mutex);
     238       277288671 :         PR_ASSERT(0 == rv);
     239                 :     }
     240          575092 :     else pt_PostNotifies(lock, PR_TRUE);
     241                 : 
     242                 : #if defined(DEBUG)
     243       277855024 :     pt_debug.locks_released += 1;
     244                 : #endif
     245       277855024 :     return PR_SUCCESS;
     246                 : }  /* PR_Unlock */
     247                 : 
     248         5146869 : 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         5146869 :     PR_ASSERT(lock->locked && pthread_equal(lock->owner, pthread_self()));
     255         5146865 : }
     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           35604 : 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           35604 :     PRUint32 ticks = PR_TicksPerSecond();
     279                 : 
     280           35604 :     tmo.tv_sec = (PRInt32)(timeout / ticks);
     281           35604 :     tmo.tv_nsec = (PRInt32)(timeout - (tmo.tv_sec * ticks));
     282           35604 :     tmo.tv_nsec = (PRInt32)PR_IntervalToMicroseconds(PT_NANOPERMICRO * tmo.tv_nsec);
     283                 : 
     284                 :     /* pthreads wants this in absolute time, off we go ... */
     285           35604 :     (void)GETTIMEOFDAY(&now);
     286                 :     /* that one's usecs, this one's nsecs - grrrr! */
     287           35604 :     tmo.tv_sec += now.tv_sec;
     288           35604 :     tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec);
     289           35604 :     tmo.tv_sec += tmo.tv_nsec / PT_BILLION;
     290           35604 :     tmo.tv_nsec %= PT_BILLION;
     291                 : 
     292           35604 :     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           35603 :     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          609115 : static void pt_PostNotifyToCvar(PRCondVar *cvar, PRBool broadcast)
     310                 : {
     311          609115 :     PRIntn index = 0;
     312          609115 :     _PT_Notified *notified = &cvar->lock->notified;
     313                 : 
     314          609115 :     PR_ASSERT(PR_TRUE == cvar->lock->locked);
     315          609115 :     PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
     316          609115 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
     317                 : 
     318                 :     while (1)
     319                 :     {
     320          609116 :         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          609116 :         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          609116 :     (void)PR_ATOMIC_INCREMENT(&cvar->notify_pending);
     342         1106180 :     notified->cv[index].times = (broadcast) ? -1 : 1;
     343          609116 :     notified->cv[index].cv = cvar;
     344          609116 :     notified->length += 1;
     345                 : 
     346                 : finished:
     347          609116 :     PR_ASSERT(PR_TRUE == cvar->lock->locked);
     348          609116 :     PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
     349          609116 : }  /* pt_PostNotifyToCvar */
     350                 : 
     351          157745 : PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
     352                 : {
     353          157745 :     PRCondVar *cv = PR_NEW(PRCondVar);
     354          157745 :     PR_ASSERT(lock != NULL);
     355          157745 :     if (cv != NULL)
     356                 :     {
     357          157745 :         int rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr); 
     358          157745 :         PR_ASSERT(0 == rv);
     359          157745 :         cv->lock = lock;
     360          157745 :         cv->notify_pending = 0;
     361                 : #if defined(DEBUG)
     362          157745 :         pt_debug.cvars_created += 1;
     363                 : #endif
     364                 :     }
     365          157745 :     return cv;
     366                 : }  /* PR_NewCondVar */
     367                 : 
     368          145644 : PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
     369                 : {
     370          145644 :     if (0 > PR_ATOMIC_DECREMENT(&cvar->notify_pending))
     371                 :     {
     372          145172 :         PRIntn rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
     373                 : #if defined(DEBUG)
     374          145172 :         memset(cvar, 0xaf, sizeof(PRCondVar));
     375          145172 :         pt_debug.cvars_destroyed += 1;
     376                 : #endif
     377          145172 :         PR_Free(cvar);
     378                 :     }
     379          145644 : }  /* PR_DestroyCondVar */
     380                 : 
     381          184232 : PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
     382                 : {
     383                 :     PRIntn rv;
     384          184232 :     PRThread *thred = PR_GetCurrentThread();
     385                 : 
     386          184232 :     PR_ASSERT(cvar != NULL);
     387                 :     /* We'd better be locked */
     388          184232 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
     389          184232 :     PR_ASSERT(PR_TRUE == cvar->lock->locked);
     390                 :     /* and it better be by us */
     391          184232 :     PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
     392                 : 
     393          184232 :     if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
     394                 : 
     395                 :     /*
     396                 :      * The thread waiting is used for PR_Interrupt
     397                 :      */
     398          184232 :     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          184232 :     if (0 != cvar->lock->notified.length)
     409           34024 :         pt_PostNotifies(cvar->lock, PR_FALSE);
     410                 : 
     411                 :     /*
     412                 :      * We're surrendering the lock, so clear out the locked field.
     413                 :      */
     414          184232 :     cvar->lock->locked = PR_FALSE;
     415                 : 
     416          184232 :     if (timeout == PR_INTERVAL_NO_TIMEOUT)
     417          148628 :         rv = pthread_cond_wait(&cvar->cv, &cvar->lock->mutex);
     418                 :     else
     419           35604 :         rv = pt_TimedWait(&cvar->cv, &cvar->lock->mutex, timeout);
     420                 : 
     421                 :     /* We just got the lock back - this better be empty */
     422          184230 :     PR_ASSERT(PR_FALSE == cvar->lock->locked);
     423          184230 :     cvar->lock->locked = PR_TRUE;
     424          184230 :     cvar->lock->owner = pthread_self();
     425                 : 
     426          184230 :     PR_ASSERT(0 == cvar->lock->notified.length);
     427          184230 :     thred->waiting = NULL;  /* and now we're not */
     428          184230 :     if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
     429          184230 :     if (rv != 0)
     430                 :     {
     431               0 :         _PR_MD_MAP_DEFAULT_ERROR(rv);
     432               0 :         return PR_FAILURE;
     433                 :     }
     434          184230 :     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          105257 : PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar)
     443                 : {
     444          105257 :     PR_ASSERT(cvar != NULL);   
     445          105257 :     pt_PostNotifyToCvar(cvar, PR_FALSE);
     446          105257 :     return PR_SUCCESS;
     447                 : }  /* PR_NotifyCondVar */
     448                 : 
     449          180654 : PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
     450                 : {
     451          180654 :     PR_ASSERT(cvar != NULL);
     452          180654 :     pt_PostNotifyToCvar(cvar, PR_TRUE);
     453          180654 :     return PR_SUCCESS;
     454                 : }  /* PR_NotifyAllCondVar */
     455                 : 
     456                 : /**************************************************************/
     457                 : /**************************************************************/
     458                 : /***************************MONITORS***************************/
     459                 : /**************************************************************/
     460                 : /**************************************************************/
     461                 : 
     462          246615 : PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
     463                 : {
     464                 :     PRMonitor *mon;
     465                 :     PRCondVar *cvar;
     466                 :     int rv;
     467                 : 
     468          246615 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     469                 : 
     470          246615 :     cvar = PR_NEWZAP(PRCondVar);
     471          246615 :     if (NULL == cvar)
     472                 :     {
     473               0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     474               0 :         return NULL;
     475                 :     }
     476          246615 :     mon = PR_NEWZAP(PRMonitor);
     477          246615 :     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          246615 :     rv = _PT_PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr); 
     485          246615 :     PR_ASSERT(0 == rv);
     486          246615 :     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          246615 :     _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
     495                 : 
     496          246615 :     mon->cvar = cvar;
     497          246615 :     rv = _PT_PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr); 
     498          246615 :     PR_ASSERT(0 == rv);
     499          246615 :     mon->entryCount = 0;
     500          246615 :     mon->cvar->lock = &mon->lock;
     501          246615 :     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          246615 :     return mon;
     510                 : }  /* PR_NewMonitor */
     511                 : 
     512           20034 : PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
     513                 : {
     514           20034 :     PRMonitor* mon = PR_NewMonitor();
     515           20034 :     if (mon)
     516           20034 :         mon->name = name;
     517           20034 :     return mon;
     518                 : }
     519                 : 
     520           47605 : PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
     521                 : {
     522                 :     int rv;
     523           47605 :     PR_ASSERT(mon != NULL);
     524           47605 :     PR_DestroyCondVar(mon->cvar);
     525           47605 :     rv = pthread_mutex_destroy(&mon->lock.mutex); PR_ASSERT(0 == rv);
     526                 : #if defined(DEBUG)
     527           47605 :         memset(mon, 0xaf, sizeof(PRMonitor));
     528                 : #endif
     529           47605 :     PR_Free(mon);    
     530           47605 : }  /* 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            1960 : PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
     537                 : {
     538            1960 :     pthread_t self = pthread_self();
     539            1960 :     if (pthread_equal(mon->owner, self))
     540            1100 :         return mon->entryCount;
     541             860 :     return 0;
     542                 : }
     543                 : 
     544         5062676 : PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
     545                 : {
     546         5062676 :     PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(&mon->lock);
     547         5062676 : }
     548                 : 
     549        21827741 : PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
     550                 : {
     551        21827741 :     pthread_t self = pthread_self();
     552                 : 
     553        21827741 :     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        21827741 :     if (!pthread_equal(mon->owner, self))
     560                 :     {
     561        21378799 :         PR_Lock(&mon->lock);
     562                 :         /* and now I have the lock */
     563        21378824 :         PR_ASSERT(0 == mon->entryCount);
     564        21378824 :         PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
     565        21378824 :         _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
     566                 :     }
     567        21827739 :     mon->entryCount += 1;
     568        21827739 : }  /* PR_EnterMonitor */
     569                 : 
     570        21827498 : PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
     571                 : {
     572        21827498 :     pthread_t self = pthread_self();
     573                 : 
     574        21827506 :     PR_ASSERT(mon != NULL);
     575                 :     /* The lock better be that - locked */
     576        21827506 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     577                 :     /* we'd better be the owner */
     578        21827651 :     PR_ASSERT(pthread_equal(mon->owner, self));
     579        21827634 :     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        21827616 :     PR_ASSERT(mon->entryCount > 0);
     584        21827540 :     mon->entryCount -= 1;  /* reduce by one */
     585        21827540 :     if (mon->entryCount == 0)
     586                 :     {
     587                 :         /* and if it transitioned to zero - unlock */
     588        21378622 :         _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);  /* make the owner unknown */
     589        21378622 :         PR_Unlock(&mon->lock);
     590                 :     }
     591        21827528 :     return PR_SUCCESS;
     592                 : }  /* PR_ExitMonitor */
     593                 : 
     594           68038 : PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
     595                 : {
     596                 :     PRStatus rv;
     597                 :     PRInt16 saved_entries;
     598                 :     pthread_t saved_owner;
     599                 : 
     600           68038 :     PR_ASSERT(mon != NULL);
     601                 :     /* we'd better be locked */
     602           68038 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     603                 :     /* and the entries better be positive */
     604           68038 :     PR_ASSERT(mon->entryCount > 0);
     605                 :     /* and it better be by us */
     606           68038 :     PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
     607                 : 
     608                 :     /* tuck these away 'till later */
     609           68038 :     saved_entries = mon->entryCount; 
     610           68038 :     mon->entryCount = 0;
     611           68038 :     _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
     612           68038 :     _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
     613                 :     
     614           68038 :     rv = PR_WaitCondVar(mon->cvar, timeout);
     615                 : 
     616                 :     /* reinstate the intresting information */
     617           68038 :     mon->entryCount = saved_entries;
     618           68038 :     _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);
     619                 : 
     620           68038 :     return rv;
     621                 : }  /* PR_Wait */
     622                 : 
     623            6795 : PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
     624                 : {
     625            6795 :     PR_ASSERT(NULL != mon);
     626                 :     /* we'd better be locked */
     627            6795 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     628                 :     /* and the entries better be positive */
     629            6795 :     PR_ASSERT(mon->entryCount > 0);
     630                 :     /* and it better be by us */
     631            6795 :     PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
     632                 : 
     633            6795 :     pt_PostNotifyToCvar(mon->cvar, PR_FALSE);
     634                 : 
     635            6795 :     return PR_SUCCESS;
     636                 : }  /* PR_Notify */
     637                 : 
     638          316410 : PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
     639                 : {
     640          316410 :     PR_ASSERT(mon != NULL);
     641                 :     /* we'd better be locked */
     642          316410 :     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     643                 :     /* and the entries better be positive */
     644          316410 :     PR_ASSERT(mon->entryCount > 0);
     645                 :     /* and it better be by us */
     646          316410 :     PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
     647                 : 
     648          316410 :     pt_PostNotifyToCvar(mon->cvar, PR_TRUE);
     649                 : 
     650          316409 :     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