KallistiOS  2.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
mutex.h
Go to the documentation of this file.
1 /* KallistiOS 2.0.0
2 
3  include/kos/mutex.h
4  Copyright (C) 2001, 2003 Dan Potter
5  Copyright (C) 2012 Lawrence Sebald
6 
7 */
8 
9 /* Other than the old function names, there's basically nothing left of the old
10  version of mutexes... */
11 
12 /** \file kos/mutex.h
13  \brief Mutual exclusion locks.
14 
15  This file defines mutual exclusion locks (or mutexes for short). The concept
16  of a mutex is one of the most common types of locks in a multi-threaded
17  environment. Mutexes do exactly what they sound like, they keep two (or
18  more) threads mutually exclusive from one another. A mutex is used around
19  a block of code to prevent two threads from interfereing with one another
20  when only one would be appropriate to be in the block at a time.
21 
22  KallistiOS implments 3 types of mutexes, to bring it roughly in-line with
23  POSIX. The types of mutexes that can be made are normal, error-checking, and
24  recursive. Each has its own strengths and weaknesses, which are briefly
25  discussed below.
26 
27  A normal mutex (MUTEX_TYPE_NORMAL) is the fastest and simplest mutex of the
28  bunch. This is roughly equivalent to a semaphore that has been initialized
29  with a count of 1. There is no protection against threads unlocking normal
30  mutexes they didn't lock, nor is there any protection against deadlocks that
31  would arise from locking the mutex twice.
32 
33  An error-checking mutex (MUTEX_TYPE_ERRORCHECK) adds a small amount of error
34  checking on top of a normal mutex. This type will not allow you to lock the
35  mutex twice (it will return an error if the same thread tries to lock it two
36  times so it will not deadlock), and it will not allow a different thread to
37  unlock the mutex if it isn't the one holding the lock.
38 
39  A recursive mutex (MUTEX_TYPE_RECURSIVE) extends the error checking mutex
40  by allowing you to lock the mutex twice in the same thread, but you must
41  also unlock it twice (this works for any number of locks -- lock it n times,
42  you must unlock it n times). Still only one thread can hold the lock, but it
43  may hold it as many times as it needs to. This is equivalent to the
44  recursive_lock_t type that was available in KallistiOS for a while (before
45  it was basically merged back into a normal mutex).
46 
47  There is a fourth type of mutex defined (MUTEX_TYPE_DEFAULT), which maps to
48  the MUTEX_TYPE_NORMAL type. This is simply for alignment with POSIX.
49 
50  \author Lawrence Sebald
51  \see kos/sem.h
52 */
53 
54 #ifndef __KOS_MUTEX_H
55 #define __KOS_MUTEX_H
56 
57 #include <sys/cdefs.h>
58 
59 __BEGIN_DECLS
60 
61 #include <kos/thread.h>
62 
63 /** \brief Mutual exclusion lock type.
64 
65  All members of this structure should be considered to be private. It is
66  unsafe to change anything in here yourself.
67 
68  \headerfile kos/mutex.h
69 */
70 typedef struct kos_mutex {
71  int type;
72  int dynamic;
74  int count;
75 } mutex_t;
76 
77 /** \defgroup mutex_types Mutex types
78 
79  The values defined in here are the various types of mutexes that KallistiOS
80  supports.
81 
82  @{
83 */
84 #define MUTEX_TYPE_NORMAL 1 /**< \brief Normal mutex type */
85 #define MUTEX_TYPE_ERRORCHECK 2 /**< \brief Error-checking mutex type */
86 #define MUTEX_TYPE_RECURSIVE 3 /**< \brief Recursive mutex type */
87 
88 /** \brief Default mutex type */
89 #define MUTEX_TYPE_DEFAULT MUTEX_TYPE_NORMAL
90 /** @} */
91 
92 /** \brief Initializer for a transient mutex. */
93 #define MUTEX_INITIALIZER { MUTEX_TYPE_NORMAL, 0, NULL, 0 }
94 
95 /** \brief Initializer for a transient error-checking mutex. */
96 #define ERRORCHECK_MUTEX_INITIALIZER { MUTEX_TYPE_ERRORCHECK, 0, NULL, 0 }
97 
98 /** \brief Initializer for a transient recursive mutex. */
99 #define RECURSIVE_MUTEX_INITIALIZER { MUTEX_TYPE_RECURSIVE, 0, NULL, 0 }
100 
101 /** \brief Allocate a new mutex.
102 
103  This function allocates and initializes a new mutex for use. This function
104  will always create mutexes of the type MUTEX_TYPE_NORMAL.
105 
106  \return The newly created mutex on success, or NULL on
107  failure (errno will be set as appropriate).
108 
109  \note This function is formally deprecated. It should not
110  be used in any future code, and may be removed in
111  the future. You should instead use mutex_init().
112 */
113 mutex_t *mutex_create() __attribute__((deprecated));
114 
115 /** \brief Initialize a new mutex.
116 
117  This function initializes a new mutex for use.
118 
119  \param m The mutex to initialize
120  \param mtype The type of the mutex to initialize it to
121 
122  \retval 0 On success
123  \retval -1 On error, errno will be set as appropriate
124 
125  \par Error Conditions:
126  \em EINVAL - an invalid type of mutex was specified
127 
128  \sa mutex_types
129 */
130 int mutex_init(mutex_t *m, int mtype);
131 
132 /** \brief Destroy a mutex.
133 
134  This function destroys a mutex, releasing any memory that may have been
135  allocated internally for it. It is your responsibility to make sure that all
136  threads waiting on the mutex are taken care of before destroying the mutex.
137 
138  This function can be called on statically initialized, as well as
139  dynamically initialized ones.
140 
141  \retval 0 On success
142  \retval -1 On error, errno will be set as appropriate
143 
144  \par Error Conditions:
145  \em EBUSY - the mutex is currently locked
146 */
147 int mutex_destroy(mutex_t *m);
148 
149 /** \brief Lock a mutex.
150 
151  This function will lock a mutex, if it is not already locked by another
152  thread. If it is locked by another thread already, this function will block
153  until the mutex has been acquired for the calling thread.
154 
155  The semantics of this function depend on the type of mutex that is used.
156 
157  \param m The mutex to acquire
158  \retval 0 On success
159  \retval -1 On error, sets errno as appropriate
160 
161  \par Error Conditions:
162  \em EPERM - called inside an interrupt \n
163  \em EINVAL - the mutex has not been initialized properly \n
164  \em EAGAIN - lock has been acquired too many times (recursive) \n
165  \em EDEADLK - would deadlock (error-checking)
166 */
167 int mutex_lock(mutex_t *m);
168 
169 /** \brief Lock a mutex (with a timeout).
170 
171  This function will attempt to lock a mutex. If the lock can be acquired
172  immediately, the function will return immediately. If not, the function will
173  block for up to the specified number of milliseconds to wait for the lock.
174  If the lock cannot be acquired in this timeframe, this function will return
175  an error.
176 
177  \param m The mutex to acquire
178  \param timeout The number of milliseconds to wait for the lock
179  \retval 0 On success
180  \retval -1 On error, errno will be set as appropriate
181 
182  \par Error Conditions:
183  \em EPERM - called inside an interrupt \n
184  \em EINVAL - the mutex has not been initialized properly \n
185  \em EINVAL - the timeout value was invalid (less than 0) \n
186  \em ETIMEDOUT - the timeout expired \n
187  \em EAGAIN - lock has been acquired too many times (recursive) \n
188  \em EDEADLK - would deadlock (error-checking)
189 */
190 int mutex_lock_timed(mutex_t *m, int timeout);
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 */
203 int mutex_is_locked(mutex_t *m);
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 EAGAIN - the mutex is already locked (mutex_lock() would block) \n
219  \em EINVAL - the mutex has not been initialized properly \n
220  \em EAGAIN - lock has been acquired too many times (recursive) \n
221  \em EDEADLK - would deadlock (error-checking)
222 */
223 int mutex_trylock(mutex_t *m);
224 
225 /** \brief Unlock a mutex.
226 
227  This function will unlock a mutex, allowing other threads to acquire it.
228  The semantics of this operation depend on the mutex type in use.
229 
230  \param m The mutex to unlock
231  \retval 0 On success
232  \retval -1 On error, errno will be set as appropriate.
233 
234  \par Error Conditions:
235  \em EPERM - the current thread does not own the mutex (error-checking or
236  recursive)
237 */
238 int mutex_unlock(mutex_t *m);
239 
240 __END_DECLS
241 
242 #endif /* __KOS_MUTEX_H */
243