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
12typedef 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
68should_inline bool spinlock_is_locked(const spinlock_t *lock)
69{
70 return lock->flag;
71}
72
73typedef 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
84should_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
98should_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
111should_inline bool recursive_spinlock_is_locked(recursive_spinlock_t *lock)
112{
113 return lock->lock.flag;
114}
115