nsprpub/pr/src/threads/prsem.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "primpl.h"
michael@0 7 #include "obsolete/prsem.h"
michael@0 8
michael@0 9 /************************************************************************/
michael@0 10
michael@0 11 /*
michael@0 12 ** Create a new semaphore.
michael@0 13 */
michael@0 14 PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value)
michael@0 15 {
michael@0 16 PRSemaphore *sem;
michael@0 17 PRCondVar *cvar;
michael@0 18 PRLock *lock;
michael@0 19
michael@0 20 sem = PR_NEWZAP(PRSemaphore);
michael@0 21 if (sem) {
michael@0 22 #ifdef HAVE_CVAR_BUILT_ON_SEM
michael@0 23 _PR_MD_NEW_SEM(&sem->md, value);
michael@0 24 #else
michael@0 25 lock = PR_NewLock();
michael@0 26 if (!lock) {
michael@0 27 PR_DELETE(sem);
michael@0 28 return NULL;
michael@0 29 }
michael@0 30
michael@0 31 cvar = PR_NewCondVar(lock);
michael@0 32 if (!cvar) {
michael@0 33 PR_DestroyLock(lock);
michael@0 34 PR_DELETE(sem);
michael@0 35 return NULL;
michael@0 36 }
michael@0 37 sem->cvar = cvar;
michael@0 38 sem->count = value;
michael@0 39 #endif
michael@0 40 }
michael@0 41 return sem;
michael@0 42 }
michael@0 43
michael@0 44 /*
michael@0 45 ** Destroy a semaphore. There must be no thread waiting on the semaphore.
michael@0 46 ** The caller is responsible for guaranteeing that the semaphore is
michael@0 47 ** no longer in use.
michael@0 48 */
michael@0 49 PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *sem)
michael@0 50 {
michael@0 51 #ifdef HAVE_CVAR_BUILT_ON_SEM
michael@0 52 _PR_MD_DESTROY_SEM(&sem->md);
michael@0 53 #else
michael@0 54 PR_ASSERT(sem->waiters == 0);
michael@0 55
michael@0 56 PR_DestroyLock(sem->cvar->lock);
michael@0 57 PR_DestroyCondVar(sem->cvar);
michael@0 58 #endif
michael@0 59 PR_DELETE(sem);
michael@0 60 }
michael@0 61
michael@0 62 /*
michael@0 63 ** Wait on a Semaphore.
michael@0 64 **
michael@0 65 ** This routine allows a calling thread to wait or proceed depending upon the
michael@0 66 ** state of the semahore sem. The thread can proceed only if the counter value
michael@0 67 ** of the semaphore sem is currently greater than 0. If the value of semaphore
michael@0 68 ** sem is positive, it is decremented by one and the routine returns immediately
michael@0 69 ** allowing the calling thread to continue. If the value of semaphore sem is 0,
michael@0 70 ** the calling thread blocks awaiting the semaphore to be released by another
michael@0 71 ** thread.
michael@0 72 **
michael@0 73 ** This routine can return PR_PENDING_INTERRUPT if the waiting thread
michael@0 74 ** has been interrupted.
michael@0 75 */
michael@0 76 PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *sem)
michael@0 77 {
michael@0 78 PRStatus status = PR_SUCCESS;
michael@0 79
michael@0 80 #ifdef HAVE_CVAR_BUILT_ON_SEM
michael@0 81 return _PR_MD_WAIT_SEM(&sem->md);
michael@0 82 #else
michael@0 83 PR_Lock(sem->cvar->lock);
michael@0 84 while (sem->count == 0) {
michael@0 85 sem->waiters++;
michael@0 86 status = PR_WaitCondVar(sem->cvar, PR_INTERVAL_NO_TIMEOUT);
michael@0 87 sem->waiters--;
michael@0 88 if (status != PR_SUCCESS)
michael@0 89 break;
michael@0 90 }
michael@0 91 if (status == PR_SUCCESS)
michael@0 92 sem->count--;
michael@0 93 PR_Unlock(sem->cvar->lock);
michael@0 94 #endif
michael@0 95
michael@0 96 return (status);
michael@0 97 }
michael@0 98
michael@0 99 /*
michael@0 100 ** This routine increments the counter value of the semaphore. If other threads
michael@0 101 ** are blocked for the semaphore, then the scheduler will determine which ONE
michael@0 102 ** thread will be unblocked.
michael@0 103 */
michael@0 104 PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *sem)
michael@0 105 {
michael@0 106 #ifdef HAVE_CVAR_BUILT_ON_SEM
michael@0 107 _PR_MD_POST_SEM(&sem->md);
michael@0 108 #else
michael@0 109 PR_Lock(sem->cvar->lock);
michael@0 110 if (sem->waiters)
michael@0 111 PR_NotifyCondVar(sem->cvar);
michael@0 112 sem->count++;
michael@0 113 PR_Unlock(sem->cvar->lock);
michael@0 114 #endif
michael@0 115 }
michael@0 116
michael@0 117 #if DEBUG
michael@0 118 /*
michael@0 119 ** Returns the value of the semaphore referenced by sem without affecting
michael@0 120 ** the state of the semaphore. The value represents the semaphore vaule
michael@0 121 ** at the time of the call, but may not be the actual value when the
michael@0 122 ** caller inspects it. (FOR DEBUGGING ONLY)
michael@0 123 */
michael@0 124 PR_IMPLEMENT(PRUintn) PR_GetValueSem(PRSemaphore *sem)
michael@0 125 {
michael@0 126 PRUintn rv;
michael@0 127
michael@0 128 #ifdef HAVE_CVAR_BUILT_ON_SEM
michael@0 129 rv = _PR_MD_GET_VALUE_SEM(&sem->md);
michael@0 130 #else
michael@0 131 PR_Lock(sem->cvar->lock);
michael@0 132 rv = sem->count;
michael@0 133 PR_Unlock(sem->cvar->lock);
michael@0 134 #endif
michael@0 135
michael@0 136 return rv;
michael@0 137 }
michael@0 138 #endif

mercurial