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.
9 /* Mutex and recursive_lock code */
11 #include "fssh_lock.h"
13 #include "fssh_kernel_export.h"
16 #define FSSH_RW_MAX_READERS 100000
20 fssh_recursive_lock_get_recursion(fssh_recursive_lock
*lock
)
22 if (lock
->holder
== fssh_find_thread(NULL
))
23 return lock
->recursion
;
30 fssh_recursive_lock_init(fssh_recursive_lock
*lock
, const char *name
)
36 name
= "recursive lock";
40 lock
->sem
= fssh_create_sem(1, name
);
41 if (lock
->sem
< FSSH_B_OK
)
42 fssh_panic("could not create recursive lock");
47 fssh_recursive_lock_destroy(fssh_recursive_lock
*lock
)
52 fssh_delete_sem(lock
->sem
);
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
)
67 lock
->holder
= thread
;
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
)
85 lock
->holder
= thread
;
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) {
100 fssh_release_sem(lock
->sem
);
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
;
120 fssh_mutex_init(fssh_mutex
*m
, const char *name
)
130 m
->sem
= fssh_create_sem(1, name
);
131 if (m
->sem
< FSSH_B_OK
)
132 fssh_panic("could not create mutex");
137 fssh_mutex_init_etc(fssh_mutex
*m
, const char *name
, uint32_t flags
)
139 fssh_mutex_init(m
, name
);
144 fssh_mutex_destroy(fssh_mutex
*mutex
)
149 if (mutex
->sem
>= 0) {
150 fssh_delete_sem(mutex
->sem
);
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
)
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
);
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
);
186 fssh_release_sem(mutex
->sem
);
191 fssh_mutex_transfer_lock(fssh_mutex
*mutex
, fssh_thread_id thread
)
193 mutex
->holder
= thread
;
201 fssh_rw_lock_init(fssh_rw_lock
*lock
, const char *name
)
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");
219 fssh_rw_lock_init_etc(fssh_rw_lock
*lock
, const char *name
, uint32_t flags
)
221 fssh_rw_lock_init(lock
, name
);
226 fssh_rw_lock_destroy(fssh_rw_lock
*lock
)
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
)) {
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)
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
)) {
265 fssh_status_t status
= fssh_acquire_sem_etc(lock
->sem
, FSSH_RW_MAX_READERS
,
267 if (status
== FSSH_B_OK
) {
268 lock
->holder
= fssh_find_thread(NULL
);
275 extern "C" fssh_status_t
276 fssh_rw_lock_write_unlock(fssh_rw_lock
*lock
)
278 if (--lock
->count
> 0)
283 return fssh_release_sem_etc(lock
->sem
, FSSH_RW_MAX_READERS
, 0);