xref: /haiku/src/tools/fs_shell/lock.cpp (revision 9f3ba01bd36e8069a3550fb10c38c48841a2c0bc)
1 /*
2  * Copyright 2002-2012, 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
fssh_recursive_lock_get_recursion(fssh_recursive_lock * lock)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
fssh_recursive_lock_init_etc(fssh_recursive_lock * lock,const char * name,uint32_t flags)30 fssh_recursive_lock_init_etc(fssh_recursive_lock *lock, const char *name,
31 	uint32_t flags)
32 {
33 	// TODO: No fssh_create_sem_etc for flags?
34 
35 	if (lock == NULL)
36 		return;
37 
38 	if (name == NULL)
39 		name = "recursive lock";
40 
41 	lock->holder = -1;
42 	lock->recursion = 0;
43 	lock->sem = fssh_create_sem(1, name);
44 	if (lock->sem < FSSH_B_OK)
45 		fssh_panic("could not create recursive lock");
46 }
47 
48 
49 extern "C" void
fssh_recursive_lock_init(fssh_recursive_lock * lock,const char * name)50 fssh_recursive_lock_init(fssh_recursive_lock *lock, const char *name)
51 {
52 	fssh_recursive_lock_init_etc(lock, name, 0);
53 }
54 
55 
56 extern "C" void
fssh_recursive_lock_destroy(fssh_recursive_lock * lock)57 fssh_recursive_lock_destroy(fssh_recursive_lock *lock)
58 {
59 	if (lock == NULL)
60 		return;
61 
62 	fssh_delete_sem(lock->sem);
63 	lock->sem = -1;
64 }
65 
66 
67 extern "C" fssh_status_t
fssh_recursive_lock_lock(fssh_recursive_lock * lock)68 fssh_recursive_lock_lock(fssh_recursive_lock *lock)
69 {
70 	fssh_thread_id thread = fssh_find_thread(NULL);
71 
72 	if (thread != lock->holder) {
73 		fssh_status_t status = fssh_acquire_sem(lock->sem);
74 		if (status < FSSH_B_OK)
75 			return status;
76 
77 		lock->holder = thread;
78 	}
79 	lock->recursion++;
80 	return FSSH_B_OK;
81 }
82 
83 
84 extern "C" fssh_status_t
fssh_recursive_lock_trylock(fssh_recursive_lock * lock)85 fssh_recursive_lock_trylock(fssh_recursive_lock *lock)
86 {
87 	fssh_thread_id thread = fssh_find_thread(NULL);
88 
89 	if (thread != lock->holder) {
90 		fssh_status_t status = fssh_acquire_sem_etc(lock->sem, 1,
91 			FSSH_B_RELATIVE_TIMEOUT, 0);
92 		if (status < FSSH_B_OK)
93 			return status;
94 
95 		lock->holder = thread;
96 	}
97 	lock->recursion++;
98 	return FSSH_B_OK;
99 }
100 
101 
102 extern "C" void
fssh_recursive_lock_unlock(fssh_recursive_lock * lock)103 fssh_recursive_lock_unlock(fssh_recursive_lock *lock)
104 {
105 	if (fssh_find_thread(NULL) != lock->holder)
106 		fssh_panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
107 
108 	if (--lock->recursion == 0) {
109 		lock->holder = -1;
110 		fssh_release_sem(lock->sem);
111 	}
112 }
113 
114 
115 extern "C" void
fssh_recursive_lock_transfer_lock(fssh_recursive_lock * lock,fssh_thread_id thread)116 fssh_recursive_lock_transfer_lock(fssh_recursive_lock *lock,
117 	fssh_thread_id thread)
118 {
119 	if (lock->recursion != 1)
120 		fssh_panic("invalid recursion level for lock transfer!");
121 
122 	lock->holder = thread;
123 }
124 
125 
126 //	#pragma mark -
127 
128 
129 extern "C" void
fssh_mutex_init(fssh_mutex * m,const char * name)130 fssh_mutex_init(fssh_mutex *m, const char *name)
131 {
132 	if (m == NULL)
133 		return;
134 
135 	if (name == NULL)
136 		name = "mutex_sem";
137 
138 	m->holder = -1;
139 
140 	m->sem = fssh_create_sem(1, name);
141 	if (m->sem < FSSH_B_OK)
142 		fssh_panic("could not create mutex");
143 }
144 
145 
146 extern "C" void
fssh_mutex_init_etc(fssh_mutex * m,const char * name,uint32_t flags)147 fssh_mutex_init_etc(fssh_mutex *m, const char *name, uint32_t flags)
148 {
149 	fssh_mutex_init(m, name);
150 }
151 
152 
153 extern "C" void
fssh_mutex_destroy(fssh_mutex * mutex)154 fssh_mutex_destroy(fssh_mutex *mutex)
155 {
156 	if (mutex == NULL)
157 		return;
158 
159 	if (mutex->sem >= 0) {
160 		fssh_delete_sem(mutex->sem);
161 		mutex->sem = -1;
162 	}
163 	mutex->holder = -1;
164 }
165 
166 
167 extern "C" fssh_status_t
fssh_mutex_lock(fssh_mutex * mutex)168 fssh_mutex_lock(fssh_mutex *mutex)
169 {
170 	fssh_thread_id me = fssh_find_thread(NULL);
171 	fssh_status_t status;
172 
173 	status = fssh_acquire_sem(mutex->sem);
174 	if (status < FSSH_B_OK)
175 		return status;
176 
177 	if (me == mutex->holder)
178 		fssh_panic("mutex_lock failure: mutex %p (sem = 0x%x) acquired twice by thread 0x%x\n", mutex, (int)mutex->sem, (int)me);
179 
180 	mutex->holder = me;
181 	return FSSH_B_OK;
182 }
183 
184 
185 extern "C" void
fssh_mutex_unlock(fssh_mutex * mutex)186 fssh_mutex_unlock(fssh_mutex *mutex)
187 {
188 	fssh_thread_id me = fssh_find_thread(NULL);
189 
190 	if (me != mutex->holder) {
191 		fssh_panic("mutex_unlock failure: thread 0x%x is trying to release mutex %p (current holder 0x%x)\n",
192 			(int)me, mutex, (int)mutex->holder);
193 	}
194 
195 	mutex->holder = -1;
196 	fssh_release_sem(mutex->sem);
197 }
198 
199 
200 extern "C" void
fssh_mutex_transfer_lock(fssh_mutex * mutex,fssh_thread_id thread)201 fssh_mutex_transfer_lock(fssh_mutex *mutex, fssh_thread_id thread)
202 {
203 	mutex->holder = thread;
204 }
205 
206 
207 //	#pragma mark -
208 
209 
210 extern "C" void
fssh_rw_lock_init(fssh_rw_lock * lock,const char * name)211 fssh_rw_lock_init(fssh_rw_lock *lock, const char *name)
212 {
213 	if (lock == NULL)
214 		return;
215 
216 	if (name == NULL)
217 		name = "r/w lock";
218 
219 	lock->count = 0;
220 	lock->holder = -1;
221 
222 	lock->sem = fssh_create_sem(FSSH_RW_MAX_READERS, name);
223 	if (lock->sem < FSSH_B_OK)
224 		fssh_panic("could not create r/w lock");
225 }
226 
227 
228 extern "C" void
fssh_rw_lock_init_etc(fssh_rw_lock * lock,const char * name,uint32_t flags)229 fssh_rw_lock_init_etc(fssh_rw_lock *lock, const char *name, uint32_t flags)
230 {
231 	fssh_rw_lock_init(lock, name);
232 }
233 
234 
235 extern "C" void
fssh_rw_lock_destroy(fssh_rw_lock * lock)236 fssh_rw_lock_destroy(fssh_rw_lock *lock)
237 {
238 	if (lock == NULL)
239 		return;
240 
241 	fssh_delete_sem(lock->sem);
242 }
243 
244 
245 extern "C" fssh_status_t
fssh_rw_lock_read_lock(fssh_rw_lock * lock)246 fssh_rw_lock_read_lock(fssh_rw_lock *lock)
247 {
248 	if (lock->holder == fssh_find_thread(NULL)) {
249 		lock->count++;
250 		return FSSH_B_OK;
251 	}
252 
253 	return fssh_acquire_sem(lock->sem);
254 }
255 
256 
257 extern "C" fssh_status_t
fssh_rw_lock_read_unlock(fssh_rw_lock * lock)258 fssh_rw_lock_read_unlock(fssh_rw_lock *lock)
259 {
260 	if (lock->holder == fssh_find_thread(NULL) && --lock->count > 0)
261 		return FSSH_B_OK;
262 
263 	return fssh_release_sem(lock->sem);
264 }
265 
266 
267 extern "C" fssh_status_t
fssh_rw_lock_write_lock(fssh_rw_lock * lock)268 fssh_rw_lock_write_lock(fssh_rw_lock *lock)
269 {
270 	if (lock->holder == fssh_find_thread(NULL)) {
271 		lock->count++;
272 		return FSSH_B_OK;
273 	}
274 
275 	fssh_status_t status = fssh_acquire_sem_etc(lock->sem, FSSH_RW_MAX_READERS,
276 		0, 0);
277 	if (status == FSSH_B_OK) {
278 		lock->holder = fssh_find_thread(NULL);
279 		lock->count = 1;
280 	}
281 	return status;
282 }
283 
284 
285 extern "C" fssh_status_t
fssh_rw_lock_write_unlock(fssh_rw_lock * lock)286 fssh_rw_lock_write_unlock(fssh_rw_lock *lock)
287 {
288 	if (--lock->count > 0)
289 		return FSSH_B_OK;
290 
291 	lock->holder = -1;
292 
293 	return fssh_release_sem_etc(lock->sem, FSSH_RW_MAX_READERS, 0);
294 }
295 
296