1 /* 2 * Copyright 2002-2007, 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 "lock.h" 12 13 #include "fssh_kernel_export.h" 14 15 16 namespace FSShell { 17 18 19 int32_t 20 recursive_lock_get_recursion(recursive_lock *lock) 21 { 22 if (lock->holder == fssh_find_thread(NULL)) 23 return lock->recursion; 24 25 return -1; 26 } 27 28 29 fssh_status_t 30 recursive_lock_init(recursive_lock *lock, const char *name) 31 { 32 if (lock == NULL) 33 return FSSH_B_BAD_VALUE; 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 42 if (lock->sem >= FSSH_B_OK) 43 return FSSH_B_OK; 44 45 return lock->sem; 46 } 47 48 49 void 50 recursive_lock_destroy(recursive_lock *lock) 51 { 52 if (lock == NULL) 53 return; 54 55 fssh_delete_sem(lock->sem); 56 lock->sem = -1; 57 } 58 59 60 fssh_status_t 61 recursive_lock_lock(recursive_lock *lock) 62 { 63 fssh_thread_id thread = fssh_find_thread(NULL); 64 65 if (thread != lock->holder) { 66 fssh_status_t status = fssh_acquire_sem(lock->sem); 67 if (status < FSSH_B_OK) 68 return status; 69 70 lock->holder = thread; 71 } 72 lock->recursion++; 73 return FSSH_B_OK; 74 } 75 76 77 void 78 recursive_lock_unlock(recursive_lock *lock) 79 { 80 if (fssh_find_thread(NULL) != lock->holder) 81 fssh_panic("recursive_lock %p unlocked by non-holder thread!\n", lock); 82 83 if (--lock->recursion == 0) { 84 lock->holder = -1; 85 fssh_release_sem(lock->sem); 86 } 87 } 88 89 90 // #pragma mark - 91 92 93 fssh_status_t 94 mutex_init(mutex *m, const char *name) 95 { 96 if (m == NULL) 97 return FSSH_EINVAL; 98 99 if (name == NULL) 100 name = "mutex_sem"; 101 102 m->holder = -1; 103 104 m->sem = fssh_create_sem(1, name); 105 if (m->sem >= FSSH_B_OK) 106 return FSSH_B_OK; 107 108 return m->sem; 109 } 110 111 112 void 113 mutex_destroy(mutex *mutex) 114 { 115 if (mutex == NULL) 116 return; 117 118 if (mutex->sem >= 0) { 119 fssh_delete_sem(mutex->sem); 120 mutex->sem = -1; 121 } 122 mutex->holder = -1; 123 } 124 125 126 fssh_status_t 127 mutex_lock(mutex *mutex) 128 { 129 fssh_thread_id me = fssh_find_thread(NULL); 130 fssh_status_t status; 131 132 status = fssh_acquire_sem(mutex->sem); 133 if (status < FSSH_B_OK) 134 return status; 135 136 if (me == mutex->holder) 137 fssh_panic("mutex_lock failure: mutex %p (sem = 0x%x) acquired twice by thread 0x%x\n", mutex, (int)mutex->sem, (int)me); 138 139 mutex->holder = me; 140 return FSSH_B_OK; 141 } 142 143 144 void 145 mutex_unlock(mutex *mutex) 146 { 147 fssh_thread_id me = fssh_find_thread(NULL); 148 149 if (me != mutex->holder) { 150 fssh_panic("mutex_unlock failure: thread 0x%x is trying to release mutex %p (current holder 0x%x)\n", 151 (int)me, mutex, (int)mutex->holder); 152 } 153 154 mutex->holder = -1; 155 fssh_release_sem(mutex->sem); 156 } 157 158 159 // #pragma mark - 160 161 162 fssh_status_t 163 benaphore_init(benaphore *ben, const char *name) 164 { 165 if (ben == NULL || name == NULL) 166 return FSSH_B_BAD_VALUE; 167 168 ben->count = 1; 169 ben->sem = fssh_create_sem(0, name); 170 if (ben->sem >= FSSH_B_OK) 171 return FSSH_B_OK; 172 173 return ben->sem; 174 } 175 176 177 void 178 benaphore_destroy(benaphore *ben) 179 { 180 fssh_delete_sem(ben->sem); 181 ben->sem = -1; 182 } 183 184 185 // #pragma mark - 186 187 188 fssh_status_t 189 rw_lock_init(rw_lock *lock, const char *name) 190 { 191 if (lock == NULL) 192 return FSSH_B_BAD_VALUE; 193 194 if (name == NULL) 195 name = "r/w lock"; 196 197 lock->sem = fssh_create_sem(FSSH_RW_MAX_READERS, name); 198 if (lock->sem >= FSSH_B_OK) 199 return FSSH_B_OK; 200 201 return lock->sem; 202 } 203 204 205 void 206 rw_lock_destroy(rw_lock *lock) 207 { 208 if (lock == NULL) 209 return; 210 211 fssh_delete_sem(lock->sem); 212 } 213 214 215 fssh_status_t 216 rw_lock_read_lock(rw_lock *lock) 217 { 218 return fssh_acquire_sem(lock->sem); 219 } 220 221 222 fssh_status_t 223 rw_lock_read_unlock(rw_lock *lock) 224 { 225 return fssh_release_sem(lock->sem); 226 } 227 228 229 fssh_status_t 230 rw_lock_write_lock(rw_lock *lock) 231 { 232 return fssh_acquire_sem_etc(lock->sem, FSSH_RW_MAX_READERS, 0, 0); 233 } 234 235 236 fssh_status_t 237 rw_lock_write_unlock(rw_lock *lock) 238 { 239 return fssh_release_sem_etc(lock->sem, FSSH_RW_MAX_READERS, 0); 240 } 241 242 243 } // namespace FSShell 244