• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![](figures/mutex-working-mechanism-for-mini-systems.png "mutex-working-mechanism-for-mini-systems")
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>![](../public_sys-resources/icon-note.gif) **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