• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Mutex<a name="EN-US_TOPIC_0000001078912734"></a>
2
3-   [Basic Concepts](#section85865329185)
4-   [Working Principles](#section8547454201819)
5-   [Development Guidelines](#section2038861117194)
6    -   [Available APIs](#section11168318131917)
7    -   [How to Develop](#section4201191122116)
8    -   [Development Example](#section10679328202117)
9
10
11## Basic Concepts<a name="section85865329185"></a>
12
13A mutual exclusion \(mutex\) is a special binary semaphore used for exclusive access to shared resources. When a task holds the mutex, the task obtains the ownership of the mutex. When the task releases the mutex, the task will lose the ownership of the mutex. When a task holds a mutex, other tasks cannot hold the mutex. In an environment where multiple tasks compete for shared resources, the mutex can protect the shared resources via exclusive access.
14
15A mutex has three attributes: protocol attribute, priority upper limit attribute, and type attribute. The protocol attribute is used to handle a mutex requested by tasks of different priorities. The protocol attribute can be any of the following:
16
17-   LOS\_MUX\_PRIO\_NONE
18
19    Do not inherit or protect the priority of the task requesting the mutex.
20
21-   LOS\_MUX\_PRIO\_INHERIT
22
23    Inherits the priority of the task that requests the mutex. This is the default protocol attribute. When the mutex protocol attribute is set to this value: If a task with a higher priority is blocked because the mutex is already held by a task, the priority of the task holding the mutex will be copied to the priority bitmap of the task control block, and then set to be the same as that of the task of a higher priority. When the task holding the mutex releases the mutex, the task priority is restored to its original value.
24
25-   LOS\_MUX\_PRIO\_PROTECT
26
27    Protects the priority of the task that requests the mutex. When the mutex protocol attribute is set to this value: If the priority of the task that requests the mutex is lower than the upper limit of the mutex priority, the task priority will be backed up to the priority bitmap of the task control block, and then set to the upper limit value of the mutex priority. When the mutex is released, the task priority is restored to its original value.
28
29
30The type attribute of a mutex specifies whether to check for deadlocks and whether to support recursive holding of the mutex. The type attribute can be any of the following:
31
32-   LOS\_MUX\_NORMAL
33
34    Common mutex, which does not check for deadlocks. If a task repeatedly attempts to hold a mutex, the thread will be deadlocked. If the mutex type attribute is set to this value, a task cannot release a mutex held by another task or repeatedly release a mutex. Otherwise, unexpected results will be caused.
35
36-   LOS\_MUX\_RECURSIVE
37
38    Recursive mutex, which is the default attribute. If the type attribute of a mutex is set to this value, a task can hold the mutex for multiple times. Another task can hold this mutex only when the number of lock holding times is the same as the number of lock release times. However, any attempt to hold a mutex held by another task or attempt to release a mutex that has been released will cause an error code.
39
40-   LOS\_MUX\_ERRORCHECK
41
42    Allows automatic check for deadlocks. When a mutex is set to this type, an error code will be returned if a task attempts to repeatedly hold the mutex, attempts to release the mutex held by another task, or attempts to release the mutex that has been released.
43
44
45## Working Principles<a name="section8547454201819"></a>
46
47In a multi-task environment, multiple tasks may access the same shared resource. However, certain shared resources are not shared, and can only be accessed exclusively by tasks. A mutex can be used to address this issue.
48
49When 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.
50
51**Figure  1**  Mutex working mechanism<a name="fig16821181173811"></a>
52![](figure/mutex-working-mechanism-23.png "mutex-working-mechanism-23")
53
54## Development Guidelines<a name="section2038861117194"></a>
55
56### Available APIs<a name="section11168318131917"></a>
57
58**Table  1**  Mutex module APIs
59
60<a name="table37108292611"></a>
61<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>Category</p>
62</th>
63<th class="cellrowborder" valign="top" width="33.31333133313331%" id="mcps1.2.4.1.2"><p id="p1671110293610"><a name="p1671110293610"></a><a name="p1671110293610"></a>API</p>
64</th>
65<th class="cellrowborder" valign="top" width="33.35333533353336%" id="mcps1.2.4.1.3"><p id="p87114292617"><a name="p87114292617"></a><a name="p87114292617"></a>Description</p>
66</th>
67</tr>
68</thead>
69<tbody><tr id="row332716281313"><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>Initializing or destroying a mutex</p>
70</td>
71<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p1932716285312"><a name="p1932716285312"></a><a name="p1932716285312"></a>LOS_MuxInit</p>
72</td>
73<td class="cellrowborder" valign="top" width="33.35333533353336%" headers="mcps1.2.4.1.3 "><p id="p932762812319"><a name="p932762812319"></a><a name="p932762812319"></a>Initializes a mutex.</p>
74</td>
75</tr>
76<tr id="row37115291166"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p127613211335"><a name="p127613211335"></a><a name="p127613211335"></a>LOS_MuxDestroy</p>
77</td>
78<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p137111129965"><a name="p137111129965"></a><a name="p137111129965"></a>Destroys the specified mutex.</p>
79</td>
80</tr>
81<tr id="row17711329268"><td class="cellrowborder" rowspan="3" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p18125182815396"><a name="p18125182815396"></a><a name="p18125182815396"></a>Requesting or releasing a mutex</p>
82</td>
83<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p215615953415"><a name="p215615953415"></a><a name="p215615953415"></a>LOS_MuxLock</p>
84</td>
85<td class="cellrowborder" valign="top" width="33.35333533353336%" headers="mcps1.2.4.1.3 "><p id="p20994162353515"><a name="p20994162353515"></a><a name="p20994162353515"></a>Requests the specified mutex.</p>
86</td>
87</tr>
88<tr id="row5711192912616"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p7974187183520"><a name="p7974187183520"></a><a name="p7974187183520"></a>LOS_MuxTrylock</p>
89</td>
90<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1271110291969"><a name="p1271110291969"></a><a name="p1271110291969"></a>Attempts to request the specified mutex without blocking.</p>
91</td>
92</tr>
93<tr id="row1571162918615"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p13021319143515"><a name="p13021319143515"></a><a name="p13021319143515"></a>LOS_MuxUnlock</p>
94</td>
95<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>
96</td>
97</tr>
98<tr id="row344193024114"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p16441730114110"><a name="p16441730114110"></a><a name="p16441730114110"></a>Verifying a mutex</p>
99</td>
100<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p1544183074110"><a name="p1544183074110"></a><a name="p1544183074110"></a>LOS_MuxIsValid</p>
101</td>
102<td class="cellrowborder" valign="top" width="33.35333533353336%" headers="mcps1.2.4.1.3 "><p id="p3441193017416"><a name="p3441193017416"></a><a name="p3441193017416"></a>Checks whether the mutex release is valid.</p>
103</td>
104</tr>
105<tr id="row1065116418421"><td class="cellrowborder" rowspan="2" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p2189182734211"><a name="p2189182734211"></a><a name="p2189182734211"></a>Initializing or destroying mutex attributes</p>
106</td>
107<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p1565244144210"><a name="p1565244144210"></a><a name="p1565244144210"></a>LOS_MuxAttrInit</p>
108</td>
109<td class="cellrowborder" valign="top" width="33.35333533353336%" headers="mcps1.2.4.1.3 "><p id="p14652342426"><a name="p14652342426"></a><a name="p14652342426"></a>Initializes mutex attributes.</p>
110</td>
111</tr>
112<tr id="row538718619427"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p538756104217"><a name="p538756104217"></a><a name="p538756104217"></a>LOS_MuxAttrDestroy</p>
113</td>
114<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p23875654210"><a name="p23875654210"></a><a name="p23875654210"></a>Destroys the specified mutex attributes.</p>
115</td>
116</tr>
117<tr id="row8143848467"><td class="cellrowborder" rowspan="8" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p2926915154717"><a name="p2926915154717"></a><a name="p2926915154717"></a>Setting and obtaining mutex attributes</p>
118</td>
119<td class="cellrowborder" valign="top" width="33.31333133313331%" headers="mcps1.2.4.1.2 "><p id="p171441842465"><a name="p171441842465"></a><a name="p171441842465"></a>LOS_MuxAttrGetType</p>
120</td>
121<td class="cellrowborder" valign="top" width="33.35333533353336%" headers="mcps1.2.4.1.3 "><p id="p151444418461"><a name="p151444418461"></a><a name="p151444418461"></a>Obtains the type attribute of a specified mutex.</p>
122</td>
123</tr>
124<tr id="row99314413464"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p793218404613"><a name="p793218404613"></a><a name="p793218404613"></a>LOS_MuxAttrSetType</p>
125</td>
126<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p51371843194813"><a name="p51371843194813"></a><a name="p51371843194813"></a>Sets the type attribute of a specified mutex.</p>
127</td>
128</tr>
129<tr id="row204470514615"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p13447115154614"><a name="p13447115154614"></a><a name="p13447115154614"></a>LOS_MuxAttrGetProtocol</p>
130</td>
131<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p20871044144720"><a name="p20871044144720"></a><a name="p20871044144720"></a>Obtains the protocol attribute of a specified mutex.</p>
132</td>
133</tr>
134<tr id="row69051358465"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p10906165124617"><a name="p10906165124617"></a><a name="p10906165124617"></a>LOS_MuxAttrSetProtocol</p>
135</td>
136<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1690617554610"><a name="p1690617554610"></a><a name="p1690617554610"></a>Sets the protocol attribute of a specified mutex.</p>
137</td>
138</tr>
139<tr id="row133571666467"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p6357146154616"><a name="p6357146154616"></a><a name="p6357146154616"></a>LOS_MuxAttrGetPrioceiling</p>
140</td>
141<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p559511469478"><a name="p559511469478"></a><a name="p559511469478"></a>Obtains the priority upper limit attribute of a specified mutex.</p>
142</td>
143</tr>
144<tr id="row5789065465"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1778916634614"><a name="p1778916634614"></a><a name="p1778916634614"></a>LOS_MuxAttrSetPrioceiling</p>
145</td>
146<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p16789126134614"><a name="p16789126134614"></a><a name="p16789126134614"></a>Sets the priority upper limit attribute of a specified mutex.</p>
147</td>
148</tr>
149<tr id="row10251772469"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p199321752124718"><a name="p199321752124718"></a><a name="p199321752124718"></a>LOS_MuxGetPrioceiling</p>
150</td>
151<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1128349114718"><a name="p1128349114718"></a><a name="p1128349114718"></a>Obtains the mutex priority upper limit attribute.</p>
152</td>
153</tr>
154<tr id="row197256714468"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p72518754614"><a name="p72518754614"></a><a name="p72518754614"></a>LOS_MuxSetPrioceiling</p>
155</td>
156<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p177254713460"><a name="p177254713460"></a><a name="p177254713460"></a>Sets the mutex priority upper limit attribute.</p>
157</td>
158</tr>
159</tbody>
160</table>
161
162### How to Develop<a name="section4201191122116"></a>
163
164The typical mutex development process is as follows:
165
1661. Call  **LOS\_MuxInit**  to initialize a mutex.
167
1682. Call  **LOS\_MuxLock**  to request a mutex.
169
170The following modes are available:
171
172-   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.
173-   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.
174-   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.
175
1763. Call  **LOS\_MuxUnlock**  to release a mutex.
177
178-   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.
179-   If no task is blocked by the specified mutex, the mutex is released successfully.
180
1814. Call  **LOS\_MuxDestroy**  to destroy a mutex.
182
183>![](../public_sys-resources/icon-note.gif) **NOTE:**
184>-   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 unlocked.
185>-   Mutexes cannot be used in the interrupt service program.
186>-   When using the LiteOS-A kernel, the 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.
187
188### Development Example<a name="section10679328202117"></a>
189
190Example Description
191
192This example implements the following:
193
1941.  Create a mutex in the  **Example\_TaskEntry**  task, and lock task scheduling. Create two tasks  **Example\_MutexTask1**  and  **Example\_MutexTask2**. and unlock task scheduling.
1952.  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.
1963.  **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**.
1974.  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.
198
199**Sample Code**
200
201The sample code is as follows:
202
203```
204#include <string.h>
205#include "los_mux.h"
206
207/* Mutex */
208LosMux g_testMux;
209/* Task ID*/
210UINT32 g_testTaskId01;
211UINT32 g_testTaskId02;
212
213VOID Example_MutexTask1(VOID)
214{
215    UINT32 ret;
216
217    printf("task1 try to get mutex, wait 10 ticks.\n");
218    /* Request a mutex.*/
219    ret = LOS_MuxLock(&g_testMux, 10);
220
221    if (ret == LOS_OK) {
222        printf("task1 get mutex g_testMux.\n");
223         /* Release the mutex.*/
224        LOS_MuxUnlock(&g_testMux);
225        return;
226    }
227    if (ret == LOS_ETIMEDOUT ) {
228            printf("task1 timeout and try to get mutex, wait forever.\n");
229            /* Request a mutex.*/
230            ret = LOS_MuxLock(&g_testMux, LOS_WAIT_FOREVER);
231            if (ret == LOS_OK) {
232                printf("task1 wait forever, get mutex g_testMux.\n");
233                /*Release the mutex.*/
234                LOS_MuxUnlock(&g_testMux);
235                /* Delete the mutex. */
236                LOS_MuxDestroy(&g_testMux);
237                printf("task1 post and delete mutex g_testMux.\n");
238                return;
239            }
240    }
241    return;
242}
243
244VOID Example_MutexTask2(VOID)
245{
246    printf("task2 try to get mutex, wait forever.\n");
247    /* Request a mutex.*/
248    (VOID)LOS_MuxLock(&g_testMux, LOS_WAIT_FOREVER);
249
250    printf("task2 get mutex g_testMux and suspend 100 ticks.\n");
251
252     /* Enable the task to enter sleep mode for 100 ticks.*/
253    LOS_TaskDelay(100);
254
255    printf("task2 resumed and post the g_testMux\n");
256    /* Release the mutex.*/
257    LOS_MuxUnlock(&g_testMux);
258    return;
259}
260
261UINT32 Example_MutexEntry(VOID)
262{
263    UINT32 ret;
264    TSK_INIT_PARAM_S task1;
265    TSK_INIT_PARAM_S task2;
266
267    /* Initializes the mutex./
268    LOS_MuxInit(&g_testMux, NULL);
269
270    /* Lock task scheduling.*/
271    LOS_TaskLock();
272
273    /* Create task 1.*/
274    memset(&task1, 0, sizeof(TSK_INIT_PARAM_S));
275    task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask1;
276    task1.pcName       = "MutexTsk1";
277    task1.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
278    task1.usTaskPrio   = 5;
279    ret = LOS_TaskCreate(&g_testTaskId01, &task1);
280    if (ret != LOS_OK) {
281        printf("task1 create failed.\n");
282        return LOS_NOK;
283    }
284
285    /* Create task 2.*/
286    memset(&task2, 0, sizeof(TSK_INIT_PARAM_S));
287    task2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask2;
288    task2.pcName       = "MutexTsk2";
289    task2.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
290    task2.usTaskPrio   = 4;
291    ret = LOS_TaskCreate(&g_testTaskId02, &task2);
292    if (ret != LOS_OK) {
293        printf("task2 create failed.\n");
294        return LOS_NOK;
295    }
296
297    /* Unlock task scheduling.*/
298    LOS_TaskUnlock();
299
300    return LOS_OK;
301}
302```
303
304**Verification**
305
306The development is successful if the return result is as follows:
307
308```
309task1 try to get mutex, wait 10 ticks.
310task2 try to get mutex, wait forever.
311task2 get mutex g_testMux and suspend 100 ticks.
312task1 timeout and try to get mutex, wait forever.
313task2 resumed and post the g_testMux
314task1 wait forever, get mutex g_testMux.
315task1 post and delete mutex g_testMux.
316```
317
318