KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
mutex.h
Go to the documentation of this file.
1/* KallistiOS ##version##
2
3 include/kos/mutex.h
4 Copyright (C) 2001, 2003 Megan Potter
5 Copyright (C) 2012, 2015 Lawrence Sebald
6
7*/
8
9/** \file kos/mutex.h
10 \brief Mutual exclusion locks.
11 \ingroup kthreads
12
13 This file defines mutual exclusion locks (or mutexes for short). The concept
14 of a mutex is one of the most common types of locks in a multi-threaded
15 environment. Mutexes do exactly what they sound like, they keep two (or
16 more) threads mutually exclusive from one another. A mutex is used around
17 a block of code to prevent two threads from interfering with one another
18 when only one would be appropriate to be in the block at a time.
19
20 KallistiOS implements 2 types of mutexes, normal mutexes and recursive
21 mutexes. Internally the implementation is the same, the only difference lies
22 in error-checking. When assert() calls are disabled (by setting the NDEBUG
23 macro), they should have the exact same behaviour.
24
25 A normal mutex (MUTEX_TYPE_NORMAL) is roughly equivalent to a semaphore that
26 has been initialized with a count of 1. If assert() is disabled, there is no
27 protection against threads unlocking normal mutexes they didn't lock, nor is
28 there any protection against a thread locking the same mutex twice.
29
30 A recursive mutex (MUTEX_TYPE_RECURSIVE) allows you to lock the mutex
31 N times in the same thread; in which case, the mutex has to be unlocked N
32 times for the mutex to be effectively released. Still only one thread can
33 hold the lock, but it may hold it as many times as it needs to.
34
35 \author Lawrence Sebald
36 \see kos/sem.h
37*/
38
39#ifndef __KOS_MUTEX_H
40#define __KOS_MUTEX_H
41
42#include <kos/cdefs.h>
43
44__BEGIN_DECLS
45
46/* Forward declare kthread to not expose all of thread.h here */
47struct kthread;
48
49/** \brief Mutual exclusion lock type.
50
51 All members of this structure should be considered to be private. It is
52 unsafe to change anything in here yourself.
53
54 \headerfile kos/mutex.h
55*/
56typedef struct kos_mutex {
57 unsigned int type;
58 struct kthread *holder;
59 int count;
60} mutex_t;
61
62/** \name Mutex types
63 \brief Types of Mutexes supported by KOS
64
65 The values defined in here are the various types of mutexes that KallistiOS
66 supports.
67
68 @{
69*/
70#define MUTEX_TYPE_NORMAL 0 /**< \brief Normal mutex type */
71#define MUTEX_TYPE_OLDNORMAL 1 /**< \brief Alias for MUTEX_TYPE_NORMAL */
72#define MUTEX_TYPE_RECURSIVE 3 /**< \brief Recursive mutex type */
73#define MUTEX_TYPE_DESTROYED 4 /**< \brief Mutex that has been destroyed */
74
75 __depr("Error-checking mutexes are deprecated")
76static const unsigned int MUTEX_TYPE_ERRORCHECK = 2;
77
78/** \brief Default mutex type */
79#define MUTEX_TYPE_DEFAULT MUTEX_TYPE_NORMAL
80/** @} */
81
82/** \brief Initializer for a transient mutex. */
83#define MUTEX_INITIALIZER { MUTEX_TYPE_NORMAL, NULL, 0 }
84
85/** \brief Initializer for a transient error-checking mutex. */
86#define ERRORCHECK_MUTEX_INITIALIZER { MUTEX_TYPE_ERRORCHECK, NULL, 0 }
87
88/** \brief Initializer for a transient recursive mutex. */
89#define RECURSIVE_MUTEX_INITIALIZER { MUTEX_TYPE_RECURSIVE, NULL, 0 }
90
91/** \brief Initialize a new mutex.
92
93 This function initializes a new mutex for use.
94
95 \param m The mutex to initialize
96 \param mtype The type of the mutex to initialize it to
97
98 \retval 0 On success
99 \retval -1 On error, errno will be set as appropriate
100
101 \par Error Conditions:
102 \em EINVAL - an invalid type of mutex was specified
103
104 \sa mutex_types
105*/
106int mutex_init(mutex_t *m, unsigned int mtype) __nonnull_all;
107
108/** \brief Destroy a mutex.
109
110 This function destroys a mutex, releasing any memory that may have been
111 allocated internally for it. It is your responsibility to make sure that all
112 threads waiting on the mutex are taken care of before destroying the mutex.
113
114 This function can be called on statically initialized as well as dynamically
115 initialized mutexes.
116
117 \param m The mutex to destroy
118
119 \retval 0 On success
120 \retval -1 On error, errno will be set as appropriate
121
122 \par Error Conditions:
123 \em EINVAL - an invalid type of mutex was specified
124 \em EBUSY - the mutex is currently locked
125*/
126int mutex_destroy(mutex_t *m) __nonnull_all;
127
128/** \brief Lock a mutex.
129
130 This function will lock a mutex, if it is not already locked by another
131 thread. If it is locked by another thread already, this function will block
132 until the mutex has been acquired for the calling thread.
133 This function can be called from within an interrupt context. In that case,
134 if the mutex is already locked, an error will be returned.
135
136 The semantics of this function depend on the type of mutex that is used.
137
138 \param m The mutex to acquire
139 \retval 0 On success
140 \retval -1 On error, sets errno as appropriate
141
142 \par Error Conditions:
143 \em EAGAIN - lock has been acquired too many times (recursive), or the
144 function was called inside an interrupt and the mutex was
145 already locked \n
146*/
147__result_use_check int mutex_lock_irqsafe(mutex_t *m) __nonnull_all;
148
149/** \brief Lock a mutex (with a timeout).
150
151 This function will attempt to lock a mutex. If the lock can be acquired
152 immediately, the function will return immediately. If not, the function will
153 block for up to the specified number of milliseconds to wait for the lock.
154 If the lock cannot be acquired in this timeframe, this function will return
155 an error.
156
157 This function cannot be used in an interrupt context.
158
159 \param m The mutex to acquire
160 \param timeout The number of milliseconds to wait for the lock
161 \retval 0 On success
162 \retval -1 On error, errno will be set as appropriate
163
164 \par Error Conditions:
165 \em ETIMEDOUT - the timeout expired \n
166 \em EAGAIN - lock has been acquired too many times (recursive) \n
167*/
168int mutex_lock_timed(mutex_t *m, unsigned int timeout) __nonnull_all;
169
170/** \brief Lock a mutex.
171
172 This function will lock a mutex, if it is not already locked by another
173 thread. If it is locked by another thread already, this function will block
174 until the mutex has been acquired for the calling thread.
175
176 The semantics of this function depend on the type of mutex that is used.
177
178 This function cannot be used in an interrupt context.
179
180 \param m The mutex to acquire
181 \retval 0 On success
182 \retval -1 On error, sets errno as appropriate
183
184 \par Error Conditions:
185 \em EAGAIN - lock has been acquired too many times (recursive) \n
186*/
187__nonnull_all
188static inline int mutex_lock(mutex_t *m) {
189 return mutex_lock_timed(m, 0);
190}
191
192/** \brief Check if a mutex is locked.
193
194 This function will check whether or not a mutex is currently locked. This is
195 not a thread-safe way to determine if the mutex will be locked by the time
196 you get around to doing it. If you wish to attempt to lock a mutex without
197 blocking, look at mutex_trylock(), not this.
198
199 \param m The mutex to check
200 \retval 0 If the mutex is not currently locked
201 \retval 1 If the mutex is currently locked
202*/
203int __pure mutex_is_locked(const mutex_t *m) __nonnull_all;
204
205/** \brief Attempt to lock a mutex.
206
207 This function will attempt to acquire the mutex for the calling thread,
208 returning immediately whether or not it could be acquired. If the mutex
209 cannot be acquired, an error will be returned.
210
211 This function is safe to call inside an interrupt.
212
213 \param m The mutex to attempt to acquire
214 \retval 0 On successfully acquiring the mutex
215 \retval -1 If the mutex cannot be acquired without blocking
216
217 \par Error Conditions:
218 \em EBUSY - the mutex is already locked (mutex_lock() would block) \n
219 \em EAGAIN - lock has been acquired too many times (recursive) \n
220*/
221int mutex_trylock(mutex_t *m) __nonnull_all;
222
223/** \brief Unlock a mutex.
224
225 This function will unlock a mutex, allowing other threads to acquire it.
226 The semantics of this operation depend on the mutex type in use.
227
228 \param m The mutex to unlock
229 \retval 0 On success
230 \retval -1 On error, errno will be set as appropriate.
231
232 \par Error Conditions: None defined
233*/
234int mutex_unlock(mutex_t *m) __nonnull_all;
235
236/** \cond */
237static inline void __mutex_scoped_cleanup(mutex_t **m) {
238 if(*m)
239 mutex_unlock(*m);
240}
241
242#define ___mutex_lock_scoped(m, l) \
243 mutex_t *__scoped_mutex_##l __attribute__((cleanup(__mutex_scoped_cleanup))) = mutex_lock(m) ? NULL : (m)
244
245#define __mutex_lock_scoped(m, l) ___mutex_lock_scoped(m, l)
246/** \endcond */
247
248/** \brief Lock a mutex with scope management
249
250 This macro will lock a mutex, similarly to mutex_lock, with the difference
251 that the mutex will automatically be unlocked once the execution exits the
252 functional block in which the macro was called.
253
254 \param m The mutex to acquire
255*/
256#define mutex_lock_scoped(m) __mutex_lock_scoped((m), __LINE__)
257
258__END_DECLS
259
260#endif /* __KOS_MUTEX_H */
Various common macros used throughout the codebase.
int mutex_destroy(mutex_t *m) __nonnull_all
Destroy a mutex.
int mutex_lock_timed(mutex_t *m, unsigned int timeout) __nonnull_all
Lock a mutex (with a timeout).
static const unsigned int MUTEX_TYPE_ERRORCHECK
Definition mutex.h:76
__result_use_check int mutex_lock_irqsafe(mutex_t *m) __nonnull_all
Lock a mutex.
static __nonnull_all int mutex_lock(mutex_t *m)
Lock a mutex.
Definition mutex.h:188
int mutex_init(mutex_t *m, unsigned int mtype) __nonnull_all
Initialize a new mutex.
int mutex_unlock(mutex_t *m) __nonnull_all
Unlock a mutex.
int __pure mutex_is_locked(const mutex_t *m) __nonnull_all
Check if a mutex is locked.
int mutex_trylock(mutex_t *m) __nonnull_all
Attempt to lock a mutex.
Mutual exclusion lock type.
Definition mutex.h:56
struct kthread * holder
Definition mutex.h:58
int count
Definition mutex.h:59
unsigned int type
Definition mutex.h:57