ReactOS 0.4.16-dev-1506-g117cd33
mutex.c
Go to the documentation of this file.
6#include <uacpi/kernel_api.h>
8
9#ifndef UACPI_BAREBONES_MODE
10
11#ifndef UACPI_REDUCED_HARDWARE
12
13#define GLOBAL_LOCK_PENDING (1 << 0)
14
15#define GLOBAL_LOCK_OWNED_BIT 1
16#define GLOBAL_LOCK_OWNED (1 << GLOBAL_LOCK_OWNED_BIT)
17
18#define GLOBAL_LOCK_MASK 0b11u
19
21{
22 uacpi_u32 value, new_value;
23 uacpi_bool was_owned;
24
25 value = *(volatile uacpi_u32*)lock;
26 do {
28
29 // Clear both owned & pending bits.
30 new_value = value & ~GLOBAL_LOCK_MASK;
31
32 // Set owned unconditionally
33 new_value |= GLOBAL_LOCK_OWNED;
34
35 // Set pending iff the lock was owned at the time of reading
36 if (was_owned)
37 new_value |= GLOBAL_LOCK_PENDING;
38 } while (!uacpi_atomic_cmpxchg32(lock, &value, new_value));
39
40 return !was_owned;
41}
42
44{
45 uacpi_u32 value, new_value;
46
47 value = *(volatile uacpi_u32*)lock;
48 do {
49 new_value = value & ~GLOBAL_LOCK_MASK;
50 } while (!uacpi_atomic_cmpxchg32(lock, &value, new_value));
51
53}
54
56{
58 uacpi_u16 spins = 0;
60
61 if (!g_uacpi_rt_ctx.has_global_lock)
62 return UACPI_STATUS_OK;
63
64 flags = uacpi_kernel_lock_spinlock(g_uacpi_rt_ctx.global_lock_spinlock);
65 for (;;) {
66 spins++;
68 "trying to acquire the global lock from firmware... (attempt %u)\n",
69 spins
70 );
71
73 &g_uacpi_rt_ctx.facs->global_lock
74 );
75 if (success)
76 break;
77
78 if (uacpi_unlikely(spins == 0xFFFF))
79 break;
80
81 g_uacpi_rt_ctx.global_lock_pending = UACPI_TRUE;
83 "global lock is owned by firmware, waiting for a release "
84 "notification...\n"
85 );
87
88 uacpi_kernel_wait_for_event(g_uacpi_rt_ctx.global_lock_event, 0xFFFF);
89 flags = uacpi_kernel_lock_spinlock(g_uacpi_rt_ctx.global_lock_spinlock);
90 }
91
92 g_uacpi_rt_ctx.global_lock_pending = UACPI_FALSE;
94
95 if (uacpi_unlikely(!success)) {
96 uacpi_error("unable to acquire global lock after %u attempts\n", spins);
98 }
99
100 uacpi_trace("global lock successfully acquired after %u attempt%s\n",
101 spins, spins > 1 ? "s" : "");
102 return UACPI_STATUS_OK;
103}
104
106{
107 if (!g_uacpi_rt_ctx.has_global_lock)
108 return;
109
110 uacpi_trace("releasing the global lock to firmware...\n");
111 if (do_release_global_lock_to_firmware(&g_uacpi_rt_ctx.facs->global_lock)) {
112 uacpi_trace("notifying firmware of the global lock release since the "
113 "pending bit was set\n");
115 }
116}
117#endif
118
121)
124)
125
128)
129{
131
134
137 return ret;
138
139 if (uacpi_unlikely(ret != UACPI_STATUS_TIMEOUT || timeout == 0xFFFF)) {
141 "unexpected status %08X (%s) while acquiring %p (timeout=%04X)\n",
143 );
144 }
145
146 return ret;
147}
148
150{
152
154
157
159 g_uacpi_rt_ctx.global_lock_mutex->handle, timeout
160 );
161 if (ret != UACPI_STATUS_OK)
162 return ret;
163
166 uacpi_release_native_mutex(g_uacpi_rt_ctx.global_lock_mutex->handle);
167 return ret;
168 }
169
170 if (uacpi_unlikely(g_uacpi_rt_ctx.global_lock_seq_num == 0xFFFFFFFF))
171 g_uacpi_rt_ctx.global_lock_seq_num = 0;
172
173 *out_seq = g_uacpi_rt_ctx.global_lock_seq_num++;
174 g_uacpi_rt_ctx.global_lock_acquired = UACPI_TRUE;
175 return UACPI_STATUS_OK;
176}
177
179{
181
182 if (uacpi_unlikely(!g_uacpi_rt_ctx.global_lock_acquired ||
183 seq != g_uacpi_rt_ctx.global_lock_seq_num))
185
186 g_uacpi_rt_ctx.global_lock_acquired = UACPI_FALSE;
188 uacpi_release_native_mutex(g_uacpi_rt_ctx.global_lock_mutex->handle);
189
190 return UACPI_STATUS_OK;
191}
192
194{
196
198 return id == uacpi_kernel_get_thread_id();
199}
200
202{
203 uacpi_thread_id this_id;
205
206 this_id = uacpi_kernel_get_thread_id();
207 if (UACPI_ATOMIC_LOAD_THREAD_ID(&mutex->owner) == this_id) {
208 if (uacpi_unlikely(mutex->depth == 0xFFFF)) {
210 "failing an attempt to acquire mutex @%p, too many recursive "
211 "acquires\n", mutex
212 );
213 return UACPI_STATUS_DENIED;
214 }
215
216 mutex->depth++;
217 return ret;
218 }
219
222 if (ret != UACPI_STATUS_OK)
223 goto out;
224
225 if (mutex->handle == g_uacpi_rt_ctx.global_lock_mutex->handle) {
229 goto out;
230 }
231 }
232
233 UACPI_ATOMIC_STORE_THREAD_ID(&mutex->owner, this_id);
234 mutex->depth = 1;
235
236out:
238 return ret;
239}
240
242{
243 if (mutex->depth-- > 1)
244 return UACPI_STATUS_OK;
245
246 if (mutex->handle == g_uacpi_rt_ctx.global_lock_mutex->handle)
248
251
252 return UACPI_STATUS_OK;
253}
254
256{
258 if (uacpi_unlikely(lock->mutex == UACPI_NULL))
260
261 lock->owner = UACPI_THREAD_ID_NONE;
262 lock->depth = 0;
263
264 return UACPI_STATUS_OK;
265}
266
268{
269 if (uacpi_unlikely(lock->depth)) {
271 "de-initializing active recursive lock %p with depth=%zu\n",
272 lock, lock->depth
273 );
274 lock->depth = 0;
275 }
276
277 lock->owner = UACPI_THREAD_ID_NONE;
278
279 if (lock->mutex != UACPI_NULL) {
281 lock->mutex = UACPI_NULL;
282 }
283
284 return UACPI_STATUS_OK;
285}
286
288{
289 uacpi_thread_id this_id;
291
292 this_id = uacpi_kernel_get_thread_id();
293 if (UACPI_ATOMIC_LOAD_THREAD_ID(&lock->owner) == this_id) {
294 lock->depth++;
295 return ret;
296 }
297
300 return ret;
301
302 UACPI_ATOMIC_STORE_THREAD_ID(&lock->owner, this_id);
303 lock->depth = 1;
304 return ret;
305}
306
308{
309 if (lock->depth-- > 1)
310 return UACPI_STATUS_OK;
311
313 return uacpi_release_native_mutex(lock->mutex);
314}
315
317{
318 lock->read_mutex = uacpi_kernel_create_mutex();
319 if (uacpi_unlikely(lock->read_mutex == UACPI_NULL))
321
322 lock->write_mutex = uacpi_kernel_create_mutex();
323 if (uacpi_unlikely(lock->write_mutex == UACPI_NULL)) {
324 uacpi_kernel_free_mutex(lock->read_mutex);
325 lock->read_mutex = UACPI_NULL;
327 }
328
329 lock->num_readers = 0;
330 return UACPI_STATUS_OK;
331}
332
334{
335 if (uacpi_unlikely(lock->num_readers)) {
336 uacpi_warn("de-initializing rw_lock %p with %zu active readers\n",
337 lock, lock->num_readers);
338 lock->num_readers = 0;
339 }
340
341 if (lock->read_mutex != UACPI_NULL) {
342 uacpi_kernel_free_mutex(lock->read_mutex);
343 lock->read_mutex = UACPI_NULL;
344 }
345 if (lock->write_mutex != UACPI_NULL) {
346 uacpi_kernel_free_mutex(lock->write_mutex);
347 lock->write_mutex = UACPI_NULL;
348 }
349
350 return UACPI_STATUS_OK;
351}
352
354{
356
357 ret = uacpi_acquire_native_mutex(lock->read_mutex);
359 return ret;
360
361 if (lock->num_readers++ == 0) {
362 ret = uacpi_acquire_native_mutex(lock->write_mutex);
364 lock->num_readers = 0;
365 }
366
367 uacpi_kernel_release_mutex(lock->read_mutex);
368 return ret;
369}
370
372{
374
375 ret = uacpi_acquire_native_mutex(lock->read_mutex);
377 return ret;
378
379 if (lock->num_readers-- == 1)
380 uacpi_release_native_mutex(lock->write_mutex);
381
382 uacpi_kernel_release_mutex(lock->read_mutex);
383 return ret;
384}
385
387{
388 return uacpi_acquire_native_mutex(lock->write_mutex);
389}
390
392{
393 return uacpi_release_native_mutex(lock->write_mutex);
394}
395
396#endif // !UACPI_BAREBONES_MODE
#define UACPI_ATOMIC_STORE_THREAD_ID(ptr, value)
Definition: arch_helpers.h:27
unsigned long uacpi_cpu_flags
Definition: arch_helpers.h:13
#define UACPI_THREAD_ID_NONE
Definition: arch_helpers.h:35
#define UACPI_ATOMIC_LOAD_THREAD_ID(ptr)
Definition: arch_helpers.h:23
uacpi_status uacpi_acquire_native_mutex_with_timeout(uacpi_handle mtx, uacpi_u16 timeout)
static uacpi_status uacpi_release_native_mutex(uacpi_handle mtx)
Definition: mutex.h:25
static uacpi_status uacpi_acquire_native_mutex(uacpi_handle mtx)
Definition: mutex.h:13
#define uacpi_atomic_cmpxchg32(ptr, expected, desired)
Definition: atomic.h:97
#define UACPI_ENSURE_INIT_LEVEL_AT_LEAST(lvl)
Definition: context.h:127
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:17
#define uacpi_trace(...)
Definition: log.h:18
#define uacpi_error(...)
Definition: log.h:21
#define uacpi_warn(...)
Definition: log.h:20
uacpi_status uacpi_namespace_write_unlock(void)
Definition: namespace.c:54
uacpi_status uacpi_namespace_write_lock(void)
Definition: namespace.c:49
#define uacpi_unlikely(expr)
Definition: compiler.h:58
uint32_t uacpi_u32
Definition: types.h:21
bool uacpi_bool
Definition: types.h:31
#define UACPI_FALSE
Definition: types.h:30
uint16_t uacpi_u16
Definition: types.h:20
#define UACPI_NULL
Definition: types.h:33
#define UACPI_TRUE
Definition: types.h:29
@ UACPI_REGISTER_FIELD_GBL_RLS
Definition: registers.h:74
uacpi_status uacpi_write_register_field(uacpi_register_field, uacpi_u64)
Definition: registers.c:518
#define uacpi_likely_success(expr)
Definition: status.h:53
#define uacpi_unlikely_error(expr)
Definition: status.h:49
uacpi_status
Definition: status.h:10
@ UACPI_STATUS_INVALID_ARGUMENT
Definition: status.h:18
@ UACPI_STATUS_OUT_OF_MEMORY
Definition: status.h:13
@ UACPI_STATUS_OK
Definition: status.h:11
@ UACPI_STATUS_TIMEOUT
Definition: status.h:29
@ UACPI_STATUS_HARDWARE_TIMEOUT
Definition: status.h:28
@ UACPI_STATUS_DENIED
Definition: status.h:31
const uacpi_char * uacpi_status_to_string(uacpi_status)
Definition: uacpi.c:50
@ UACPI_INIT_LEVEL_SUBSYSTEM_INITIALIZED
Definition: types.h:66
uacpi_status uacpi_release_aml_mutex(uacpi_mutex *mutex)
Definition: mutex.c:241
uacpi_status uacpi_rw_lock_deinit(struct uacpi_rw_lock *lock)
Definition: mutex.c:333
uacpi_status uacpi_release_global_lock(uacpi_u32 seq)
Definition: mutex.c:178
uacpi_status uacpi_recursive_lock_deinit(struct uacpi_recursive_lock *lock)
Definition: mutex.c:267
return ret
Definition: mutex.c:146
uacpi_bool uacpi_this_thread_owns_aml_mutex(uacpi_mutex *mutex)
Definition: mutex.c:193
uacpi_status uacpi_rw_lock_init(struct uacpi_rw_lock *lock)
Definition: mutex.c:316
uacpi_status uacpi_recursive_lock_init(struct uacpi_recursive_lock *lock)
Definition: mutex.c:255
#define GLOBAL_LOCK_PENDING
Definition: mutex.c:13
static uacpi_bool try_acquire_global_lock_from_firmware(uacpi_u32 *lock)
Definition: mutex.c:20
#define GLOBAL_LOCK_OWNED_BIT
Definition: mutex.c:15
uacpi_status uacpi_rw_unlock_read(struct uacpi_rw_lock *lock)
Definition: mutex.c:371
uacpi_status uacpi_rw_unlock_write(struct uacpi_rw_lock *lock)
Definition: mutex.c:391
uacpi_status uacpi_acquire_global_lock(uacpi_u16 timeout, uacpi_u32 *out_seq)
Definition: mutex.c:149
uacpi_status uacpi_acquire_aml_mutex(uacpi_mutex *mutex, uacpi_u16 timeout)
Definition: mutex.c:201
uacpi_status uacpi_rw_lock_read(struct uacpi_rw_lock *lock)
Definition: mutex.c:353
static uacpi_bool do_release_global_lock_to_firmware(uacpi_u32 *lock)
Definition: mutex.c:43
static uacpi_status uacpi_acquire_global_lock_from_firmware(void)
Definition: mutex.c:55
static void uacpi_release_global_lock_to_firmware(void)
Definition: mutex.c:105
uacpi_status uacpi_recursive_lock_acquire(struct uacpi_recursive_lock *lock)
Definition: mutex.c:287
uacpi_status uacpi_rw_lock_write(struct uacpi_rw_lock *lock)
Definition: mutex.c:386
uacpi_status uacpi_recursive_lock_release(struct uacpi_recursive_lock *lock)
Definition: mutex.c:307
#define GLOBAL_LOCK_OWNED
Definition: mutex.c:16
GLbitfield flags
Definition: glext.h:7161
GLuint id
Definition: glext.h:5910
uacpi_bool uacpi_kernel_wait_for_event(uacpi_handle, uacpi_u16)
Definition: uacpiosl.c:66
uacpi_handle uacpi_kernel_create_mutex(void)
Definition: uacpiosl.c:139
void uacpi_kernel_free_mutex(uacpi_handle)
Definition: uacpiosl.c:146
uacpi_thread_id uacpi_kernel_get_thread_id(void)
Definition: uacpiosl.c:184
void uacpi_kernel_release_mutex(uacpi_handle)
Definition: uacpiosl.c:159
uacpi_status uacpi_kernel_acquire_mutex(uacpi_handle, uacpi_u16)
Definition: uacpiosl.c:152
uacpi_cpu_flags uacpi_kernel_lock_spinlock(uacpi_handle)
Definition: uacpiosl.c:98
void uacpi_kernel_unlock_spinlock(uacpi_handle, uacpi_cpu_flags)
Definition: uacpiosl.c:105
Definition: module.h:456
Definition: dhcpd.h:245
rwlock_t lock
Definition: tcpcore.h:0
#define UACPI_STUB_IF_REDUCED_HARDWARE(fn)
Definition: uacpi.h:26
uacpi_u32 * out_seq
Definition: uacpi.h:251
#define UACPI_ALWAYS_OK_FOR_REDUCED_HARDWARE(fn)
Definition: uacpi.h:28
Definition: pdh_main.c:96
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define success(from, fromstr, to, tostr)