1 /* 2 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 9 /* Mutex and recursive_lock code */ 10 11 #include "fssh_lock.h" 12 13 #include "fssh_kernel_export.h" 14 15 16 #define FSSH_RW_MAX_READERS 100000 17 18 19 extern "C" int32_t 20 fssh_recursive_lock_get_recursion(fssh_recursive_lock *lock) 21 { 22 if (lock->holder == fssh_find_thread(NULL)) 23 return lock->recursion; 24 25 return -1; 26 } 27 28 29 extern "C" void 30 fssh_recursive_lock_init(fssh_recursive_lock *lock, const char *name) 31 { 32 if (lock == NULL) 33 return; 34 35 if (name == NULL) 36 name = "recursive lock"; 37 38 lock->holder = -1; 39 lock->recursion = 0; 40 lock->sem = fssh_create_sem(1, name); 41 if (lock->sem < FSSH_B_OK) 42 fssh_panic("could not create recursive lock"); 43 } 44 45 46 extern "C" void 47 fssh_recursive_lock_destroy(fssh_recursive_lock *lock) 48 { 49 if (lock == NULL) 50 return; 51 52 fssh_delete_sem(lock->sem); 53 lock->sem = -1; 54 } 55 56 57 extern "C" fssh_status_t 58 fssh_recursive_lock_lock(fssh_recursive_lock *lock) 59 { 60 fssh_thread_id thread = fssh_find_thread(NULL); 61 62 if (thread != lock->holder) { 63 fssh_status_t status = fssh_acquire_sem(lock->sem); 64 if (status < FSSH_B_OK) 65 return status; 66 67 lock->holder = thread; 68 } 69 lock->recursion++; 70 return FSSH_B_OK; 71 } 72 73 74 extern "C" fssh_status_t 75 fssh_recursive_lock_trylock(fssh_recursive_lock *lock) 76 { 77 fssh_thread_id thread = fssh_find_thread(NULL); 78 79 if (thread != lock->holder) { 80 fssh_status_t status = fssh_acquire_sem_etc(lock->sem, 1, 81 FSSH_B_RELATIVE_TIMEOUT, 0); 82 if (status < FSSH_B_OK) 83 return status; 84 85 lock->holder = thread; 86 } 87 lock->recursion++; 88 return FSSH_B_OK; 89 } 90 91 92 extern "C" void 93 fssh_recursive_lock_unlock(fssh_recursive_lock *lock) 94 { 95 if (fssh_find_thread(NULL) != lock->holder) 96 fssh_panic("recursive_lock %p unlocked by non-holder thread!\n", lock); 97 98 if (--lock->recursion == 0) { 99 lock->holder = -1; 100 fssh_release_sem(lock->sem); 101 } 102 } 103 104 105 // #pragma mark - 106 107 108 extern "C" void 109 fssh_mutex_init(fssh_mutex *m, const char *name) 110 { 111 if (m == NULL) 112 return; 113 114 if (name == NULL) 115 name = "mutex_sem"; 116 117 m->holder = -1; 118 119 m->sem = fssh_create_sem(1, name); 120 if (m->sem < FSSH_B_OK) 121 fssh_panic("could not create mutex"); 122 } 123 124 125 extern "C" void 126 fssh_mutex_init_etc(fssh_mutex *m, const char *name, uint32_t flags) 127 { 128 fssh_mutex_init(m, name); 129 } 130 131 132 extern "C" void 133 fssh_mutex_destroy(fssh_mutex *mutex) 134 { 135 if (mutex == NULL) 136 return; 137 138 if (mutex->sem >= 0) { 139 fssh_delete_sem(mutex->sem); 140 mutex->sem = -1; 141 } 142 mutex->holder = -1; 143 } 144 145 146 extern "C" fssh_status_t 147 fssh_mutex_lock(fssh_mutex *mutex) 148 { 149 fssh_thread_id me = fssh_find_thread(NULL); 150 fssh_status_t status; 151 152 status = fssh_acquire_sem(mutex->sem); 153 if (status < FSSH_B_OK) 154 return status; 155 156 if (me == mutex->holder) 157 fssh_panic("mutex_lock failure: mutex %p (sem = 0x%x) acquired twice by thread 0x%x\n", mutex, (int)mutex->sem, (int)me); 158 159 mutex->holder = me; 160 return FSSH_B_OK; 161 } 162 163 164 extern "C" void 165 fssh_mutex_unlock(fssh_mutex *mutex) 166 { 167 fssh_thread_id me = fssh_find_thread(NULL); 168 169 if (me != mutex->holder) { 170 fssh_panic("mutex_unlock failure: thread 0x%x is trying to release mutex %p (current holder 0x%x)\n", 171 (int)me, mutex, (int)mutex->holder); 172 } 173 174 mutex->holder = -1; 175 fssh_release_sem(mutex->sem); 176 } 177 178 179 extern "C" void 180 fssh_mutex_transfer_lock(fssh_mutex *mutex, fssh_thread_id thread) 181 { 182 mutex->holder = thread; 183 } 184 185 186 // #pragma mark - 187 188 189 extern "C" void 190 fssh_rw_lock_init(fssh_rw_lock *lock, const char *name) 191 { 192 if (lock == NULL) 193 return; 194 195 if (name == NULL) 196 name = "r/w lock"; 197 198 lock->count = 0; 199 lock->holder = -1; 200 201 lock->sem = fssh_create_sem(FSSH_RW_MAX_READERS, name); 202 if (lock->sem < FSSH_B_OK) 203 fssh_panic("could not create r/w lock"); 204 } 205 206 207 extern "C" void 208 fssh_rw_lock_init_etc(fssh_rw_lock *lock, const char *name, uint32_t flags) 209 { 210 fssh_rw_lock_init(lock, name); 211 } 212 213 214 extern "C" void 215 fssh_rw_lock_destroy(fssh_rw_lock *lock) 216 { 217 if (lock == NULL) 218 return; 219 220 fssh_delete_sem(lock->sem); 221 } 222 223 224 extern "C" fssh_status_t 225 fssh_rw_lock_read_lock(fssh_rw_lock *lock) 226 { 227 if (lock->holder == fssh_find_thread(NULL)) { 228 lock->count++; 229 return FSSH_B_OK; 230 } 231 232 return fssh_acquire_sem(lock->sem); 233 } 234 235 236 extern "C" fssh_status_t 237 fssh_rw_lock_read_unlock(fssh_rw_lock *lock) 238 { 239 if (lock->holder == fssh_find_thread(NULL) && --lock->count > 0) 240 return FSSH_B_OK; 241 242 return fssh_release_sem(lock->sem); 243 } 244 245 246 extern "C" fssh_status_t 247 fssh_rw_lock_write_lock(fssh_rw_lock *lock) 248 { 249 if (lock->holder == fssh_find_thread(NULL)) { 250 lock->count++; 251 return FSSH_B_OK; 252 } 253 254 fssh_status_t status = fssh_acquire_sem_etc(lock->sem, FSSH_RW_MAX_READERS, 255 0, 0); 256 if (status == FSSH_B_OK) { 257 lock->holder = fssh_find_thread(NULL); 258 lock->count = 1; 259 } 260 return status; 261 } 262 263 264 extern "C" fssh_status_t 265 fssh_rw_lock_write_unlock(fssh_rw_lock *lock) 266 { 267 if (--lock->count > 0) 268 return FSSH_B_OK; 269 270 lock->holder = -1; 271 272 return fssh_release_sem_etc(lock->sem, FSSH_RW_MAX_READERS, 0); 273 } 274 275