ReactOS 0.4.17-dev-683-g0dafdc5
mutex.c
Go to the documentation of this file.
6#include <uacpi/internal/io.h>
7#include <uacpi/kernel_api.h>
9
10#ifndef UACPI_BAREBONES_MODE
11
12#ifndef UACPI_REDUCED_HARDWARE
13
14#define GLOBAL_LOCK_PENDING (1 << 0)
15
16#define GLOBAL_LOCK_OWNED_BIT 1
17#define GLOBAL_LOCK_OWNED (1 << GLOBAL_LOCK_OWNED_BIT)
18
19#define GLOBAL_LOCK_MASK 3u
20
22{
23 uacpi_u32 value, new_value;
24 uacpi_bool was_owned;
25
27 do {
29
30 // Clear both owned & pending bits.
31 new_value = value & ~GLOBAL_LOCK_MASK;
32
33 // Set owned unconditionally
34 new_value |= GLOBAL_LOCK_OWNED;
35
36 // Set pending iff the lock was owned at the time of reading
37 if (was_owned)
38 new_value |= GLOBAL_LOCK_PENDING;
39 } while (!uacpi_atomic_cmpxchg32(lock, &value, new_value));
40
41 return !was_owned;
42}
43
45{
46 uacpi_u32 value, new_value;
47
49 do {
50 new_value = value & ~GLOBAL_LOCK_MASK;
51 } while (!uacpi_atomic_cmpxchg32(lock, &value, new_value));
52
54}
55
57{
59 uacpi_u16 spins = 0;
61
62 if (!g_uacpi_rt_ctx.has_global_lock)
63 return UACPI_STATUS_OK;
64
65 flags = uacpi_kernel_lock_spinlock(g_uacpi_rt_ctx.global_lock_spinlock);
66 for (;;) {
67 spins++;
69 "trying to acquire the global lock from firmware... (attempt %u)",
70 spins
71 );
72
74 &g_uacpi_rt_ctx.facs->global_lock
75 );
76 if (success)
77 break;
78
79 if (uacpi_unlikely(spins == 0xFFFF))
80 break;
81
82 g_uacpi_rt_ctx.global_lock_pending = UACPI_TRUE;
84 "global lock is owned by firmware, waiting for a release "
85 "notification..."
86 );
88
89 uacpi_kernel_wait_for_event(g_uacpi_rt_ctx.global_lock_event, 0xFFFF);
90 flags = uacpi_kernel_lock_spinlock(g_uacpi_rt_ctx.global_lock_spinlock);
91 }
92
93 g_uacpi_rt_ctx.global_lock_pending = UACPI_FALSE;
95
96 if (uacpi_unlikely(!success)) {
97 uacpi_error("unable to acquire global lock after %u attempts", spins);
99 }
100
101 uacpi_trace("global lock successfully acquired after %u attempt%s",
102 spins, spins > 1 ? "s" : "");
103 return UACPI_STATUS_OK;
104}
105
107{
108 if (!g_uacpi_rt_ctx.has_global_lock)
109 return;
110
111 uacpi_trace("releasing the global lock to firmware...");
112 if (do_release_global_lock_to_firmware(&g_uacpi_rt_ctx.facs->global_lock)) {
113 uacpi_trace("notifying firmware of the global lock release since the "
114 "pending bit was set");
116 }
117}
118#endif
119
122)
125)
126
129)
130{
132
135
138 return ret;
139
140 if (uacpi_unlikely(ret != UACPI_STATUS_TIMEOUT || timeout == 0xFFFF)) {
142 "unexpected status %08X (%s) while acquiring %p (timeout=%04X)",
144 );
145 }
146
147 return ret;
148}
149
151{
153
155
158
160 g_uacpi_rt_ctx.global_lock_mutex->handle, timeout
161 );
162 if (ret != UACPI_STATUS_OK)
163 return ret;
164
167 uacpi_release_native_mutex(g_uacpi_rt_ctx.global_lock_mutex->handle);
168 return ret;
169 }
170
171 if (uacpi_unlikely(g_uacpi_rt_ctx.global_lock_seq_num == 0xFFFFFFFF))
172 g_uacpi_rt_ctx.global_lock_seq_num = 0;
173
174 *out_seq = g_uacpi_rt_ctx.global_lock_seq_num++;
175 g_uacpi_rt_ctx.global_lock_acquired = UACPI_TRUE;
176 return UACPI_STATUS_OK;
177}
178
180{
182
183 if (uacpi_unlikely(!g_uacpi_rt_ctx.global_lock_acquired ||
184 seq != g_uacpi_rt_ctx.global_lock_seq_num))
186
187 g_uacpi_rt_ctx.global_lock_acquired = UACPI_FALSE;
189 uacpi_release_native_mutex(g_uacpi_rt_ctx.global_lock_mutex->handle);
190
191 return UACPI_STATUS_OK;
192}
193
195{
197
199 return id == uacpi_kernel_get_thread_id();
200}
201
203{
204 uacpi_thread_id this_id;
206
207 this_id = uacpi_kernel_get_thread_id();
208 if (UACPI_ATOMIC_LOAD_THREAD_ID(&mutex->owner) == this_id) {
209 if (uacpi_unlikely(mutex->depth == 0xFFFF)) {
211 "failing an attempt to acquire mutex @%p, too many recursive "
212 "acquires", mutex
213 );
214 return UACPI_STATUS_DENIED;
215 }
216
217 mutex->depth++;
218 return ret;
219 }
220
223 if (ret != UACPI_STATUS_OK)
224 goto out;
225
226 if (mutex->handle == g_uacpi_rt_ctx.global_lock_mutex->handle) {
230 goto out;
231 }
232 }
233
234 UACPI_ATOMIC_STORE_THREAD_ID(&mutex->owner, this_id);
235 mutex->depth = 1;
236
237out:
239 return ret;
240}
241
243{
244 if (mutex->depth-- > 1)
245 return UACPI_STATUS_OK;
246
247 if (mutex->handle == g_uacpi_rt_ctx.global_lock_mutex->handle)
249
252
253 return UACPI_STATUS_OK;
254}
255
257{
259 if (uacpi_unlikely(lock->mutex == UACPI_NULL))
261
262 lock->owner = UACPI_THREAD_ID_NONE;
263 lock->depth = 0;
264
265 return UACPI_STATUS_OK;
266}
267
269{
270 if (uacpi_unlikely(lock->depth)) {
272 "de-initializing active recursive lock %p with depth=%zu",
273 lock, lock->depth
274 );
275 lock->depth = 0;
276 }
277
278 lock->owner = UACPI_THREAD_ID_NONE;
279
280 if (lock->mutex != UACPI_NULL) {
282 lock->mutex = UACPI_NULL;
283 }
284
285 return UACPI_STATUS_OK;
286}
287
289{
290 uacpi_thread_id this_id;
292
293 this_id = uacpi_kernel_get_thread_id();
294 if (UACPI_ATOMIC_LOAD_THREAD_ID(&lock->owner) == this_id) {
295 lock->depth++;
296 return ret;
297 }
298
301 return ret;
302
303 UACPI_ATOMIC_STORE_THREAD_ID(&lock->owner, this_id);
304 lock->depth = 1;
305 return ret;
306}
307
309{
310 if (lock->depth-- > 1)
311 return UACPI_STATUS_OK;
312
314 return uacpi_release_native_mutex(lock->mutex);
315}
316
318{
319 lock->read_mutex = uacpi_kernel_create_mutex();
320 if (uacpi_unlikely(lock->read_mutex == UACPI_NULL))
322
323 lock->write_mutex = uacpi_kernel_create_mutex();
324 if (uacpi_unlikely(lock->write_mutex == UACPI_NULL)) {
325 uacpi_kernel_free_mutex(lock->read_mutex);
326 lock->read_mutex = UACPI_NULL;
328 }
329
330 lock->num_readers = 0;
331 return UACPI_STATUS_OK;
332}
333
335{
336 if (uacpi_unlikely(lock->num_readers)) {
337 uacpi_warn("de-initializing rw_lock %p with %zu active readers",
338 lock, lock->num_readers);
339 lock->num_readers = 0;
340 }
341
342 if (lock->read_mutex != UACPI_NULL) {
343 uacpi_kernel_free_mutex(lock->read_mutex);
344 lock->read_mutex = UACPI_NULL;
345 }
346 if (lock->write_mutex != UACPI_NULL) {
347 uacpi_kernel_free_mutex(lock->write_mutex);
348 lock->write_mutex = UACPI_NULL;
349 }
350
351 return UACPI_STATUS_OK;
352}
353
355{
357
358 ret = uacpi_acquire_native_mutex(lock->read_mutex);
360 return ret;
361
362 if (lock->num_readers++ == 0) {
363 ret = uacpi_acquire_native_mutex(lock->write_mutex);
365 lock->num_readers = 0;
366 }
367
368 uacpi_kernel_release_mutex(lock->read_mutex);
369 return ret;
370}
371
373{
375
376 ret = uacpi_acquire_native_mutex(lock->read_mutex);
378 return ret;
379
380 if (lock->num_readers-- == 1)
381 uacpi_release_native_mutex(lock->write_mutex);
382
383 uacpi_kernel_release_mutex(lock->read_mutex);
384 return ret;
385}
386
388{
389 return uacpi_acquire_native_mutex(lock->write_mutex);
390}
391
393{
394 return uacpi_release_native_mutex(lock->write_mutex);
395}
396
397#endif // !UACPI_BAREBONES_MODE
#define UACPI_ATOMIC_STORE_THREAD_ID(ptr, value)
Definition: arch_helpers.h:28
unsigned long uacpi_cpu_flags
Definition: arch_helpers.h:13
#define UACPI_THREAD_ID_NONE
Definition: arch_helpers.h:36
#define UACPI_ATOMIC_LOAD_THREAD_ID(ptr)
Definition: arch_helpers.h:24
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:315
#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_mmio_read32
Definition: io.h:79
#define uacpi_trace(...)
Definition: log.h:33
#define uacpi_error(...)
Definition: log.h:36
#define uacpi_warn(...)
Definition: log.h:35
uacpi_status uacpi_namespace_write_unlock(void)
Definition: namespace.c:51
uacpi_status uacpi_namespace_write_lock(void)
Definition: namespace.c:46
#define uacpi_unlikely(expr)
Definition: compiler.h:88
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:60
@ UACPI_INIT_LEVEL_SUBSYSTEM_INITIALIZED
Definition: types.h:72
uacpi_status uacpi_release_aml_mutex(uacpi_mutex *mutex)
Definition: mutex.c:242
uacpi_status uacpi_rw_lock_deinit(struct uacpi_rw_lock *lock)
Definition: mutex.c:334
uacpi_status uacpi_release_global_lock(uacpi_u32 seq)
Definition: mutex.c:179
uacpi_status uacpi_recursive_lock_deinit(struct uacpi_recursive_lock *lock)
Definition: mutex.c:268
return ret
Definition: mutex.c:147
uacpi_bool uacpi_this_thread_owns_aml_mutex(uacpi_mutex *mutex)
Definition: mutex.c:194
uacpi_status uacpi_rw_lock_init(struct uacpi_rw_lock *lock)
Definition: mutex.c:317
uacpi_status uacpi_recursive_lock_init(struct uacpi_recursive_lock *lock)
Definition: mutex.c:256
#define GLOBAL_LOCK_PENDING
Definition: mutex.c:14
static uacpi_bool try_acquire_global_lock_from_firmware(uacpi_u32 *lock)
Definition: mutex.c:21
#define GLOBAL_LOCK_OWNED_BIT
Definition: mutex.c:16
uacpi_status uacpi_rw_unlock_read(struct uacpi_rw_lock *lock)
Definition: mutex.c:372
uacpi_status uacpi_rw_unlock_write(struct uacpi_rw_lock *lock)
Definition: mutex.c:392
uacpi_status uacpi_acquire_global_lock(uacpi_u16 timeout, uacpi_u32 *out_seq)
Definition: mutex.c:150
uacpi_status uacpi_acquire_aml_mutex(uacpi_mutex *mutex, uacpi_u16 timeout)
Definition: mutex.c:202
uacpi_status uacpi_rw_lock_read(struct uacpi_rw_lock *lock)
Definition: mutex.c:354
static uacpi_bool do_release_global_lock_to_firmware(uacpi_u32 *lock)
Definition: mutex.c:44
static uacpi_status uacpi_acquire_global_lock_from_firmware(void)
Definition: mutex.c:56
static void uacpi_release_global_lock_to_firmware(void)
Definition: mutex.c:106
uacpi_status uacpi_recursive_lock_acquire(struct uacpi_recursive_lock *lock)
Definition: mutex.c:288
uacpi_status uacpi_rw_lock_write(struct uacpi_rw_lock *lock)
Definition: mutex.c:387
uacpi_status uacpi_recursive_lock_release(struct uacpi_recursive_lock *lock)
Definition: mutex.c:308
#define GLOBAL_LOCK_OWNED
Definition: mutex.c:17
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:248
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:271
#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)