1// 2// close group struct osMutexAttr_t 3/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 4// ==== Mutex Management ==== 5/** 6\addtogroup CMSIS_RTOS_MutexMgmt Mutex Management 7\ingroup CMSIS_RTOS 8\brief Synchronize resource access using Mutual Exclusion (Mutex). 9\details 10<b>Mutual exclusion</b> (widely known as \b Mutex) is used in various operating systems for resource management. Many 11resources in a microcontroller device can be used repeatedly, but only by one thread at a time (for example communication 12channels, memory, and files). Mutexes are used to protect access to a shared resource. A mutex is created and then passed 13between the threads (they can acquire and release the mutex). 14 15\image html "Mutex.png" "CMSIS-RTOS Mutex" 16 17A mutex is a special version of a \ref CMSIS_RTOS_SemaphoreMgmt "semaphore". Like the semaphore, it is a container for 18tokens. But instead of being able to have multiple tokens, a mutex can only carry one (representing the resource). Thus, a 19mutex token is binary and bounded, i.e. it is either \em available, or \em blocked by a owning thread. The advantage of a 20mutex is that it introduces thread ownership. When a thread acquires a mutex and becomes its owner, subsequent mutex acquires 21from that thread will succeed immediately without any latency (if \ref osMutexRecursive is specified). Thus, mutex acquires/releases 22can be nested. 23 24\image html "mutex_states.png" "CMSIS-RTOS Mutex States" 25 26\note Mutex management functions cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines" (ISR), unlike a 27binary semaphore that can be released from an ISR. 28 29@{ 30*/ 31/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 32/** 33\def osMutexRecursive 34\details 35Recursive flag in osMutexAttr_t. 36 37The same thread can consume a mutex multiple times without locking itself. 38Each time the owning thread acquires the mutex the lock count is incremented. The mutex must 39be released multiple times as well until the lock count reaches zero. At reaching zero the 40mutex is actually released and can be acquired by other threads. 41 42\note The maximum amount of recursive locks possible is implementation specific, i.e. the type size used for the lock count. 43If the maximum amount of recursive locks is depleted mutex acquire might fail. 44 45<b>Code Example</b> 46\code 47#include "cmsis_os2.h" 48 49osMutexId_t mutex_id; 50 51const osMutexAttr_t Thread_Mutex_attr = { 52 "myThreadMutex", // human readable mutex name 53 osMutexRecursive, // attr_bits 54 NULL, // memory for control block 55 0U // size for control block 56}; 57 58// must be called from a thread context 59void UseMutexRecursively(int count) { 60 osStatus_t result = osMutexAcquire(mutex_id, osWaitForever); // lock count is incremented, might fail when lock count is depleted 61 if (result == osOK) { 62 if (count < 10) { 63 UseMutexRecursively(count + 1); 64 } 65 osMutexRelease(mutex_id); // lock count is decremented, actually releases the mutex on lock count zero 66 } 67} 68\endcode 69*/ 70 71/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 72/** 73\def osMutexPrioInherit 74\details 75Priority inheritance flag in osMutexAttr_t. 76 77A mutex using priority inheritance protocol transfers a waiting threads priority to the 78current mutex owner if the owners thread priority is lower. This assures that a low priority 79thread does not block a high priority thread. 80 81Otherwise a low priority thread might hold a mutex but is not granted execution time due to 82another mid priority thread. Without priority inheritance the high priority thread waiting 83for the mutex would be blocked by the mid priority thread, called priority inversion. 84 85<b>Code Example</b> 86 87This example reveals a blocked high priority thread if \ref osMutexPrioInherit is removed. 88 89\code 90#include "cmsis_os2.h" 91 92osMutexId_t mutex_id; 93 94const osMutexAttr_t Thread_Mutex_attr = { 95 "myThreadMutex", // human readable mutex name 96 osMutexPrioInherit, // attr_bits 97 NULL, // memory for control block 98 0U // size for control block 99}; 100 101void HighPrioThread(void *argument) { 102 osDelay(1000U); // wait 1s until start actual work 103 while(1) { 104 osMutexAcquire(mutex_id, osWaitForever); // try to acquire mutex 105 // do stuff 106 osMutexRelease(mutex_id); 107 } 108} 109 110void MidPrioThread(void *argument) { 111 osDelay(1000U); // wait 1s until start actual work 112 while(1) { 113 // do non blocking stuff 114 } 115} 116 117void LowPrioThread(void *argument) { 118 while(1) { 119 osMutexAcquire(mutex_id, osWaitForever); 120 osDelay(5000U); // block mutex for 5s 121 osMutexRelease(mutex_id); 122 osDelay(5000U); // sleep for 5s 123 } 124} 125\endcode 126 127During the first second the high and mid priority threads are delayed. Thus the low priority 128thread can start its work, acquires the mutex and delays while holding it. 129 130After the first second the high and mid priority threads become ready. Thus the high priority 131thread gets precedence and tries to acquire the mutex. Because the mutex is already owned by 132the low priority thread the high priority thread gets blocked. 133 134Finally the mid priority thread gets executed and start doing a lot of non-blocking stuff, 135i.e. it does not call any blocking RTOS functionality. 136 137Without \ref osMutexPrioInherit we would stuck here forever. Even if the low priority thread 138gets ready after 5s. Due to its low priority the mid priority thread always gets precedence. 139The effect called priority inversion leads to the mid priority thread blocking the high 140priority thread indirectly. 141 142Using \ref osMutexPrioInherit as shown in the example code we get rid of this situation. Due 143to the priority inheritance protocol the low priority thread inherits the high priority 144while holding the mutex. Thus the low priority thread gets precedence over the mid priority 145thread until it release the mutex. On osMutexRelease the high priority thread get ready and 146is scheduled immediately. 147 148*/ 149 150/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 151/** 152\def osMutexRobust 153\details 154Robust flag in osMutexAttr_t. 155 156Robust mutexes are automatically released if the owning thread is terminated (either by 157\ref osThreadExit or \ref osThreadTerminate). Non-robust mutexes are not released and the user must 158assure mutex release manually. 159 160<b>Code Example</b> 161 162This example reveals a blocked mutex if osMutexRobust is removed. 163 164\code 165#include "cmsis_os2.h" 166 167osMutexId_t mutex_id; 168 169const osMutexAttr_t Thread_Mutex_attr = { 170 "myThreadMutex", // human readable mutex name 171 osMutexRobust, // attr_bits 172 NULL, // memory for control block 173 0U // size for control block 174}; 175 176void Thread(void *argument) { 177 osMutexAcquire(mutex_id, osWaitForever); 178 osThreadExit(); 179} 180\endcode 181 182Due to \ref osMutexRobust the mutex gets released automatically. A non-robust mutex would stay locked and cannot be released anymore. 183*/ 184 185/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 186/** 187\typedef osMutexId_t 188\details 189Returned by: 190- \ref osMutexNew 191*/ 192 193/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 194/** 195\struct osMutexAttr_t 196\details 197Specifies the following attributes for the \ref osMutexNew function. 198*/ 199 200/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 201/** 202\fn osMutexId_t osMutexNew (const osMutexAttr_t *attr) 203\details 204The function \b osMutexNew creates and initializes a new mutex object and returns the pointer to the mutex object identifier 205or \token{NULL} in case of an error. It can be safely called before the RTOS is 206started (call to \ref osKernelStart), but not before it is initialized (call to \ref osKernelInitialize). 207 208The parameter \a attr sets the mutex object attributes (refer to \ref osMutexAttr_t). Default attributes will be used if set 209to \token{NULL}. 210 211\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". 212 213<b>Code Example</b> 214\code 215#include "cmsis_os2.h" 216 217osMutexId_t mutex_id; 218 219const osMutexAttr_t Thread_Mutex_attr = { 220 "myThreadMutex", // human readable mutex name 221 osMutexRecursive | osMutexPrioInherit, // attr_bits 222 NULL, // memory for control block 223 0U // size for control block 224}; 225 226void CreateMutex (void) { 227 mutex_id = osMutexNew(&Thread_Mutex_attr); 228 if (mutex_id != NULL) { 229 // Mutex object created 230 } 231} 232\endcode 233*/ 234 235*/ 236/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 237/** 238\fn const char *osMutexGetName (osMutexId_t mutex_id) 239\details 240The function \b osMutexGetName returns the pointer to the name string of the mutex identified by parameter \a mutex_id or 241\token{NULL} in case of an error. 242 243\note This function may be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". 244*/ 245 246/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 247/** 248\fn osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) 249\details 250The blocking function \b osMutexAcquire waits until a mutex object specified by parameter \a mutex_id becomes available. If 251no other thread has obtained the mutex, the function instantly returns and blocks the mutex object. 252 253The parameter \a timeout specifies how long the system waits to acquire the mutex. While the system waits, the thread that is 254calling this function is put into the \ref ThreadStates "BLOCKED" state. The parameter \ref CMSIS_RTOS_TimeOutValue "timeout" 255can have the following values: 256 - when \a timeout is \token{0}, the function returns instantly (i.e. try semantics). 257 - 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). 258 - all other values specify a time in kernel ticks for a timeout (i.e. timed-wait semantics). 259 260Possible \ref osStatus_t return values: 261 - \em osOK: the mutex has been obtained. 262 - \em osErrorTimeout: the mutex could not be obtained in the given time. 263 - \em osErrorResource: the mutex could not be obtained when no \a timeout was specified. 264 - \em osErrorParameter: parameter \em mutex_id is \token{NULL} or invalid. 265 - \em osErrorISR: cannot be called from interrupt service routines. 266 - \em osErrorSafetyClass: the calling thread safety class is lower than the safety class of the specified mutex. 267 268\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". 269 270<b>Code Example</b> 271\code 272#include "cmsis_os2.h" 273 274void WaitMutex (void) { 275 osMutexId_t mutex_id; 276 osStatus_t status; 277 278 mutex_id = osMutexNew(NULL); 279 if (mutex_id != NULL) { 280 status = osMutexAcquire(mutex_id, 0U); 281 if (status != osOK) { 282 // handle failure code 283 } 284 } 285} 286\endcode 287*/ 288 289/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 290/** 291\fn osStatus_t osMutexRelease (osMutexId_t mutex_id) 292\details 293The function \b osMutexRelease releases a mutex specified by parameter \a mutex_id. Other threads that currently wait for 294this mutex will be put into the \ref ThreadStates "READY" state. 295 296Possible \ref osStatus_t return values: 297 - \em osOK: the mutex has been correctly released. 298 - \em osErrorResource: the mutex could not be released (mutex was not acquired or running thread is not the owner). 299 - \em osErrorParameter: parameter \em mutex_id is \token{NULL} or invalid. 300 - \em osErrorISR: \b osMutexRelease cannot be called from interrupt service routines. 301 302\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". 303 304<b>Code Example</b> 305\code 306#include "cmsis_os2.h" 307 308osMutexId_t mutex_id; // Mutex id populated by the function osMutexNew() 309 310void ReleaseMutex (osMutexId_t mutex_id) { 311 osStatus_t status; 312 313 if (mutex_id != NULL) { 314 status = osMutexRelease(mutex_id); 315 if (status != osOK) { 316 // handle failure code 317 } 318 } 319} 320\endcode 321*/ 322 323/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 324/** 325\fn osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) 326\details 327The function \b osMutexGetOwner returns the thread ID of the thread that acquired a mutex specified by parameter \a 328mutex_id. In case of an error or if the mutex is not blocked by any thread, it returns \token{NULL}. 329 330\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". 331*/ 332 333/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/ 334/** 335\fn osStatus_t osMutexDelete (osMutexId_t mutex_id) 336\details 337The function \b osMutexDelete deletes a mutex object specified by parameter \a mutex_id. It releases internal memory obtained 338for mutex handling. After this call, the \a mutex_id is no longer valid and cannot be used. The mutex may be created again 339using the function \ref osMutexNew. 340 341Possible \ref osStatus_t return values: 342 - \em osOK: the mutex object has been deleted. 343 - \em osErrorParameter: parameter \em mutex_id is \token{NULL} or invalid. 344 - \em osErrorResource: the mutex is in an invalid state. 345 - \em osErrorISR: \b osMutexDelete cannot be called from interrupt service routines. 346 - \em osErrorSafetyClass: the calling thread safety class is lower than the safety class of the specified mutex. 347 348\note This function \b cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines". 349 350<b>Code Example</b> 351\code 352#include "cmsis_os2.h" 353 354osMutexId_t mutex_id; // Mutex id populated by the function osMutexNew() 355 356void DeleteMutex (osMutexId_t mutex_id) { 357 osStatus_t status; 358 359 if (mutex_id != NULL) { 360 status = osMutexDelete(mutex_id); 361 if (status != osOK) { 362 // handle failure code 363 } 364 } 365} 366\endcode 367*/ 368/// @} 369 370// these struct members must stay outside the group to avoid double entries in documentation 371/** 372\var osMutexAttr_t::attr_bits 373\details 374The following bit masks can be used to set options: 375 - \ref osMutexRecursive : a thread can consume the mutex multiple times without locking itself. 376 - \ref osMutexPrioInherit : the owner thread inherits the priority of a (higher priority) waiting thread. 377 - \ref osMutexRobust : the mutex is automatically released when owner thread is terminated. 378 379Use logical \em 'OR' operation to select multiple options, for example: 380\code 381osMutexRecursive | osMutexPrioInherit; 382\endcode 383 384Default: \token{0} which specifies: 385 - <i>non recursive mutex</i>: a thread cannot consume the mutex multiple times. 386 - <i>non priority raising</i>: the priority of an owning thread is not changed. 387 - <i>mutex is not automatically release</i>: the mutex object must be always is automatically released when owner thread is terminated. 388 389*/ 390/** 391\var osMutexAttr_t::cb_mem 392\details 393Pointer to a memory for the mutex control block object. Refer to \ref CMSIS_RTOS_MemoryMgmt_Manual for more information. 394 395Default: \token{NULL} to use \ref CMSIS_RTOS_MemoryMgmt_Automatic for the mutex control block. 396*/ 397/** 398\var osMutexAttr_t::cb_size 399\details 400The size (in bytes) of memory block passed with \ref cb_mem. Required value depends on the underlying kernel implementation. 401 402Default: \token{0} as the default is no memory provided with \ref cb_mem. 403*/ 404/** 405\var osMutexAttr_t::name 406\details 407Pointer to a constant string with a human readable name (displayed during debugging) of the mutex object. 408 409Default: \token{NULL} no name specified. 410*/ 411