1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #pragma once |
4 | |
5 | #include "mos/platform/platform_defs.h" |
6 | |
7 | #include <mos/mos_global.h> |
8 | #include <mos/types.h> |
9 | |
10 | #define barrier() MOS_PLATFORM_MEMORY_BARRIER() |
11 | |
12 | typedef struct |
13 | { |
14 | bool flag; |
15 | #if MOS_DEBUG_FEATURE(spinlock) |
16 | const char *file; |
17 | int line; |
18 | #endif |
19 | } spinlock_t; |
20 | |
21 | #define spinlock_init(lock) \ |
22 | do \ |
23 | { \ |
24 | (lock)->flag = 0; \ |
25 | } while (0) |
26 | |
27 | // clang-format off |
28 | #define SPINLOCK_INIT { 0 } |
29 | // clang-format on |
30 | |
31 | #define _spinlock_real_acquire(lock) \ |
32 | do \ |
33 | { \ |
34 | barrier(); \ |
35 | while (__atomic_test_and_set(&(lock)->flag, __ATOMIC_ACQUIRE)) \ |
36 | ; \ |
37 | } while (0) |
38 | |
39 | #define _spinlock_real_release(lock) \ |
40 | do \ |
41 | { \ |
42 | __atomic_clear(&(lock)->flag, __ATOMIC_RELEASE); \ |
43 | } while (0) |
44 | |
45 | #if MOS_DEBUG_FEATURE(spinlock) |
46 | #define spinlock_acquire(lock) \ |
47 | do \ |
48 | { \ |
49 | _spinlock_real_acquire(lock); \ |
50 | (lock)->file = __FILE__; \ |
51 | (lock)->line = __LINE__; \ |
52 | } while (0) |
53 | #define spinlock_release(lock) \ |
54 | do \ |
55 | { \ |
56 | (lock)->file = NULL; \ |
57 | (lock)->line = 0; \ |
58 | _spinlock_real_release(lock); \ |
59 | } while (0) |
60 | #else |
61 | #define spinlock_acquire(lock) _spinlock_real_acquire(lock) |
62 | #define spinlock_release(lock) _spinlock_real_release(lock) |
63 | #endif |
64 | |
65 | #define spinlock_acquire_nodebug(lock) _spinlock_real_acquire(lock) |
66 | #define spinlock_release_nodebug(lock) _spinlock_real_release(lock) |
67 | |
68 | should_inline bool spinlock_is_locked(const spinlock_t *lock) |
69 | { |
70 | return lock->flag; |
71 | } |
72 | |
73 | typedef struct |
74 | { |
75 | spinlock_t lock; |
76 | void *owner; |
77 | size_t count; |
78 | } recursive_spinlock_t; |
79 | |
80 | // clang-format off |
81 | #define RECURSIVE_SPINLOCK_INIT { SPINLOCK_INIT, NULL, 0 } |
82 | // clang-format on |
83 | |
84 | should_inline void recursive_spinlock_acquire(recursive_spinlock_t *lock, void *owner) |
85 | { |
86 | if (lock->owner == owner) |
87 | { |
88 | lock->count++; |
89 | } |
90 | else |
91 | { |
92 | spinlock_acquire(&lock->lock); |
93 | lock->owner = owner; |
94 | lock->count = 1; |
95 | } |
96 | } |
97 | |
98 | should_inline void recursive_spinlock_release(recursive_spinlock_t *lock, void *owner) |
99 | { |
100 | if (lock->owner == owner) |
101 | { |
102 | lock->count--; |
103 | if (lock->count == 0) |
104 | { |
105 | lock->owner = NULL; |
106 | spinlock_release(&lock->lock); |
107 | } |
108 | } |
109 | } |
110 | |
111 | should_inline bool recursive_spinlock_is_locked(recursive_spinlock_t *lock) |
112 | { |
113 | return lock->lock.flag; |
114 | } |
115 | |