libctru  v1.6.0
synchronization.h
Go to the documentation of this file.
1 /**
2  * @file synchronization.h
3  * @brief Provides synchronization locks.
4  */
5 #pragma once
6 #include <sys/lock.h>
7 #include <3ds/svc.h>
8 
9 /// A light lock.
10 typedef _LOCK_T LightLock;
11 
12 /// A recursive lock.
13 typedef _LOCK_RECURSIVE_T RecursiveLock;
14 
15 /// A light event.
16 typedef struct
17 {
18  s32 state; ///< State of the event: -2=cleared sticky, -1=cleared oneshot, 0=signaled oneshot, 1=signaled sticky
19  LightLock lock; ///< Lock used for sticky timer operation
20 } LightEvent;
21 
22 /// A light semaphore.
23 typedef struct
24 {
25  s32 current_count; ///< The current release count of the semaphore
26  s16 num_threads_acq; ///< Number of threads concurrently acquiring the semaphore
27  s16 max_count; ///< The maximum release count of the semaphore
29 
30 /// Performs a Data Synchronization Barrier operation.
31 static inline void __dsb(void)
32 {
33  __asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (0) : "memory");
34 }
35 
36 /// Performs a clrex operation.
37 static inline void __clrex(void)
38 {
39  __asm__ __volatile__("clrex" ::: "memory");
40 }
41 
42 /**
43  * @brief Performs a ldrex operation.
44  * @param addr Address to perform the operation on.
45  * @return The resulting value.
46  */
47 static inline s32 __ldrex(s32* addr)
48 {
49  s32 val;
50  __asm__ __volatile__("ldrex %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr));
51  return val;
52 }
53 
54 /**
55  * @brief Performs a strex operation.
56  * @param addr Address to perform the operation on.
57  * @param val Value to store.
58  * @return Whether the operation was successful.
59  */
60 static inline bool __strex(s32* addr, s32 val)
61 {
62  bool res;
63  __asm__ __volatile__("strex %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
64  return res;
65 }
66 
67 /**
68  * @brief Performs a ldrexh operation.
69  * @param addr Address to perform the operation on.
70  * @return The resulting value.
71  */
72 static inline u16 __ldrexh(u16* addr)
73 {
74  u16 val;
75  __asm__ __volatile__("ldrexh %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr));
76  return val;
77 }
78 
79 /**
80  * @brief Performs a strexh operation.
81  * @param addr Address to perform the operation on.
82  * @param val Value to store.
83  * @return Whether the operation was successful.
84  */
85 static inline bool __strexh(u16* addr, u16 val)
86 {
87  bool res;
88  __asm__ __volatile__("strexh %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
89  return res;
90 }
91 
92 /**
93  * @brief Performs a ldrexb operation.
94  * @param addr Address to perform the operation on.
95  * @return The resulting value.
96  */
97 static inline u8 __ldrexb(u8* addr)
98 {
99  u8 val;
100  __asm__ __volatile__("ldrexb %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr));
101  return val;
102 }
103 
104 /**
105  * @brief Performs a strexb operation.
106  * @param addr Address to perform the operation on.
107  * @param val Value to store.
108  * @return Whether the operation was successful.
109  */
110 static inline bool __strexb(u8* addr, u8 val)
111 {
112  bool res;
113  __asm__ __volatile__("strexb %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
114  return res;
115 }
116 
117 /// Performs an atomic pre-increment operation.
118 #define AtomicIncrement(ptr) __atomic_add_fetch((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
119 /// Performs an atomic pre-decrement operation.
120 #define AtomicDecrement(ptr) __atomic_sub_fetch((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
121 /// Performs an atomic post-increment operation.
122 #define AtomicPostIncrement(ptr) __atomic_fetch_add((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
123 /// Performs an atomic post-decrement operation.
124 #define AtomicPostDecrement(ptr) __atomic_fetch_sub((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
125 /// Performs an atomic swap operation.
126 #define AtomicSwap(ptr, value) __atomic_exchange_n((u32*)(ptr), (value), __ATOMIC_SEQ_CST)
127 
128 /**
129  * @brief Retrieves the synchronization subsystem's address arbiter handle.
130  * @return The synchronization subsystem's address arbiter handle.
131  */
133 
134 /**
135  * @brief Initializes a light lock.
136  * @param lock Pointer to the lock.
137  */
138 void LightLock_Init(LightLock* lock);
139 
140 /**
141  * @brief Locks a light lock.
142  * @param lock Pointer to the lock.
143  */
144 void LightLock_Lock(LightLock* lock);
145 
146 /**
147  * @brief Attempts to lock a light lock.
148  * @param lock Pointer to the lock.
149  * @return Zero on success, non-zero on failure.
150  */
151 int LightLock_TryLock(LightLock* lock);
152 
153 /**
154  * @brief Unlocks a light lock.
155  * @param lock Pointer to the lock.
156  */
157 void LightLock_Unlock(LightLock* lock);
158 
159 /**
160  * @brief Initializes a recursive lock.
161  * @param lock Pointer to the lock.
162  */
164 
165 /**
166  * @brief Locks a recursive lock.
167  * @param lock Pointer to the lock.
168  */
170 
171 /**
172  * @brief Attempts to lock a recursive lock.
173  * @param lock Pointer to the lock.
174  * @return Zero on success, non-zero on failure.
175  */
177 
178 /**
179  * @brief Unlocks a recursive lock.
180  * @param lock Pointer to the lock.
181  */
183 
184 /**
185  * @brief Initializes a light event.
186  * @param event Pointer to the event.
187  * @param reset_type Type of reset the event uses (RESET_ONESHOT/RESET_STICKY).
188  */
189 void LightEvent_Init(LightEvent* event, ResetType reset_type);
190 
191 /**
192  * @brief Clears a light event.
193  * @param event Pointer to the event.
194  */
195 void LightEvent_Clear(LightEvent* event);
196 
197 /**
198  * @brief Wakes up threads waiting on a sticky light event without signaling it. If the event had been signaled before, it is cleared instead.
199  * @param event Pointer to the event.
200  */
201 void LightEvent_Pulse(LightEvent* event);
202 
203 /**
204  * @brief Signals a light event, waking up threads waiting on it.
205  * @param event Pointer to the event.
206  */
207 void LightEvent_Signal(LightEvent* event);
208 
209 /**
210  * @brief Attempts to wait on a light event.
211  * @param event Pointer to the event.
212  * @return Non-zero if the event was signaled, zero otherwise.
213  */
214 int LightEvent_TryWait(LightEvent* event);
215 
216 /**
217  * @brief Waits on a light event.
218  * @param event Pointer to the event.
219  */
220 void LightEvent_Wait(LightEvent* event);
221 
222 /**
223  * @brief Initializes a light semaphore.
224  * @param event Pointer to the semaphore.
225  * @param max_count Initial count of the semaphore.
226  * @param max_count Maximum count of the semaphore.
227  */
228 void LightSemaphore_Init(LightSemaphore* semaphore, s16 initial_count, s16 max_count);
229 
230 /**
231  * @brief Acquires a light semaphore.
232  * @param semaphore Pointer to the semaphore.
233  * @param count Acquire count
234  */
235 void LightSemaphore_Acquire(LightSemaphore* semaphore, s32 count);
236 
237 /**
238  * @brief Releases a light semaphore.
239  * @param semaphore Pointer to the semaphore.
240  * @param count Release count
241  */
242 void LightSemaphore_Release(LightSemaphore* semaphore, s32 count);
void LightLock_Init(LightLock *lock)
Initializes a light lock.
A light semaphore.
Definition: synchronization.h:23
void LightEvent_Init(LightEvent *event, ResetType reset_type)
Initializes a light event.
s32 state
State of the event: -2=cleared sticky, -1=cleared oneshot, 0=signaled oneshot, 1=signaled sticky.
Definition: synchronization.h:18
ResetType
Reset types (for use with events and timers)
Definition: svc.h:94
uint16_t u16
16-bit unsigned integer
Definition: types.h:22
void LightEvent_Wait(LightEvent *event)
Waits on a light event.
void LightSemaphore_Release(LightSemaphore *semaphore, s32 count)
Releases a light semaphore.
void LightEvent_Pulse(LightEvent *event)
Wakes up threads waiting on a sticky light event without signaling it.
s32 current_count
The current release count of the semaphore.
Definition: synchronization.h:25
u32 Handle
Resource handle.
Definition: types.h:41
_LOCK_RECURSIVE_T RecursiveLock
A recursive lock.
Definition: synchronization.h:13
s16 max_count
The maximum release count of the semaphore.
Definition: synchronization.h:27
void RecursiveLock_Init(RecursiveLock *lock)
Initializes a recursive lock.
uint8_t u8
would be nice if newlib had this already
Definition: types.h:21
static void __dsb(void)
Performs a Data Synchronization Barrier operation.
Definition: synchronization.h:31
void LightEvent_Clear(LightEvent *event)
Clears a light event.
void RecursiveLock_Unlock(RecursiveLock *lock)
Unlocks a recursive lock.
A light event.
Definition: synchronization.h:16
LightLock lock
Lock used for sticky timer operation.
Definition: synchronization.h:19
int32_t s32
32-bit signed integer
Definition: types.h:28
void LightSemaphore_Acquire(LightSemaphore *semaphore, s32 count)
Acquires a light semaphore.
static bool __strex(s32 *addr, s32 val)
Performs a strex operation.
Definition: synchronization.h:60
static u8 __ldrexb(u8 *addr)
Performs a ldrexb operation.
Definition: synchronization.h:97
s16 num_threads_acq
Number of threads concurrently acquiring the semaphore.
Definition: synchronization.h:26
_LOCK_T LightLock
A light lock.
Definition: synchronization.h:10
void LightLock_Lock(LightLock *lock)
Locks a light lock.
static bool __strexb(u8 *addr, u8 val)
Performs a strexb operation.
Definition: synchronization.h:110
static u16 __ldrexh(u16 *addr)
Performs a ldrexh operation.
Definition: synchronization.h:72
void LightSemaphore_Init(LightSemaphore *semaphore, s16 initial_count, s16 max_count)
Initializes a light semaphore.
static s32 __ldrex(s32 *addr)
Performs a ldrex operation.
Definition: synchronization.h:47
int LightEvent_TryWait(LightEvent *event)
Attempts to wait on a light event.
static void __clrex(void)
Performs a clrex operation.
Definition: synchronization.h:37
int LightLock_TryLock(LightLock *lock)
Attempts to lock a light lock.
void RecursiveLock_Lock(RecursiveLock *lock)
Locks a recursive lock.
Syscall wrappers.
void LightEvent_Signal(LightEvent *event)
Signals a light event, waking up threads waiting on it.
int RecursiveLock_TryLock(RecursiveLock *lock)
Attempts to lock a recursive lock.
Handle __sync_get_arbiter(void)
Retrieves the synchronization subsystem's address arbiter handle.
static bool __strexh(u16 *addr, u16 val)
Performs a strexh operation.
Definition: synchronization.h:85
void LightLock_Unlock(LightLock *lock)
Unlocks a light lock.
int16_t s16
16-bit signed integer
Definition: types.h:27