1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "los_mux.h"
33 #include "los_config.h"
34 #include "los_debug.h"
35 #include "los_hook.h"
36 #include "los_interrupt.h"
37 #include "los_memory.h"
38 #include "los_sched.h"
39
40 #if (LOSCFG_BASE_IPC_MUX == 1)
41
42 LITE_OS_SEC_BSS LosMuxCB* g_allMux = NULL;
43 LITE_OS_SEC_DATA_INIT LOS_DL_LIST g_unusedMuxList;
44
45 /*****************************************************************************
46 Function : OsMuxInit
47 Description : Initializes the mutex
48 Input : None
49 Output : None
50 Return : LOS_OK on success, or error code on failure
51 *****************************************************************************/
OsMuxInit(VOID)52 LITE_OS_SEC_TEXT_INIT UINT32 OsMuxInit(VOID)
53 {
54 LosMuxCB *muxNode = NULL;
55 UINT32 index;
56
57 LOS_ListInit(&g_unusedMuxList);
58
59 if (LOSCFG_BASE_IPC_MUX_LIMIT == 0) {
60 return LOS_ERRNO_MUX_MAXNUM_ZERO;
61 }
62
63 g_allMux = (LosMuxCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_MUX_LIMIT * sizeof(LosMuxCB)));
64 if (g_allMux == NULL) {
65 return LOS_ERRNO_MUX_NO_MEMORY;
66 }
67
68 for (index = 0; index < LOSCFG_BASE_IPC_MUX_LIMIT; index++) {
69 muxNode = ((LosMuxCB *)g_allMux) + index;
70 muxNode->muxID = index;
71 muxNode->owner = (LosTaskCB *)NULL;
72 muxNode->muxStat = OS_MUX_UNUSED;
73 #if (LOSCFG_MUTEX_CREATE_TRACE == 1)
74 muxNode->createInfo = 0;
75 #endif
76 LOS_ListTailInsert(&g_unusedMuxList, &muxNode->muxList);
77 }
78 return LOS_OK;
79 }
80
81 /*****************************************************************************
82 Function : LOS_MuxCreate
83 Description : Create a mutex
84 Input : None
85 Output : muxHandle ------ Mutex operation handle
86 Return : LOS_OK on success, or error code on failure
87 *****************************************************************************/
LOS_MuxCreate(UINT32 * muxHandle)88 LITE_OS_SEC_TEXT_INIT UINT32 LOS_MuxCreate(UINT32 *muxHandle)
89 {
90 UINT32 intSave;
91 LosMuxCB *muxCreated = NULL;
92 LOS_DL_LIST *unusedMux = NULL;
93 UINT32 errNo;
94 UINT32 errLine;
95
96 if (muxHandle == NULL) {
97 return LOS_ERRNO_MUX_PTR_NULL;
98 }
99
100 intSave = LOS_IntLock();
101 if (LOS_ListEmpty(&g_unusedMuxList)) {
102 LOS_IntRestore(intSave);
103 OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_ALL_BUSY);
104 }
105
106 unusedMux = LOS_DL_LIST_FIRST(&(g_unusedMuxList));
107 LOS_ListDelete(unusedMux);
108 muxCreated = (GET_MUX_LIST(unusedMux));
109 muxCreated->muxCount = 0;
110 muxCreated->muxStat = OS_MUX_USED;
111 muxCreated->priority = 0;
112 muxCreated->owner = (LosTaskCB *)NULL;
113 LOS_ListInit(&muxCreated->muxList);
114 *muxHandle = (UINT32)muxCreated->muxID;
115 LOS_IntRestore(intSave);
116 OsHookCall(LOS_HOOK_TYPE_MUX_CREATE, muxCreated);
117 return LOS_OK;
118 ERR_HANDLER:
119 OS_RETURN_ERROR_P2(errLine, errNo);
120 }
121
122 /*****************************************************************************
123 Function : LOS_MuxDelete
124 Description : Delete a mutex
125 Input : muxHandle ------Mutex operation handle
126 Output : None
127 Return : LOS_OK on success, or error code on failure
128 *****************************************************************************/
LOS_MuxDelete(UINT32 muxHandle)129 LITE_OS_SEC_TEXT_INIT UINT32 LOS_MuxDelete(UINT32 muxHandle)
130 {
131 UINT32 intSave;
132 LosMuxCB *muxDeleted = NULL;
133 UINT32 errNo;
134 UINT32 errLine;
135
136 if (muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) {
137 OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_INVALID);
138 }
139
140 muxDeleted = GET_MUX(muxHandle);
141 intSave = LOS_IntLock();
142 if (muxDeleted->muxStat == OS_MUX_UNUSED) {
143 LOS_IntRestore(intSave);
144 OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_INVALID);
145 }
146
147 if ((!LOS_ListEmpty(&muxDeleted->muxList)) || muxDeleted->muxCount) {
148 LOS_IntRestore(intSave);
149 OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_PENDED);
150 }
151
152 LOS_ListAdd(&g_unusedMuxList, &muxDeleted->muxList);
153 muxDeleted->muxStat = OS_MUX_UNUSED;
154 #if (LOSCFG_MUTEX_CREATE_TRACE == 1)
155 muxDeleted->createInfo = 0;
156 #endif
157 LOS_IntRestore(intSave);
158
159 OsHookCall(LOS_HOOK_TYPE_MUX_DELETE, muxDeleted);
160 return LOS_OK;
161 ERR_HANDLER:
162 OS_RETURN_ERROR_P2(errLine, errNo);
163 }
164
OsMuxValidCheck(LosMuxCB * muxPended)165 STATIC_INLINE UINT32 OsMuxValidCheck(LosMuxCB *muxPended)
166 {
167 if (muxPended->muxStat == OS_MUX_UNUSED) {
168 return LOS_ERRNO_MUX_INVALID;
169 }
170
171 if (OS_INT_ACTIVE) {
172 return LOS_ERRNO_MUX_IN_INTERR;
173 }
174
175 if (g_losTaskLock) {
176 PRINT_ERR("!!!LOS_ERRNO_MUX_PEND_IN_LOCK!!!\n");
177 return LOS_ERRNO_MUX_PEND_IN_LOCK;
178 }
179
180 if (g_losTask.runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
181 return LOS_ERRNO_MUX_PEND_IN_SYSTEM_TASK;
182 }
183
184 return LOS_OK;
185 }
186
187 /*****************************************************************************
188 Function : LOS_MuxPend
189 Description : Specify the mutex P operation
190 Input : muxHandle ------ Mutex operation handleone
191 : timeOut ------- waiting time
192 Output : None
193 Return : LOS_OK on success, or error code on failure
194 *****************************************************************************/
LOS_MuxPend(UINT32 muxHandle,UINT32 timeout)195 LITE_OS_SEC_TEXT UINT32 LOS_MuxPend(UINT32 muxHandle, UINT32 timeout)
196 {
197 UINT32 intSave;
198 LosMuxCB *muxPended = NULL;
199 UINT32 retErr;
200 LosTaskCB *runningTask = NULL;
201
202 if (muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) {
203 OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
204 }
205
206 muxPended = GET_MUX(muxHandle);
207 intSave = LOS_IntLock();
208 retErr = OsMuxValidCheck(muxPended);
209 if (retErr) {
210 goto ERROR_MUX_PEND;
211 }
212
213 runningTask = (LosTaskCB *)g_losTask.runTask;
214 if (muxPended->muxCount == 0) {
215 muxPended->muxCount++;
216 muxPended->owner = runningTask;
217 muxPended->priority = runningTask->priority;
218 LOS_IntRestore(intSave);
219 goto HOOK;
220 }
221
222 if (muxPended->owner == runningTask) {
223 muxPended->muxCount++;
224 LOS_IntRestore(intSave);
225 goto HOOK;
226 }
227
228 if (!timeout) {
229 retErr = LOS_ERRNO_MUX_UNAVAILABLE;
230 goto ERROR_MUX_PEND;
231 }
232
233 runningTask->taskMux = (VOID *)muxPended;
234
235 if (muxPended->owner->priority > runningTask->priority) {
236 (VOID)OsSchedModifyTaskSchedParam(muxPended->owner, runningTask->priority);
237 }
238
239 OsSchedTaskWait(&muxPended->muxList, timeout);
240
241 LOS_IntRestore(intSave);
242 OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout);
243 LOS_Schedule();
244
245 intSave = LOS_IntLock();
246 if (runningTask->taskStatus & OS_TASK_STATUS_TIMEOUT) {
247 runningTask->taskStatus &= (~OS_TASK_STATUS_TIMEOUT);
248 retErr = LOS_ERRNO_MUX_TIMEOUT;
249 goto ERROR_MUX_PEND;
250 }
251
252 LOS_IntRestore(intSave);
253 return LOS_OK;
254
255 HOOK:
256 OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout);
257 return LOS_OK;
258
259 ERROR_MUX_PEND:
260 LOS_IntRestore(intSave);
261 OS_RETURN_ERROR(retErr);
262 }
263
264 /*****************************************************************************
265 Function : LOS_MuxPost
266 Description : Specify the mutex V operation,
267 Input : muxHandle ------ Mutex operation handle
268 Output : None
269 Return : LOS_OK on success, or error code on failure
270 *****************************************************************************/
LOS_MuxPost(UINT32 muxHandle)271 LITE_OS_SEC_TEXT UINT32 LOS_MuxPost(UINT32 muxHandle)
272 {
273 UINT32 intSave;
274 LosMuxCB *muxPosted = GET_MUX(muxHandle);
275 LosTaskCB *resumedTask = NULL;
276 LosTaskCB *runningTask = NULL;
277
278 intSave = LOS_IntLock();
279
280 if ((muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) ||
281 (muxPosted->muxStat == OS_MUX_UNUSED)) {
282 LOS_IntRestore(intSave);
283 OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
284 }
285
286 if (OS_INT_ACTIVE) {
287 LOS_IntRestore(intSave);
288 OS_RETURN_ERROR(LOS_ERRNO_MUX_IN_INTERR);
289 }
290
291 runningTask = (LosTaskCB *)g_losTask.runTask;
292 if ((muxPosted->muxCount == 0) || (muxPosted->owner != runningTask)) {
293 LOS_IntRestore(intSave);
294 OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
295 }
296
297 if (--(muxPosted->muxCount) != 0) {
298 LOS_IntRestore(intSave);
299 OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted);
300 return LOS_OK;
301 }
302
303 if ((muxPosted->owner->priority) != muxPosted->priority) {
304 (VOID)OsSchedModifyTaskSchedParam(muxPosted->owner, muxPosted->priority);
305 }
306
307 if (!LOS_ListEmpty(&muxPosted->muxList)) {
308 resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(muxPosted->muxList)));
309
310 muxPosted->muxCount = 1;
311 muxPosted->owner = resumedTask;
312 muxPosted->priority = resumedTask->priority;
313 resumedTask->taskMux = NULL;
314
315 OsSchedTaskWake(resumedTask);
316
317 LOS_IntRestore(intSave);
318 OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted);
319 LOS_Schedule();
320 } else {
321 muxPosted->owner = NULL;
322 LOS_IntRestore(intSave);
323 }
324
325 return LOS_OK;
326 }
327
328 #endif /* (LOSCFG_BASE_IPC_MUX == 1) */
329