ReactOS 0.4.17-dev-1218-gfae4549
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_wait_for_native_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 *out_seq = ++g_uacpi_rt_ctx.global_lock_seq_num;
172 g_uacpi_rt_ctx.global_lock_acquired = UACPI_TRUE;
173 return UACPI_STATUS_OK;
174}
175
177{
179
180 if (uacpi_unlikely(!g_uacpi_rt_ctx.global_lock_acquired ||
181 seq != g_uacpi_rt_ctx.global_lock_seq_num))
183
184 g_uacpi_rt_ctx.global_lock_acquired = UACPI_FALSE;
186 uacpi_release_native_mutex(g_uacpi_rt_ctx.global_lock_mutex->handle);
187
188 return UACPI_STATUS_OK;
189}
190
192{
194
196 return id == uacpi_kernel_get_thread_id();
197}
198
200{
201 uacpi_thread_id this_id;
203
204 this_id = uacpi_kernel_get_thread_id();
205 if (UACPI_ATOMIC_LOAD_THREAD_ID(&mutex->owner) == this_id) {
206 if (uacpi_unlikely(mutex->depth == 0xFFFF)) {
208 "failing an attempt to acquire mutex @%p, too many recursive "
209 "acquires", mutex
210 );
211 return UACPI_STATUS_DENIED;
212 }
213
214 mutex->depth++;
215 return ret;
216 }
217
220 if (ret != UACPI_STATUS_OK)
221 goto out;
222
223 if (mutex->handle == g_uacpi_rt_ctx.global_lock_mutex->handle) {
227 goto out;
228 }
229 }
230
231 UACPI_ATOMIC_STORE_THREAD_ID(&mutex->owner, this_id);
232 mutex->depth = 1;
233
234out:
236 return ret;
237}
238
240{
241 if (mutex->depth-- > 1)
242 return UACPI_STATUS_OK;
243
244 if (mutex->handle == g_uacpi_rt_ctx.global_lock_mutex->handle)
246
249
250 return UACPI_STATUS_OK;
251}
252
254{
256 if (uacpi_unlikely(lock->mutex == UACPI_NULL))
258
259 lock->owner = UACPI_THREAD_ID_NONE;
260 lock->depth = 0;
261
262 return UACPI_STATUS_OK;
263}
264
266{
267 if (uacpi_unlikely(lock->depth)) {
269 "de-initializing active recursive lock %p with depth=%zu",
270 lock, lock->depth
271 );
272 lock->depth = 0;
273 }
274
275 lock->owner = UACPI_THREAD_ID_NONE;
276
277 if (lock->mutex != UACPI_NULL) {
279 lock->mutex = UACPI_NULL;
280 }
281
282 return UACPI_STATUS_OK;
283}
284
286{
287 uacpi_thread_id this_id;
289
290 this_id = uacpi_kernel_get_thread_id();
291 if (UACPI_ATOMIC_LOAD_THREAD_ID(&lock->owner) == this_id) {
292 lock->depth++;
293 return ret;
294 }
295
298 return ret;
299
300 UACPI_ATOMIC_STORE_THREAD_ID(&lock->owner, this_id);
301 lock->depth = 1;
302 return ret;
303}
304
306{
307 if (lock->depth-- > 1)
308 return UACPI_STATUS_OK;
309
311 return uacpi_release_native_mutex(lock->mutex);
312}
313
315{
316 lock->read_mutex = uacpi_create_native_mutex();
317 if (uacpi_unlikely(lock->read_mutex == UACPI_NULL))
319
320 lock->write_mutex = uacpi_create_native_mutex();
321 if (uacpi_unlikely(lock->write_mutex == UACPI_NULL)) {
322 uacpi_free_native_mutex(lock->read_mutex);
323 lock->read_mutex = UACPI_NULL;
325 }
326
327 lock->num_readers = 0;
328 return UACPI_STATUS_OK;
329}
330
332{
333 if (uacpi_unlikely(lock->num_readers)) {
334 uacpi_warn("de-initializing rw_lock %p with %zu active readers",
335 lock, lock->num_readers);
336 lock->num_readers = 0;
337 }
338
339 if (lock->read_mutex != UACPI_NULL) {
340 uacpi_free_native_mutex(lock->read_mutex);
341 lock->read_mutex = UACPI_NULL;
342 }
343 if (lock->write_mutex != UACPI_NULL) {
344 uacpi_free_native_mutex(lock->write_mutex);
345 lock->write_mutex = UACPI_NULL;
346 }
347
348 return UACPI_STATUS_OK;
349}
350
352{
354
355 ret = uacpi_acquire_native_mutex(lock->read_mutex);
357 return ret;
358
359 if (lock->num_readers++ == 0) {
360 ret = uacpi_acquire_native_mutex(lock->write_mutex);
362 lock->num_readers = 0;
363 }
364
365 uacpi_release_native_mutex(lock->read_mutex);
366 return ret;
367}
368
370{
372
373 ret = uacpi_acquire_native_mutex(lock->read_mutex);
375 return ret;
376
377 if (lock->num_readers-- == 1)
378 uacpi_release_native_mutex(lock->write_mutex);
379
380 uacpi_release_native_mutex(lock->read_mutex);
381 return ret;
382}
383
385{
386 return uacpi_acquire_native_mutex(lock->write_mutex);
387}
388
390{
391 return uacpi_release_native_mutex(lock->write_mutex);
392}
393
394#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:44
static void uacpi_free_native_mutex(uacpi_handle mtx)
Definition: mutex.h:27
static uacpi_status uacpi_acquire_native_mutex(uacpi_handle mtx)
Definition: mutex.h:32
static uacpi_handle uacpi_create_native_mutex(void)
Definition: mutex.h:22
static uacpi_bool uacpi_wait_for_native_event(uacpi_handle evt, uacpi_u16 timeout)
Definition: mutex.h:88
#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:18
#define uacpi_mmio_read32
Definition: io.h:90
#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:54
#define uacpi_unlikely_error(expr)
Definition: status.h:50
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:61
@ UACPI_INIT_LEVEL_SUBSYSTEM_INITIALIZED
Definition: types.h:72
uacpi_status uacpi_release_aml_mutex(uacpi_mutex *mutex)
Definition: mutex.c:239
uacpi_status uacpi_rw_lock_deinit(struct uacpi_rw_lock *lock)
Definition: mutex.c:331
uacpi_status uacpi_release_global_lock(uacpi_u32 seq)
Definition: mutex.c:176
uacpi_status uacpi_recursive_lock_deinit(struct uacpi_recursive_lock *lock)
Definition: mutex.c:265
return ret
Definition: mutex.c:147
uacpi_bool uacpi_this_thread_owns_aml_mutex(uacpi_mutex *mutex)
Definition: mutex.c:191
uacpi_status uacpi_rw_lock_init(struct uacpi_rw_lock *lock)
Definition: mutex.c:314
uacpi_status uacpi_recursive_lock_init(struct uacpi_recursive_lock *lock)
Definition: mutex.c:253
#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:369
uacpi_status uacpi_rw_unlock_write(struct uacpi_rw_lock *lock)
Definition: mutex.c:389
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:199
uacpi_status uacpi_rw_lock_read(struct uacpi_rw_lock *lock)
Definition: mutex.c:351
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:285
uacpi_status uacpi_rw_lock_write(struct uacpi_rw_lock *lock)
Definition: mutex.c:384
uacpi_status uacpi_recursive_lock_release(struct uacpi_recursive_lock *lock)
Definition: mutex.c:305
#define GLOBAL_LOCK_OWNED
Definition: mutex.c:17
GLbitfield flags
Definition: glext.h:7161
GLuint id
Definition: glext.h:5910
uacpi_status uacpi_kernel_wait_for_semaphore(uacpi_handle, uacpi_u16)
uacpi_thread_id uacpi_kernel_get_thread_id(void)
Definition: uacpiosl.c:184
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:64
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define success(from, fromstr, to, tostr)