xref: /haiku/src/tools/fs_shell/lock.cpp (revision 0d452c8f34013b611a54c746a71c05e28796eae2)
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