tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_pl_rwlock.c (5424B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * pkix_pl_rwlock.c
      6 *
      7 * Read/Write Lock Functions
      8 *
      9 */
     10 
     11 #include "pkix_pl_rwlock.h"
     12 
     13 /* --Private-Functions-------------------------------------------- */
     14 
     15 static PKIX_Error *
     16 pkix_pl_RWLock_Destroy(
     17        PKIX_PL_Object *object,
     18        void *plContext)
     19 {
     20        PKIX_PL_RWLock* rwlock = NULL;
     21 
     22        PKIX_ENTER(RWLOCK, "pkix_pl_RWLock_Destroy");
     23        PKIX_NULLCHECK_ONE(object);
     24 
     25        PKIX_CHECK(pkix_CheckType(object, PKIX_RWLOCK_TYPE, plContext),
     26                    PKIX_OBJECTNOTRWLOCK);
     27 
     28        rwlock = (PKIX_PL_RWLock*) object;
     29 
     30        PKIX_RWLOCK_DEBUG("Calling PR_DestroyRWLock)\n");
     31        PR_DestroyRWLock(rwlock->lock);
     32        rwlock->lock = NULL;
     33 
     34 cleanup:
     35 
     36        PKIX_RETURN(RWLOCK);
     37 }
     38 
     39 /*
     40 * FUNCTION: pkix_pl_RWLock_RegisterSelf
     41 * DESCRIPTION:
     42 *  Registers PKIX_RWLOCK_TYPE and its related functions with systemClasses[]
     43 * THREAD SAFETY:
     44 *  Not Thread Safe - for performance and complexity reasons
     45 *
     46 *  Since this function is only called by PKIX_PL_Initialize, which should
     47 *  only be called once, it is acceptable that this function is not
     48 *  thread-safe.
     49 */
     50 PKIX_Error *
     51 pkix_pl_RWLock_RegisterSelf(
     52        void *plContext)
     53 {
     54 
     55        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
     56        pkix_ClassTable_Entry entry;
     57 
     58        PKIX_ENTER(RWLOCK, "pkix_pl_RWLock_RegisterSelf");
     59 
     60        entry.description = "RWLock";
     61        entry.objCounter = 0;
     62        entry.typeObjectSize = sizeof(PKIX_PL_RWLock);
     63        entry.destructor = pkix_pl_RWLock_Destroy;
     64        entry.equalsFunction = NULL;
     65        entry.hashcodeFunction = NULL;
     66        entry.toStringFunction = NULL;
     67        entry.comparator = NULL;
     68        entry.duplicateFunction = NULL;
     69 
     70        systemClasses[PKIX_RWLOCK_TYPE] = entry;
     71 
     72        PKIX_RETURN(RWLOCK);
     73 }
     74 
     75 /* --Public-Functions--------------------------------------------- */
     76 
     77 PKIX_Error *
     78 PKIX_PL_RWLock_Create(
     79        PKIX_PL_RWLock **pNewLock,
     80        void *plContext)
     81 {
     82        PKIX_PL_RWLock *rwLock = NULL;
     83 
     84        PKIX_ENTER(RWLOCK, "PKIX_PL_RWLock_Create");
     85        PKIX_NULLCHECK_ONE(pNewLock);
     86 
     87        PKIX_CHECK(PKIX_PL_Object_Alloc
     88                    (PKIX_RWLOCK_TYPE,
     89                    sizeof (PKIX_PL_RWLock),
     90                    (PKIX_PL_Object **)&rwLock,
     91                    plContext),
     92                    PKIX_ERRORALLOCATINGRWLOCK);
     93 
     94        PKIX_RWLOCK_DEBUG("\tCalling PR_NewRWLock)\n");
     95        rwLock->lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "PKIX RWLock");
     96 
     97        if (rwLock->lock == NULL) {
     98                PKIX_DECREF(rwLock);
     99                PKIX_ERROR(PKIX_OUTOFMEMORY);
    100        }
    101 
    102        rwLock->readCount = 0;
    103        rwLock->writeLocked = PKIX_FALSE;
    104 
    105        *pNewLock = rwLock;
    106 
    107 cleanup:
    108 
    109        PKIX_RETURN(RWLOCK);
    110 }
    111 
    112 PKIX_Error *
    113 PKIX_PL_AcquireReaderLock(
    114        PKIX_PL_RWLock *lock,
    115        void *plContext)
    116 {
    117        PKIX_ENTER(RWLOCK, "PKIX_PL_AcquireReaderLock");
    118        PKIX_NULLCHECK_ONE(lock);
    119 
    120        PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Rlock)\n");
    121        (void) PR_RWLock_Rlock(lock->lock);
    122 
    123        lock->readCount++;
    124 
    125        PKIX_RETURN(RWLOCK);
    126 }
    127 
    128 PKIX_Error *
    129 PKIX_PL_ReleaseReaderLock(
    130        PKIX_PL_RWLock *lock,
    131        void *plContext)
    132 {
    133        PKIX_ENTER(RWLOCK, "PKIX_PL_ReleaseReaderLock");
    134        PKIX_NULLCHECK_ONE(lock);
    135 
    136        PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Unlock)\n");
    137        (void) PR_RWLock_Unlock(lock->lock);
    138 
    139        lock->readCount--;
    140 
    141        PKIX_RETURN(RWLOCK);
    142 }
    143 
    144 PKIX_Error *
    145 PKIX_PL_IsReaderLockHeld(
    146        PKIX_PL_RWLock *lock,
    147        PKIX_Boolean *pIsHeld,
    148        void *plContext)
    149 {
    150        PKIX_ENTER(RWLOCK, "PKIX_PL_IsReaderLockHeld");
    151        PKIX_NULLCHECK_TWO(lock, pIsHeld);
    152 
    153        *pIsHeld = (lock->readCount > 0)?PKIX_TRUE:PKIX_FALSE;
    154 
    155        PKIX_RETURN(RWLOCK);
    156 }
    157 
    158 PKIX_Error *
    159 PKIX_PL_AcquireWriterLock(
    160        PKIX_PL_RWLock *lock,
    161        void *plContext)
    162 {
    163        PKIX_ENTER(RWLOCK, "PKIX_PL_AcquireWriterLock");
    164        PKIX_NULLCHECK_ONE(lock);
    165 
    166        PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Wlock\n");
    167        (void) PR_RWLock_Wlock(lock->lock);
    168 
    169        if (lock->readCount > 0) {
    170                PKIX_ERROR(PKIX_LOCKHASNONZEROREADCOUNT);
    171        }
    172 
    173        /* We should never acquire a write lock if the lock is held */
    174        lock->writeLocked = PKIX_TRUE;
    175 
    176 cleanup:
    177 
    178        PKIX_RETURN(RWLOCK);
    179 }
    180 
    181 PKIX_Error *
    182 PKIX_PL_ReleaseWriterLock(
    183        PKIX_PL_RWLock *lock,
    184        void *plContext)
    185 {
    186        PKIX_ENTER(RWLOCK, "PKIX_PL_ReleaseWriterLock");
    187        PKIX_NULLCHECK_ONE(lock);
    188 
    189        if (lock->readCount > 0) {
    190                PKIX_ERROR(PKIX_LOCKHASNONZEROREADCOUNT);
    191        }
    192 
    193        PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Unlock)\n");
    194        (void) PR_RWLock_Unlock(lock->lock);
    195 
    196        /* XXX Need to think about thread safety here */
    197        /* There should be a single lock holder  */
    198        lock->writeLocked = PKIX_FALSE;
    199 
    200 cleanup:
    201 
    202        PKIX_RETURN(RWLOCK);
    203 }
    204 
    205 PKIX_Error *
    206 PKIX_PL_IsWriterLockHeld(
    207        PKIX_PL_RWLock *lock,
    208        PKIX_Boolean *pIsHeld,
    209        void *plContext)
    210 {
    211        PKIX_ENTER(RWLOCK, "PKIX_PL_IsWriterLockHeld");
    212        PKIX_NULLCHECK_TWO(lock, pIsHeld);
    213 
    214        *pIsHeld = lock->writeLocked;
    215 
    216        PKIX_RETURN(RWLOCK);
    217 }