vfs: check userland buffers before reading them.
[haiku.git] / src / tools / fs_shell / lock.cpp
blob5008c77a219e985d9d153058d29520972d3bad21
1 /*
2 * Copyright 2002-2012, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
6 * Distributed under the terms of the NewOS License.
7 */
9 /* Mutex and recursive_lock code */
11 #include "fssh_lock.h"
13 #include "fssh_kernel_export.h"
16 #define FSSH_RW_MAX_READERS 100000
19 extern "C" int32_t
20 fssh_recursive_lock_get_recursion(fssh_recursive_lock *lock)
22 if (lock->holder == fssh_find_thread(NULL))
23 return lock->recursion;
25 return -1;
29 extern "C" void
30 fssh_recursive_lock_init(fssh_recursive_lock *lock, const char *name)
32 if (lock == NULL)
33 return;
35 if (name == NULL)
36 name = "recursive lock";
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");
46 extern "C" void
47 fssh_recursive_lock_destroy(fssh_recursive_lock *lock)
49 if (lock == NULL)
50 return;
52 fssh_delete_sem(lock->sem);
53 lock->sem = -1;
57 extern "C" fssh_status_t
58 fssh_recursive_lock_lock(fssh_recursive_lock *lock)
60 fssh_thread_id thread = fssh_find_thread(NULL);
62 if (thread != lock->holder) {
63 fssh_status_t status = fssh_acquire_sem(lock->sem);
64 if (status < FSSH_B_OK)
65 return status;
67 lock->holder = thread;
69 lock->recursion++;
70 return FSSH_B_OK;
74 extern "C" fssh_status_t
75 fssh_recursive_lock_trylock(fssh_recursive_lock *lock)
77 fssh_thread_id thread = fssh_find_thread(NULL);
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;
85 lock->holder = thread;
87 lock->recursion++;
88 return FSSH_B_OK;
92 extern "C" void
93 fssh_recursive_lock_unlock(fssh_recursive_lock *lock)
95 if (fssh_find_thread(NULL) != lock->holder)
96 fssh_panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
98 if (--lock->recursion == 0) {
99 lock->holder = -1;
100 fssh_release_sem(lock->sem);
105 extern "C" void
106 fssh_recursive_lock_transfer_lock(fssh_recursive_lock *lock,
107 fssh_thread_id thread)
109 if (lock->recursion != 1)
110 fssh_panic("invalid recursion level for lock transfer!");
112 lock->holder = thread;
116 // #pragma mark -
119 extern "C" void
120 fssh_mutex_init(fssh_mutex *m, const char *name)
122 if (m == NULL)
123 return;
125 if (name == NULL)
126 name = "mutex_sem";
128 m->holder = -1;
130 m->sem = fssh_create_sem(1, name);
131 if (m->sem < FSSH_B_OK)
132 fssh_panic("could not create mutex");
136 extern "C" void
137 fssh_mutex_init_etc(fssh_mutex *m, const char *name, uint32_t flags)
139 fssh_mutex_init(m, name);
143 extern "C" void
144 fssh_mutex_destroy(fssh_mutex *mutex)
146 if (mutex == NULL)
147 return;
149 if (mutex->sem >= 0) {
150 fssh_delete_sem(mutex->sem);
151 mutex->sem = -1;
153 mutex->holder = -1;
157 extern "C" fssh_status_t
158 fssh_mutex_lock(fssh_mutex *mutex)
160 fssh_thread_id me = fssh_find_thread(NULL);
161 fssh_status_t status;
163 status = fssh_acquire_sem(mutex->sem);
164 if (status < FSSH_B_OK)
165 return status;
167 if (me == mutex->holder)
168 fssh_panic("mutex_lock failure: mutex %p (sem = 0x%x) acquired twice by thread 0x%x\n", mutex, (int)mutex->sem, (int)me);
170 mutex->holder = me;
171 return FSSH_B_OK;
175 extern "C" void
176 fssh_mutex_unlock(fssh_mutex *mutex)
178 fssh_thread_id me = fssh_find_thread(NULL);
180 if (me != mutex->holder) {
181 fssh_panic("mutex_unlock failure: thread 0x%x is trying to release mutex %p (current holder 0x%x)\n",
182 (int)me, mutex, (int)mutex->holder);
185 mutex->holder = -1;
186 fssh_release_sem(mutex->sem);
190 extern "C" void
191 fssh_mutex_transfer_lock(fssh_mutex *mutex, fssh_thread_id thread)
193 mutex->holder = thread;
197 // #pragma mark -
200 extern "C" void
201 fssh_rw_lock_init(fssh_rw_lock *lock, const char *name)
203 if (lock == NULL)
204 return;
206 if (name == NULL)
207 name = "r/w lock";
209 lock->count = 0;
210 lock->holder = -1;
212 lock->sem = fssh_create_sem(FSSH_RW_MAX_READERS, name);
213 if (lock->sem < FSSH_B_OK)
214 fssh_panic("could not create r/w lock");
218 extern "C" void
219 fssh_rw_lock_init_etc(fssh_rw_lock *lock, const char *name, uint32_t flags)
221 fssh_rw_lock_init(lock, name);
225 extern "C" void
226 fssh_rw_lock_destroy(fssh_rw_lock *lock)
228 if (lock == NULL)
229 return;
231 fssh_delete_sem(lock->sem);
235 extern "C" fssh_status_t
236 fssh_rw_lock_read_lock(fssh_rw_lock *lock)
238 if (lock->holder == fssh_find_thread(NULL)) {
239 lock->count++;
240 return FSSH_B_OK;
243 return fssh_acquire_sem(lock->sem);
247 extern "C" fssh_status_t
248 fssh_rw_lock_read_unlock(fssh_rw_lock *lock)
250 if (lock->holder == fssh_find_thread(NULL) && --lock->count > 0)
251 return FSSH_B_OK;
253 return fssh_release_sem(lock->sem);
257 extern "C" fssh_status_t
258 fssh_rw_lock_write_lock(fssh_rw_lock *lock)
260 if (lock->holder == fssh_find_thread(NULL)) {
261 lock->count++;
262 return FSSH_B_OK;
265 fssh_status_t status = fssh_acquire_sem_etc(lock->sem, FSSH_RW_MAX_READERS,
266 0, 0);
267 if (status == FSSH_B_OK) {
268 lock->holder = fssh_find_thread(NULL);
269 lock->count = 1;
271 return status;
275 extern "C" fssh_status_t
276 fssh_rw_lock_write_unlock(fssh_rw_lock *lock)
278 if (--lock->count > 0)
279 return FSSH_B_OK;
281 lock->holder = -1;
283 return fssh_release_sem_etc(lock->sem, FSSH_RW_MAX_READERS, 0);