2 // close group struct osMutexAttr_t
3 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
4 // ==== Mutex Management ====
6 \addtogroup CMSIS_RTOS_MutexMgmt Mutex Management
8 \brief Synchronize resource access using Mutual Exclusion (Mutex).
10 <b>Mutual exclusion</b> (widely known as \b Mutex) is used in various operating systems for resource management. Many
11 resources in a microcontroller device can be used repeatedly, but only by one thread at a time (for example communication
12 channels, memory, and files). Mutexes are used to protect access to a shared resource. A mutex is created and then passed
13 between the threads (they can acquire and release the mutex).
15 \image html "Mutex.png" "CMSIS-RTOS Mutex"
17 A mutex is a special version of a \ref CMSIS_RTOS_SemaphoreMgmt "semaphore". Like the semaphore, it is a container for
18 tokens. But instead of being able to have multiple tokens, a mutex can only carry one (representing the resource). Thus, a
19 mutex token is binary and bounded, i.e. it is either \em available, or \em blocked by a owning thread. The advantage of a
20 mutex is that it introduces thread ownership. When a thread acquires a mutex and becomes its owner, subsequent mutex acquires
21 from that thread will succeed immediately without any latency (if \ref osMutexRecursive is specified). Thus, mutex acquires/releases
24 \image html "mutex_states.png" "CMSIS-RTOS Mutex States"
26 \note Mutex management functions cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines" (ISR), unlike a
27 binary semaphore that can be released from an ISR.
28 \note Refer to \ref mutexConfig for RTX5 configuration options.
32 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
36 Recursive flag in osMutexAttr_t.
38 The same thread can consume a mutex multiple times without locking itself.
39 Each time the owning thread acquires the mutex the lock count is incremented. The mutex must
40 be released multiple times as well until the lock count reaches zero. At reaching zero the
41 mutex is actually released and can be acquired by other threads.
43 \note The maximum amount of recursive locks possible is implementation specific, i.e. the type size used for the lock count.
44 If the maximum amount of recursive locks is depleted mutex acquire might fail.
48 #include "cmsis_os2.h"
52 const osMutexAttr_t Thread_Mutex_attr = {
53 "myThreadMutex", // human readable mutex name
54 osMutexRecursive, // attr_bits
55 NULL, // memory for control block
56 0U // size for control block
59 // must be called from a thread context
60 void UseMutexRecursively(int count) {
61 osStatus_t result = osMutexAcquire(mutex_id, osWaitForever); // lock count is incremented, might fail when lock count is depleted
64 UseMutexRecursively(count + 1);
66 osMutexRelease(mutex_id); // lock count is decremented, actually releases the mutex on lock count zero
72 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
74 \def osMutexPrioInherit
76 Priority inheritance flag in osMutexAttr_t.
78 A mutex using priority inheritance protocol transfers a waiting threads priority to the
79 current mutex owner if the owners thread priority is lower. This assures that a low priority
80 thread does not block a high priority thread.
82 Otherwise a low priority thread might hold a mutex but is not granted execution time due to
83 another mid priority thread. Without priority inheritance the high priority thread waiting
84 for the mutex would be blocked by the mid priority thread, called priority inversion.
88 This example reveals a blocked high priority thread if osMutexPrioInherit is removed.
91 #include "cmsis_os2.h"
95 const osMutexAttr_t Thread_Mutex_attr = {
96 "myThreadMutex", // human readable mutex name
97 osMutexPrioInherit, // attr_bits
98 NULL, // memory for control block
99 0U // size for control block
102 void HighPrioThread(void *argument) {
103 osDelay(1000); // wait 1s until start actual work
105 osMutexAcquire(mutex_id, osWaitForever); // try to acquire mutex
107 osMutexRelease(mutex_id);
111 void MidPrioThread(void *argument) {
112 osDelay(1000); // wait 1s until start actual work
114 // do non blocking stuff
118 void LowPrioThread(void *argument) {
120 osMutexAcquire(mutex_id, osWaitForever);
121 osDelay(5000); // block mutex for 5s
122 osMutexRelease(mutex_id);
123 osDelay(5000); // sleep for 5s
128 During the first second the high and mid priority threads are delayed. Thus the low priority
129 thread can start its work, acquires the mutex and delays while holding it.
131 After the first second the high and mid priority threads become ready. Thus the high priority
132 thread gets precedence and tries to acquire the mutex. Because the mutex is already owned by
133 the low priority thread the high priority thread gets blocked.
135 Finally the mid priority thread gets executed and start doing a lot of non-blocking stuff,
136 i.e. it does not call any blocking RTOS functionality.
138 Without osMutexPrioInherit we would stuck here forever. Even if the low priority thread
139 gets ready after 5s. Due to its low priority the mid priority thread always gets precedence.
140 The effect called priority inversion leads to the mid priority thread blocking the high
141 priority thread indirectly.
143 Using osMutexPrioInherit as shown in the example code we get rid of this situation. Due
144 to the priority inheritance protocol the low priority thread inherites the high priority
145 while holding the mutex. Thus the low priority thread gets precedence over the mid priority
146 thread until it release the mutex. On osMutexRelease the high priority thread get ready and
147 is scheduled immediately.
151 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
155 Robust flag in osMutexAttr_t.
157 Robust mutexes are automatically released if the owning thread is terminated (either by
158 osThreadExit or osThreadTerminate). Non-robust mutexes are not released and the user must
159 assure mutex release manually.
163 This example reveals a blocked mutex if osMutexRobust is removed.
166 #include "cmsis_os2.h"
168 osMutexId_t mutex_id;
170 const osMutexAttr_t Thread_Mutex_attr = {
171 "myThreadMutex", // human readable mutex name
172 osMutexRobust, // attr_bits
173 NULL, // memory for control block
174 0U // size for control block
177 void Thread(void *argument) {
178 osMutexAcquire(mutex_id, osWaitForever);
183 Due to osMutexRobust the mutex gets released automatically. A non-robust mutex would stay locked and cannot be released anymore.
186 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
194 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
196 \struct osMutexAttr_t
198 Attributes to configure a mutex.
200 Refer to \ref CMSIS_RTOS_MemoryMgmt for details about usage of
201 - osMutexAttr_t::cb_mem
202 - osMutexAttr_t::cb_size
205 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
207 \fn osMutexId_t osMutexNew (const osMutexAttr_t *attr)
209 The function \b osMutexNew creates and initializes a new mutex object and returns the pointer to the mutex object identifier
210 or \token{NULL} in case of an error. It can be safely called before the RTOS is
211 started (call to \ref osKernelStart), but not before it is initialized (call to \ref osKernelInitialize).
213 The parameter \a attr sets the mutex object attributes (refer to \ref osMutexAttr_t). Default attributes will be used if set
218 Possible return values:
219 - pointer to the mutex object identifier, in case of success
220 - \em 'NULL', if the control block memory (\em attr->cb_mem) is not \em NULL and the memory is not 4 byte aligned
221 - \em 'NULL', if the control block memory (\em attr->cb_mem) is not \em NULL but the size (\em attr->cb_size) is not big enough to store a \em mutex object control block
222 - \em 'NULL', if the control block memory (\em attr->cb_mem) is \em NULL but the size (\em attr->cb_size) is not 0
223 - \em NULL, if in IRQ mode
224 - \em NULL, if IRQ is masked.
226 \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
230 #include "cmsis_os2.h"
232 osMutexId_t mutex_id;
234 const osMutexAttr_t Thread_Mutex_attr = {
235 "myThreadMutex", // human readable mutex name
236 osMutexRecursive | osMutexPrioInherit, // attr_bits
237 NULL, // memory for control block
238 0U // size for control block
241 void CreateMutex (void) {
242 mutex_id = osMutexNew(&Thread_Mutex_attr);
243 if (mutex_id != NULL) {
244 // Mutex object created
251 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
253 \fn const char *osMutexGetName (osMutexId_t mutex_id)
255 The function \b osMutexGetName returns the pointer to the name string of the mutex identified by parameter \a mutex_id or
256 \token{NULL} in case of an error.
258 Possible return values:
259 - pointer to the name string of the mutex, in case of success
260 - \em NULL, if a mutex specified by \a mutex_id does not exist
261 - \em NULL, if the mutex specified by \a mutex_id is \em NULL
262 - \em NULL, if the state of the mutex is \em 'osRtxObjectInactive'
263 - \em NULL, if IRQ is masked
264 - \em NULL, if in IRQ mode.
268 \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
271 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
273 \fn osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout)
275 The blocking function \b osMutexAcquire waits until a mutex object specified by parameter \a mutex_id becomes available. If
276 no other thread has obtained the mutex, the function instantly returns and blocks the mutex object.
278 The parameter \a timeout specifies how long the system waits to acquire the mutex. While the system waits, the thread that is
279 calling this function is put into the \ref ThreadStates "BLOCKED" state. The parameter \ref CMSIS_RTOS_TimeOutValue "timeout"
280 can have the following values:
281 - when \a timeout is \token{0}, the function returns instantly (i.e. try semantics).
282 - when \a timeout is set to \b osWaitForever the function will wait for an infinite time until the mutex becomes available (i.e. wait semantics).
283 - all other values specify a time in kernel ticks for a timeout (i.e. timed-wait semantics).
285 Possible \ref osStatus_t return values:
286 - \em 'osOK', if the mutex specified by \a mutex_id has been obtained
287 - \em 'osErrorTimeOut', if the mutex is locked by another thread and \em timeout > 0
288 - \em 'osErrorResource', if the mutex is locked by another thread and \em timeout == 0
289 - \em 'osErrorParameter', if the mutex is equal to \em NULL
290 - \em 'osErrorResource' if the maximum number of mutex locks has been reached (\em mutex->lock is greater than \em 'osRtxMutexLockLimit')
291 - \em 'osErrorParameter', if the mutex specified by \a mutex_id does not exist
292 - \em 'osErrorResource', if the mutex is in state \em 'osRtxObjectInactive'
293 - \em 'osErrorISR', if IRQ is masked
294 - \em 'osErrorISR', in IRQ mode.
297 \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
301 #include "cmsis_os2.h"
303 void WaitMutex (void) {
304 osMutexId_t mutex_id;
307 mutex_id = osMutexNew(NULL);
308 if (mutex_id != NULL) {
309 status = osMutexAcquire(mutex_id, 0);
310 if (status != osOK) {
311 // handle failure code
318 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
320 \fn osStatus_t osMutexRelease (osMutexId_t mutex_id)
322 The function \b osMutexRelease releases a mutex specified by parameter \a mutex_id. Other threads that currently wait for
323 this mutex will be put into the \ref ThreadStates "READY" state.
325 Possible \ref osStatus_t return values:
326 - \em 'osOK', if the mutex specified by \em mutex_id has been correctly released
327 - \em 'osErrorResource' if the mutex specified by \em mutex_id is in state \em 'osRtxObjectInactive'
328 - \em 'osErrorResource' if the running thread does not own the mutex specified by \em mutex_id
329 - \em 'osErrorParameter' if a mutex specified by \a mutex_id does not exist
330 - \em 'osErrorParameter' if the mutex specified by \em mutex_id is \em NULL
331 - \em 'osErrorResource', if the mutex specified by \em mutex_id is not locked
332 - \em 'osErrorISR', if IRQ is masked
333 - \em 'osErrorISR', if in IRQ mode.
336 \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
340 #include "cmsis_os2.h"
342 osMutexId_t mutex_id; // Mutex id populated by the function osMutexNew()
344 void ReleaseMutex (osMutexId_t mutex_id) {
347 if (mutex_id != NULL) {
348 status = osMutexRelease(mutex_id);
349 if (status != osOK) {
350 // handle failure code
357 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
359 \fn osThreadId_t osMutexGetOwner (osMutexId_t mutex_id)
361 The function \b osMutexGetOwner returns the thread ID of the thread that acquired a mutex specified by parameter \a
362 mutex_id. In case of an error or if the mutex is not blocked by any thread, it returns \token{NULL}.
364 Possible \ref osThreadId_t return values:
365 - the thread ID of the thread that acquired the mutex specified by \a mutex_id
366 - \em NULL, if the mutex specified by \em mutex_id is not blocked
367 - \em NULL, if a mutex specified by \a mutex_id does not exist
368 - \em NULL, if the mutex is \em NULL
369 - \em NULL, if the state of of the mutex specified by \em mutex_id is \em 'osRtxObjectInactive'
370 - \em NULL, if IRQ is masked
371 - \em NULL, if in IRQ mode.
373 \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
376 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
378 \fn osStatus_t osMutexDelete (osMutexId_t mutex_id)
380 The function \b osMutexDelete deletes a mutex object specified by parameter \a mutex_id. It releases internal memory obtained
381 for mutex handling. After this call, the \a mutex_id is no longer valid and cannot be used. The mutex may be created again
382 using the function \ref osMutexNew.
384 Possible \ref osStatus_t return values:
385 - \em 'osOK', if the mutex specified by \a mutex_id mutex_id has been deleted
386 - \em 'osErrorParameter', if a mutex specified by \a mutex_id mutex_id does not exist
387 - \em 'osErrrorResource', if the state of the mutex specified by \a mutex_id mutex_id is \em 'osRtxObjectInactive'
388 - \em 'osErrorISR', if IRQ is masked
389 - \em 'osErrorISR', in IRQ mode.
392 \note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
396 #include "cmsis_os2.h"
398 osMutexId_t mutex_id; // Mutex id populated by the function osMutexNew()
400 void DeleteMutex (osMutexId_t mutex_id) {
403 if (mutex_id != NULL) {
404 status = osMutexDelete(mutex_id);
405 if (status != osOK) {
406 // handle failure code
414 // these struct members must stay outside the group to avoid double entries in documentation
416 \var osMutexAttr_t::attr_bits
418 The following predefined bit masks can be assigned to set options for a mutex object.
420 | Bit Mask | Description |
421 | :-------------------------- | :------------------ |
422 | \ref osMutexRecursive | Mutex is recursive. |
423 | \ref osMutexPrioInherit | Priority inheritance protocol. |
424 | \ref osMutexRobust | Robust mutex. |
428 \var osMutexAttr_t::cb_mem
430 Pointer to a memory location for the mutex control block object. This can optionally be used for custom memory management systems.\n
431 Default: \token{NULL} (uses kernel memory management).
434 \var osMutexAttr_t::cb_size
436 The size of the memory block passed with \ref cb_mem. Must be the size of a mutex control block object or larger.
439 \var osMutexAttr_t::name
441 Pointer to a string with a human readable name of the event object.\n
442 Default: \token{NULL}.