|  | .. _mutexes_v2: | 
|  |  | 
|  | Mutexes | 
|  | ####### | 
|  |  | 
|  | A :dfn:`mutex` is a kernel object that implements a traditional | 
|  | reentrant mutex. A mutex allows multiple threads to safely share | 
|  | an associated hardware or software resource by ensuring mutually exclusive | 
|  | access to the resource. | 
|  |  | 
|  | .. contents:: | 
|  | :local: | 
|  | :depth: 2 | 
|  |  | 
|  | Concepts | 
|  | ******** | 
|  |  | 
|  | Any number of mutexes can be defined (limited only by available RAM). Each mutex | 
|  | is referenced by its memory address. | 
|  |  | 
|  | A mutex has the following key properties: | 
|  |  | 
|  | * A **lock count** that indicates the number of times the mutex has be locked | 
|  | by the thread that has locked it. A count of zero indicates that the mutex | 
|  | is unlocked. | 
|  |  | 
|  | * An **owning thread** that identifies the thread that has locked the mutex, | 
|  | when it is locked. | 
|  |  | 
|  | A mutex must be initialized before it can be used. This sets its lock count | 
|  | to zero. | 
|  |  | 
|  | A thread that needs to use a shared resource must first gain exclusive rights | 
|  | to access it by **locking** the associated mutex. If the mutex is already locked | 
|  | by another thread, the requesting thread may choose to wait for the mutex | 
|  | to be unlocked. | 
|  |  | 
|  | After locking a mutex, the thread may safely use the associated resource | 
|  | for as long as needed; however, it is considered good practice to hold the lock | 
|  | for as short a time as possible to avoid negatively impacting other threads | 
|  | that want to use the resource. When the thread no longer needs the resource | 
|  | it must **unlock** the mutex to allow other threads to use the resource. | 
|  |  | 
|  | Any number of threads may wait on a locked mutex simultaneously. | 
|  | When the mutex becomes unlocked it is then locked by the highest-priority | 
|  | thread that has waited the longest. | 
|  |  | 
|  | .. note:: | 
|  | Mutex objects are *not* designed for use by ISRs. | 
|  |  | 
|  | Reentrant Locking | 
|  | ================= | 
|  |  | 
|  | A thread is permitted to lock a mutex it has already locked. | 
|  | This allows the thread to access the associated resource at a point | 
|  | in its execution when the mutex may or may not already be locked. | 
|  |  | 
|  | A mutex that is repeatedly locked by a thread must be unlocked an equal number | 
|  | of times before the mutex becomes fully unlocked so it can be claimed | 
|  | by another thread. | 
|  |  | 
|  | Priority Inheritance | 
|  | ==================== | 
|  |  | 
|  | The thread that has locked a mutex is eligible for :dfn:`priority inheritance`. | 
|  | This means the kernel will *temporarily* elevate the thread's priority | 
|  | if a higher priority thread begins waiting on the mutex. This allows the owning | 
|  | thread to complete its work and release the mutex more rapidly by executing | 
|  | at the same priority as the waiting thread. Once the mutex has been unlocked, | 
|  | the unlocking thread resets its priority to the level it had before locking | 
|  | that mutex. | 
|  |  | 
|  | .. note:: | 
|  | The :kconfig:option:`CONFIG_PRIORITY_CEILING` configuration option limits | 
|  | how high the kernel can raise a thread's priority due to priority | 
|  | inheritance. The default value of 0 permits unlimited elevation. | 
|  |  | 
|  | The owning thread's base priority is saved in the mutex when it obtains the | 
|  | lock. Each time a higher priority thread waits on a mutex, the kernel adjusts | 
|  | the owning thread's priority. When the owning thread releases the lock (or if | 
|  | the high priority waiting thread times out), the kernel restores the thread's | 
|  | base priority from the value saved in the mutex. | 
|  |  | 
|  | This works well for priority inheritance as long as only one locked mutex is | 
|  | involved. However, if multiple mutexes are involved, sub-optimal behavior will | 
|  | be observed if the mutexes are not unlocked in the reverse order to which the | 
|  | owning thread's priority was previously raised. Consequently it is recommended | 
|  | that a thread lock only a single mutex at a time when multiple mutexes are | 
|  | shared between threads of different priorities. | 
|  |  | 
|  | Implementation | 
|  | ************** | 
|  |  | 
|  | Defining a Mutex | 
|  | ================ | 
|  |  | 
|  | A mutex is defined using a variable of type :c:struct:`k_mutex`. | 
|  | It must then be initialized by calling :c:func:`k_mutex_init`. | 
|  |  | 
|  | The following code defines and initializes a mutex. | 
|  |  | 
|  | .. code-block:: c | 
|  |  | 
|  | struct k_mutex my_mutex; | 
|  |  | 
|  | k_mutex_init(&my_mutex); | 
|  |  | 
|  | Alternatively, a mutex can be defined and initialized at compile time | 
|  | by calling :c:macro:`K_MUTEX_DEFINE`. | 
|  |  | 
|  | The following code has the same effect as the code segment above. | 
|  |  | 
|  | .. code-block:: c | 
|  |  | 
|  | K_MUTEX_DEFINE(my_mutex); | 
|  |  | 
|  | Locking a Mutex | 
|  | =============== | 
|  |  | 
|  | A mutex is locked by calling :c:func:`k_mutex_lock`. | 
|  |  | 
|  | The following code builds on the example above, and waits indefinitely | 
|  | for the mutex to become available if it is already locked by another thread. | 
|  |  | 
|  | .. code-block:: c | 
|  |  | 
|  | k_mutex_lock(&my_mutex, K_FOREVER); | 
|  |  | 
|  | The following code waits up to 100 milliseconds for the mutex to become | 
|  | available, and gives a warning if the mutex does not become available. | 
|  |  | 
|  | .. code-block:: c | 
|  |  | 
|  | if (k_mutex_lock(&my_mutex, K_MSEC(100)) == 0) { | 
|  | /* mutex successfully locked */ | 
|  | } else { | 
|  | printf("Cannot lock XYZ display\n"); | 
|  | } | 
|  |  | 
|  | Unlocking a Mutex | 
|  | ================= | 
|  |  | 
|  | A mutex is unlocked by calling :c:func:`k_mutex_unlock`. | 
|  |  | 
|  | The following code builds on the example above, | 
|  | and unlocks the mutex that was previously locked by the thread. | 
|  |  | 
|  | .. code-block:: c | 
|  |  | 
|  | k_mutex_unlock(&my_mutex); | 
|  |  | 
|  | Suggested Uses | 
|  | ************** | 
|  |  | 
|  | Use a mutex to provide exclusive access to a resource, such as a physical | 
|  | device. | 
|  |  | 
|  | Configuration Options | 
|  | ********************* | 
|  |  | 
|  | Related configuration options: | 
|  |  | 
|  | * :kconfig:option:`CONFIG_PRIORITY_CEILING` | 
|  |  | 
|  | API Reference | 
|  | ************* | 
|  |  | 
|  | .. doxygengroup:: mutex_apis | 
|  |  | 
|  | Futex API Reference | 
|  | ******************* | 
|  |  | 
|  | k_futex is a lightweight mutual exclusion primitive designed to minimize | 
|  | kernel involvement. Uncontended operation relies only on atomic access | 
|  | to shared memory. k_futex are tracked as kernel objects and can live in | 
|  | user memory so that any access bypasses the kernel object permission | 
|  | management mechanism. | 
|  |  | 
|  | .. doxygengroup:: futex_apis | 
|  |  | 
|  | User Mode Mutex API Reference | 
|  | ***************************** | 
|  |  | 
|  | sys_mutex behaves almost exactly like k_mutex, with the added advantage | 
|  | that a sys_mutex instance can reside in user memory. When user mode isn't | 
|  | enabled, sys_mutex behaves like k_mutex. | 
|  |  | 
|  | .. doxygengroup:: user_mutex_apis |