1# Mutex 2 3## Basic Concepts 4 5A mutual exclusion \(mutex\) is a special binary semaphore used for exclusive access to shared resources. 6 7A mutex can be unlocked or locked. When a mutex is held by a task, the mutex is locked and the task obtains the ownership of the mutex. When the task releases the mutex, the mutex is unlocked and the task will lose the ownership of the mutex. When a task holds a mutex, other tasks cannot unlock or hold the mutex. 8 9In an environment where multiple tasks compete for shared resources, the mutex can protect the shared resources via exclusive access. In addition, the mutex can prevent semaphore priority inversion, which occurs when a low-priority task holds a semaphore but a high-priority task has to wait until the low-priority task releases it. 10 11## Working Principles<a name="section115161649726"></a> 12 13In a multi-task environment, multiple tasks may access the same shared resources. However, certain shared resources are not shared, and can only be accessed exclusively by tasks. A mutex can be used to address this issue. 14 15When non-shared resources are accessed by a task, the mutex is locked. Other tasks will be blocked until the mutex is released by the task. The mutex allows only one task to access the shared resources at a time, ensuring integrity of operations on the shared resources. 16 17**Figure 1** Mutex working mechanism for mini systems 18 19 20## Available APIs 21 22**Table 1** APIs of the mutex module 23 24<a name="table37108292611"></a> 25<table><thead align="left"><tr id="row8711112919610"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.1"><p id="p3711102912617"><a name="p3711102912617"></a><a name="p3711102912617"></a>Function</p> 26</th> 27<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.2"><p id="p1671110293610"><a name="p1671110293610"></a><a name="p1671110293610"></a>API</p> 28</th> 29<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p87114292617"><a name="p87114292617"></a><a name="p87114292617"></a>Description</p> 30</th> 31</tr> 32</thead> 33<tbody><tr id="row37115291166"><td class="cellrowborder" rowspan="2" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p1795312108911"><a name="p1795312108911"></a><a name="p1795312108911"></a>Creating or deleting a mutex</p> 34</td> 35<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1671120293611"><a name="p1671120293611"></a><a name="p1671120293611"></a>LOS_MuxCreate</p> 36</td> 37<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p171112291967"><a name="p171112291967"></a><a name="p171112291967"></a>Creates a mutex.</p> 38</td> 39</tr> 40<tr id="row17711329268"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p071114291864"><a name="p071114291864"></a><a name="p071114291864"></a>LOS_MuxDelete</p> 41</td> 42<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p137111129965"><a name="p137111129965"></a><a name="p137111129965"></a>Deletes the specified mutex.</p> 43</td> 44</tr> 45<tr id="row5711192912616"><td class="cellrowborder" rowspan="2" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p86087143910"><a name="p86087143910"></a><a name="p86087143910"></a>Requesting or releasing a mutex</p> 46</td> 47<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1171112295614"><a name="p1171112295614"></a><a name="p1171112295614"></a>LOS_MuxPend</p> 48</td> 49<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1271110291969"><a name="p1271110291969"></a><a name="p1271110291969"></a>Requests the specified mutex.</p> 50</td> 51</tr> 52<tr id="row1571162918615"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p57111229967"><a name="p57111229967"></a><a name="p57111229967"></a>LOS_MuxPost</p> 53</td> 54<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p107118291660"><a name="p107118291660"></a><a name="p107118291660"></a>Releases the specified mutex.</p> 55</td> 56</tr> 57</tbody> 58</table> 59 60## How to Develop 61 62The typical mutex development process is as follows: 63 641. Call **LOS\_MuxCreate** to create a mutex. 652. Call **LOS\_MuxPend** to request a mutex. 66 67 The following modes are available: 68 69 - Non-block mode: A task acquires the mutex if the requested mutex is not held by any task or the task holding the mutex is the same as the task requesting the mutex. 70 - Permanent block mode: A task acquires the mutex if the requested mutex is not occupied. If the mutex is occupied, the task will be blocked and the task with the highest priority in the ready queue will be executed. The blocked task can be unlocked and executed only when the mutex is released. 71 - Scheduled block mode: A task acquires the mutex if the requested mutex is not occupied. If the mutex is occupied, the task will be blocked and the task with the highest priority in the ready queue will be executed. The blocked task can be executed only when the mutex is released within the specified timeout period or when the specified timeout period expires. 72 733. Call **LOS\_MuxPost** to release a mutex. 74 - If tasks are blocked by the specified mutex, the task with a higher priority will be unblocked when the mutex is released. The unblocked task changes to the Ready state and is scheduled. 75 - If no task is blocked by the specified mutex, the mutex is released successfully. 76 774. Call **LOS\_MuxDelete** to delete a mutex. 78 79> **NOTE**<br/> 80>- Two tasks cannot lock the same mutex. If a task attempts to lock a mutex held by another task, the task will be blocked until the mutex is unclocked. 81>- Mutexes cannot be used in the interrupt service program. 82>- When using the LiteOS-M kernel, OpenHarmony must ensure real-time task scheduling and avoid long-time task blocking. Therefore, a mutex must be released as soon as possible after use. 83>- When a mutex is held by a task, the task priority cannot be changed by using APIs such as **LOS\_TaskPriSet**. 84 85## Development Example 86 87### Example Description 88 89This example implements the following: 90 911. Create the **Example\_TaskEntry** task. In this task, create a mutex to lock task scheduling, and create two tasks **Example\_MutexTask1** \(with a lower priority\) and **Example\_MutexTask2** \(with a higher priority\) to unlock task scheduling. 922. When being scheduled, **Example\_MutexTask2** requests a mutex in permanent block mode. After acquiring the mutex, **Example\_MutexTask2** enters the sleep mode for 100 ticks. **Example\_MutexTask2** is suspended, and **Example\_MutexTask1** is woken up. 933. **Example\_MutexTask1** requests a mutex in scheduled block mode, and waits for 10 ticks. Because the mutex is still held by **Example\_MutexTask2**, **Example\_MutexTask1** is suspended. After 10 ticks, **Example\_MutexTask1** is woken up and attempts to request a mutex in permanent block mode. **Example\_MutexTask1** is suspended because the mutex is still held by **Example\_MutexTask2**. 944. After 100 ticks, **Example\_MutexTask2** is woken up and releases the mutex, and then **Example\_MutexTask1** is woken up. **Example\_MutexTask1** acquires the mutex and then releases the mutex. At last, the mutex is deleted. 95 96### Sample Code 97 98The sample code is as follows: 99 100``` 101#include <string.h> 102#include "los_mux.h" 103 104/* Mutex handler ID*/ 105UINT32 g_testMux; 106/* Task ID*/ 107UINT32 g_testTaskId01; 108UINT32 g_testTaskId02; 109 110VOID Example_MutexTask1(VOID) 111{ 112 UINT32 ret; 113 114 printf("task1 try to get mutex, wait 10 ticks.\n"); 115 /* Request a mutex. */ 116 ret = LOS_MuxPend(g_testMux, 10); 117 118 if (ret == LOS_OK) { 119 printf("task1 get mutex g_testMux.\n"); 120 /*Release the mutex. */ 121 LOS_MuxPost(g_testMux); 122 return; 123 } 124 if (ret == LOS_ERRNO_MUX_TIMEOUT ) { 125 printf("task1 timeout and try to get mutex, wait forever.\n"); 126 /* Request a mutex. */ 127 ret = LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); 128 if (ret == LOS_OK) { 129 printf("task1 wait forever, get mutex g_testMux.\n"); 130 /*Release the mutex. */ 131 LOS_MuxPost(g_testMux); 132 /* Delete the mutex. */ 133 LOS_MuxDelete(g_testMux); 134 printf("task1 post and delete mutex g_testMux.\n"); 135 return; 136 } 137 } 138 return; 139} 140 141VOID Example_MutexTask2(VOID) 142{ 143 printf("task2 try to get mutex, wait forever.\n"); 144 /* Request a mutex. */ 145 (VOID)LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); 146 147 printf("task2 get mutex g_testMux and suspend 100 ticks.\n"); 148 149 /* Enable the task to enter sleep mode for 100 ticks. */ 150 LOS_TaskDelay(100); 151 152 printf("task2 resumed and post the g_testMux\n"); 153 /* Release the mutex. */ 154 LOS_MuxPost(g_testMux); 155 return; 156} 157 158UINT32 Example_TaskEntry(VOID) 159{ 160 UINT32 ret; 161 TSK_INIT_PARAM_S task1; 162 TSK_INIT_PARAM_S task2; 163 164 /* Create a mutex. */ 165 LOS_MuxCreate(&g_testMux); 166 167 /* Lock task scheduling. */ 168 LOS_TaskLock(); 169 170 /* Create task 1. */ 171 memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); 172 task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask1; 173 task1.pcName = "MutexTsk1"; 174 task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 175 task1.usTaskPrio = 5; 176 ret = LOS_TaskCreate(&g_testTaskId01, &task1); 177 if (ret != LOS_OK) { 178 printf("task1 create failed.\n"); 179 return LOS_NOK; 180 } 181 182 /* Create task 2. */ 183 memset(&task2, 0, sizeof(TSK_INIT_PARAM_S)); 184 task2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask2; 185 task2.pcName = "MutexTsk2"; 186 task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 187 task2.usTaskPrio = 4; 188 ret = LOS_TaskCreate(&g_testTaskId02, &task2); 189 if (ret != LOS_OK) { 190 printf("task2 create failed.\n"); 191 return LOS_NOK; 192 } 193 194 /* Unlock task scheduling. */ 195 LOS_TaskUnlock(); 196 197 return LOS_OK; 198} 199``` 200 201### Verification 202 203The development is successful if the return result is as follows: 204 205``` 206task2 try to get mutex, wait forever. 207task2 get mutex g_testMux and suspend 100 ticks. 208task1 try to get mutex, wait 10 ticks. 209task1 timeout and try to get mutex, wait forever. 210task2 resumed and post the g_testMux 211task1 wait forever, get mutex g_testMux. 212task1 post and delete mutex g_testMux. 213``` 214 215