• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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