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 }