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 42LITE_OS_SEC_BSS LosMuxCB* g_allMux = NULL; 43LITE_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 *****************************************************************************/ 52LITE_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 *****************************************************************************/ 88LITE_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; 118ERR_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 *****************************************************************************/ 129LITE_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; 161ERR_HANDLER: 162 OS_RETURN_ERROR_P2(errLine, errNo); 163} 164 165STATIC_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 *****************************************************************************/ 195LITE_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 255HOOK: 256 OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout); 257 return LOS_OK; 258 259ERROR_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 *****************************************************************************/ 271LITE_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