1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include <mos/lib/sync/mutex.h>
4
5#ifdef __MOS_KERNEL__
6#include <mos/locks/futex.h>
7#else
8#include <mos/syscall/usermode.h>
9#define futex_wait(futex, val) syscall_futex_wait(futex, val)
10#define futex_wake(futex, val) syscall_futex_wake(futex, val)
11#endif
12
13// a mutex_t holds a value of 0 or 1, meaning:
14// mutex acquired = 1
15// mutex released = 0
16
17void mutex_acquire(mutex_t *m)
18{
19 while (1)
20 {
21 mutex_t zero = 0;
22 // try setting the mutex to 1 (only if it's 0)
23 if (__atomic_compare_exchange_n(m, &zero, 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
24 return;
25
26 // tell the kernel that "the mutex should be 1", and wait until it is 0
27 futex_wait(futex: m, expected: 1);
28 }
29}
30
31void mutex_release(mutex_t *m)
32{
33 mutex_t one = 1;
34 // try setting the mutex to 0 (only if it's 1)
35 if (__atomic_compare_exchange_n(m, &one, 0, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
36 {
37 bool result = futex_wake(lock: m, num_to_wake: 1); // TODO: Handle error
38 MOS_UNUSED(result);
39 }
40}
41