10d163575Sopenharmony_ci/*
20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
30d163575Sopenharmony_ci * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
40d163575Sopenharmony_ci *
50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
60d163575Sopenharmony_ci * are permitted provided that the following conditions are met:
70d163575Sopenharmony_ci *
80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
90d163575Sopenharmony_ci *    conditions and the following disclaimer.
100d163575Sopenharmony_ci *
110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
120d163575Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
130d163575Sopenharmony_ci *    provided with the distribution.
140d163575Sopenharmony_ci *
150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
160d163575Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
170d163575Sopenharmony_ci *    permission.
180d163575Sopenharmony_ci *
190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
300d163575Sopenharmony_ci */
310d163575Sopenharmony_ci
320d163575Sopenharmony_ci#include "los_mux_pri.h"
330d163575Sopenharmony_ci#include "los_bitmap.h"
340d163575Sopenharmony_ci#include "los_spinlock.h"
350d163575Sopenharmony_ci#include "los_mp.h"
360d163575Sopenharmony_ci#include "los_task_pri.h"
370d163575Sopenharmony_ci#include "los_exc.h"
380d163575Sopenharmony_ci#include "los_sched_pri.h"
390d163575Sopenharmony_ci
400d163575Sopenharmony_ci
410d163575Sopenharmony_ci#ifdef LOSCFG_BASE_IPC_MUX
420d163575Sopenharmony_ci#define MUTEXATTR_TYPE_MASK 0x0FU
430d163575Sopenharmony_ci
440d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxAttrInit(LosMuxAttr *attr)
450d163575Sopenharmony_ci{
460d163575Sopenharmony_ci    if (attr == NULL) {
470d163575Sopenharmony_ci        return LOS_EINVAL;
480d163575Sopenharmony_ci    }
490d163575Sopenharmony_ci
500d163575Sopenharmony_ci    attr->protocol    = LOS_MUX_PRIO_INHERIT;
510d163575Sopenharmony_ci    attr->prioceiling = OS_TASK_PRIORITY_LOWEST;
520d163575Sopenharmony_ci    attr->type        = LOS_MUX_DEFAULT;
530d163575Sopenharmony_ci    return LOS_OK;
540d163575Sopenharmony_ci}
550d163575Sopenharmony_ci
560d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxAttrDestroy(LosMuxAttr *attr)
570d163575Sopenharmony_ci{
580d163575Sopenharmony_ci    if (attr == NULL) {
590d163575Sopenharmony_ci        return LOS_EINVAL;
600d163575Sopenharmony_ci    }
610d163575Sopenharmony_ci
620d163575Sopenharmony_ci    return LOS_OK;
630d163575Sopenharmony_ci}
640d163575Sopenharmony_ci
650d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetType(const LosMuxAttr *attr, INT32 *outType)
660d163575Sopenharmony_ci{
670d163575Sopenharmony_ci    INT32 type;
680d163575Sopenharmony_ci
690d163575Sopenharmony_ci    if ((attr == NULL) || (outType == NULL)) {
700d163575Sopenharmony_ci        return LOS_EINVAL;
710d163575Sopenharmony_ci    }
720d163575Sopenharmony_ci
730d163575Sopenharmony_ci    type = (INT32)(attr->type & MUTEXATTR_TYPE_MASK);
740d163575Sopenharmony_ci    if ((type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
750d163575Sopenharmony_ci        return LOS_EINVAL;
760d163575Sopenharmony_ci    }
770d163575Sopenharmony_ci
780d163575Sopenharmony_ci    *outType = type;
790d163575Sopenharmony_ci
800d163575Sopenharmony_ci    return LOS_OK;
810d163575Sopenharmony_ci}
820d163575Sopenharmony_ci
830d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetType(LosMuxAttr *attr, INT32 type)
840d163575Sopenharmony_ci{
850d163575Sopenharmony_ci    if ((attr == NULL) || (type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
860d163575Sopenharmony_ci        return LOS_EINVAL;
870d163575Sopenharmony_ci    }
880d163575Sopenharmony_ci
890d163575Sopenharmony_ci    attr->type = (UINT8)((attr->type & ~MUTEXATTR_TYPE_MASK) | (UINT32)type);
900d163575Sopenharmony_ci    return LOS_OK;
910d163575Sopenharmony_ci}
920d163575Sopenharmony_ci
930d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetProtocol(const LosMuxAttr *attr, INT32 *protocol)
940d163575Sopenharmony_ci{
950d163575Sopenharmony_ci    if ((attr != NULL) && (protocol != NULL)) {
960d163575Sopenharmony_ci        *protocol = attr->protocol;
970d163575Sopenharmony_ci    } else {
980d163575Sopenharmony_ci        return LOS_EINVAL;
990d163575Sopenharmony_ci    }
1000d163575Sopenharmony_ci
1010d163575Sopenharmony_ci    return LOS_OK;
1020d163575Sopenharmony_ci}
1030d163575Sopenharmony_ci
1040d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetProtocol(LosMuxAttr *attr, INT32 protocol)
1050d163575Sopenharmony_ci{
1060d163575Sopenharmony_ci    if (attr == NULL) {
1070d163575Sopenharmony_ci        return LOS_EINVAL;
1080d163575Sopenharmony_ci    }
1090d163575Sopenharmony_ci
1100d163575Sopenharmony_ci    switch (protocol) {
1110d163575Sopenharmony_ci        case LOS_MUX_PRIO_NONE:
1120d163575Sopenharmony_ci        case LOS_MUX_PRIO_INHERIT:
1130d163575Sopenharmony_ci        case LOS_MUX_PRIO_PROTECT:
1140d163575Sopenharmony_ci            attr->protocol = (UINT8)protocol;
1150d163575Sopenharmony_ci            return LOS_OK;
1160d163575Sopenharmony_ci        default:
1170d163575Sopenharmony_ci            return LOS_EINVAL;
1180d163575Sopenharmony_ci    }
1190d163575Sopenharmony_ci}
1200d163575Sopenharmony_ci
1210d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetPrioceiling(const LosMuxAttr *attr, INT32 *prioceiling)
1220d163575Sopenharmony_ci{
1230d163575Sopenharmony_ci    if (attr == NULL) {
1240d163575Sopenharmony_ci        return LOS_EINVAL;
1250d163575Sopenharmony_ci    }
1260d163575Sopenharmony_ci
1270d163575Sopenharmony_ci    if (prioceiling != NULL) {
1280d163575Sopenharmony_ci        *prioceiling = attr->prioceiling;
1290d163575Sopenharmony_ci    }
1300d163575Sopenharmony_ci
1310d163575Sopenharmony_ci    return LOS_OK;
1320d163575Sopenharmony_ci}
1330d163575Sopenharmony_ci
1340d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetPrioceiling(LosMuxAttr *attr, INT32 prioceiling)
1350d163575Sopenharmony_ci{
1360d163575Sopenharmony_ci    if ((attr == NULL) ||
1370d163575Sopenharmony_ci        (prioceiling < OS_TASK_PRIORITY_HIGHEST) ||
1380d163575Sopenharmony_ci        (prioceiling > OS_TASK_PRIORITY_LOWEST)) {
1390d163575Sopenharmony_ci        return LOS_EINVAL;
1400d163575Sopenharmony_ci    }
1410d163575Sopenharmony_ci
1420d163575Sopenharmony_ci    attr->prioceiling = (UINT8)prioceiling;
1430d163575Sopenharmony_ci
1440d163575Sopenharmony_ci    return LOS_OK;
1450d163575Sopenharmony_ci}
1460d163575Sopenharmony_ci
1470d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxSetPrioceiling(LosMux *mutex, INT32 prioceiling, INT32 *oldPrioceiling)
1480d163575Sopenharmony_ci{
1490d163575Sopenharmony_ci    INT32 ret;
1500d163575Sopenharmony_ci    INT32 retLock;
1510d163575Sopenharmony_ci    if ((mutex == NULL) ||
1520d163575Sopenharmony_ci        (prioceiling < OS_TASK_PRIORITY_HIGHEST) ||
1530d163575Sopenharmony_ci        (prioceiling > OS_TASK_PRIORITY_LOWEST)) {
1540d163575Sopenharmony_ci        return LOS_EINVAL;
1550d163575Sopenharmony_ci    }
1560d163575Sopenharmony_ci
1570d163575Sopenharmony_ci    retLock = LOS_MuxLock(mutex, LOS_WAIT_FOREVER);
1580d163575Sopenharmony_ci    if (retLock != LOS_OK) {
1590d163575Sopenharmony_ci        return retLock;
1600d163575Sopenharmony_ci    }
1610d163575Sopenharmony_ci
1620d163575Sopenharmony_ci    if (oldPrioceiling != NULL) {
1630d163575Sopenharmony_ci        *oldPrioceiling = mutex->attr.prioceiling;
1640d163575Sopenharmony_ci    }
1650d163575Sopenharmony_ci
1660d163575Sopenharmony_ci    ret = LOS_MuxAttrSetPrioceiling(&mutex->attr, prioceiling);
1670d163575Sopenharmony_ci
1680d163575Sopenharmony_ci    retLock = LOS_MuxUnlock(mutex);
1690d163575Sopenharmony_ci    if ((ret == LOS_OK) && (retLock != LOS_OK)) {
1700d163575Sopenharmony_ci        return retLock;
1710d163575Sopenharmony_ci    }
1720d163575Sopenharmony_ci
1730d163575Sopenharmony_ci    return ret;
1740d163575Sopenharmony_ci}
1750d163575Sopenharmony_ci
1760d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxGetPrioceiling(const LosMux *mutex, INT32 *prioceiling)
1770d163575Sopenharmony_ci{
1780d163575Sopenharmony_ci    if ((mutex != NULL) && (prioceiling != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
1790d163575Sopenharmony_ci        *prioceiling = mutex->attr.prioceiling;
1800d163575Sopenharmony_ci        return LOS_OK;
1810d163575Sopenharmony_ci    }
1820d163575Sopenharmony_ci
1830d163575Sopenharmony_ci    return LOS_EINVAL;
1840d163575Sopenharmony_ci}
1850d163575Sopenharmony_ci
1860d163575Sopenharmony_ciLITE_OS_SEC_TEXT BOOL LOS_MuxIsValid(const LosMux *mutex)
1870d163575Sopenharmony_ci{
1880d163575Sopenharmony_ci    if ((mutex != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
1890d163575Sopenharmony_ci        return TRUE;
1900d163575Sopenharmony_ci    }
1910d163575Sopenharmony_ci
1920d163575Sopenharmony_ci    return FALSE;
1930d163575Sopenharmony_ci}
1940d163575Sopenharmony_ci
1950d163575Sopenharmony_ciSTATIC UINT32 OsCheckMutexAttr(const LosMuxAttr *attr)
1960d163575Sopenharmony_ci{
1970d163575Sopenharmony_ci    if (((INT8)(attr->type) < LOS_MUX_NORMAL) || (attr->type > LOS_MUX_ERRORCHECK)) {
1980d163575Sopenharmony_ci        return LOS_NOK;
1990d163575Sopenharmony_ci    }
2000d163575Sopenharmony_ci    if (((INT8)(attr->prioceiling) < OS_TASK_PRIORITY_HIGHEST) || (attr->prioceiling > OS_TASK_PRIORITY_LOWEST)) {
2010d163575Sopenharmony_ci        return LOS_NOK;
2020d163575Sopenharmony_ci    }
2030d163575Sopenharmony_ci    if (((INT8)(attr->protocol) < LOS_MUX_PRIO_NONE) || (attr->protocol > LOS_MUX_PRIO_PROTECT)) {
2040d163575Sopenharmony_ci        return LOS_NOK;
2050d163575Sopenharmony_ci    }
2060d163575Sopenharmony_ci    return LOS_OK;
2070d163575Sopenharmony_ci}
2080d163575Sopenharmony_ci
2090d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
2100d163575Sopenharmony_ci{
2110d163575Sopenharmony_ci    UINT32 intSave;
2120d163575Sopenharmony_ci
2130d163575Sopenharmony_ci    if (mutex == NULL) {
2140d163575Sopenharmony_ci        return LOS_EINVAL;
2150d163575Sopenharmony_ci    }
2160d163575Sopenharmony_ci
2170d163575Sopenharmony_ci    if (attr == NULL) {
2180d163575Sopenharmony_ci        (VOID)LOS_MuxAttrInit(&mutex->attr);
2190d163575Sopenharmony_ci    } else {
2200d163575Sopenharmony_ci        (VOID)memcpy_s(&mutex->attr, sizeof(LosMuxAttr), attr, sizeof(LosMuxAttr));
2210d163575Sopenharmony_ci    }
2220d163575Sopenharmony_ci
2230d163575Sopenharmony_ci    if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
2240d163575Sopenharmony_ci        return LOS_EINVAL;
2250d163575Sopenharmony_ci    }
2260d163575Sopenharmony_ci
2270d163575Sopenharmony_ci    SCHEDULER_LOCK(intSave);
2280d163575Sopenharmony_ci    mutex->muxCount = 0;
2290d163575Sopenharmony_ci    mutex->owner = NULL;
2300d163575Sopenharmony_ci    LOS_ListInit(&mutex->muxList);
2310d163575Sopenharmony_ci    mutex->magic = OS_MUX_MAGIC;
2320d163575Sopenharmony_ci    SCHEDULER_UNLOCK(intSave);
2330d163575Sopenharmony_ci    return LOS_OK;
2340d163575Sopenharmony_ci}
2350d163575Sopenharmony_ci
2360d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
2370d163575Sopenharmony_ci{
2380d163575Sopenharmony_ci    UINT32 intSave;
2390d163575Sopenharmony_ci
2400d163575Sopenharmony_ci    if (mutex == NULL) {
2410d163575Sopenharmony_ci        return LOS_EINVAL;
2420d163575Sopenharmony_ci    }
2430d163575Sopenharmony_ci
2440d163575Sopenharmony_ci    SCHEDULER_LOCK(intSave);
2450d163575Sopenharmony_ci    if (mutex->magic != OS_MUX_MAGIC) {
2460d163575Sopenharmony_ci        SCHEDULER_UNLOCK(intSave);
2470d163575Sopenharmony_ci        return LOS_EBADF;
2480d163575Sopenharmony_ci    }
2490d163575Sopenharmony_ci
2500d163575Sopenharmony_ci    if (mutex->muxCount != 0) {
2510d163575Sopenharmony_ci        SCHEDULER_UNLOCK(intSave);
2520d163575Sopenharmony_ci        return LOS_EBUSY;
2530d163575Sopenharmony_ci    }
2540d163575Sopenharmony_ci
2550d163575Sopenharmony_ci    (VOID)memset_s(mutex, sizeof(LosMux), 0, sizeof(LosMux));
2560d163575Sopenharmony_ci    SCHEDULER_UNLOCK(intSave);
2570d163575Sopenharmony_ci    return LOS_OK;
2580d163575Sopenharmony_ci}
2590d163575Sopenharmony_ci
2600d163575Sopenharmony_ciSTATIC VOID OsMuxBitmapSet(const LosMux *mutex, const LosTaskCB *runTask)
2610d163575Sopenharmony_ci{
2620d163575Sopenharmony_ci    if (mutex->attr.protocol != LOS_MUX_PRIO_INHERIT) {
2630d163575Sopenharmony_ci        return;
2640d163575Sopenharmony_ci    }
2650d163575Sopenharmony_ci
2660d163575Sopenharmony_ci    SchedParam param = { 0 };
2670d163575Sopenharmony_ci    LosTaskCB *owner = (LosTaskCB *)mutex->owner;
2680d163575Sopenharmony_ci    INT32 ret = OsSchedParamCompare(owner, runTask);
2690d163575Sopenharmony_ci    if (ret > 0) {
2700d163575Sopenharmony_ci        runTask->ops->schedParamGet(runTask, &param);
2710d163575Sopenharmony_ci        owner->ops->priorityInheritance(owner, &param);
2720d163575Sopenharmony_ci    }
2730d163575Sopenharmony_ci}
2740d163575Sopenharmony_ci
2750d163575Sopenharmony_ciVOID OsMuxBitmapRestore(const LosMux *mutex, const LOS_DL_LIST *list, const LosTaskCB *runTask)
2760d163575Sopenharmony_ci{
2770d163575Sopenharmony_ci    if (mutex->attr.protocol != LOS_MUX_PRIO_INHERIT) {
2780d163575Sopenharmony_ci        return;
2790d163575Sopenharmony_ci    }
2800d163575Sopenharmony_ci
2810d163575Sopenharmony_ci    SchedParam param = { 0 };
2820d163575Sopenharmony_ci    LosTaskCB *owner = (LosTaskCB *)mutex->owner;
2830d163575Sopenharmony_ci    runTask->ops->schedParamGet(runTask, &param);
2840d163575Sopenharmony_ci    owner->ops->priorityRestore(owner, list, &param);
2850d163575Sopenharmony_ci}
2860d163575Sopenharmony_ci
2870d163575Sopenharmony_ciSTATIC UINT32 OsMuxPendOp(LosTaskCB *runTask, LosMux *mutex, UINT32 timeout)
2880d163575Sopenharmony_ci{
2890d163575Sopenharmony_ci    UINT32 ret;
2900d163575Sopenharmony_ci
2910d163575Sopenharmony_ci    if ((mutex->muxList.pstPrev == NULL) || (mutex->muxList.pstNext == NULL)) {
2920d163575Sopenharmony_ci        /* This is for mutex macro initialization. */
2930d163575Sopenharmony_ci        mutex->muxCount = 0;
2940d163575Sopenharmony_ci        mutex->owner = NULL;
2950d163575Sopenharmony_ci        LOS_ListInit(&mutex->muxList);
2960d163575Sopenharmony_ci    }
2970d163575Sopenharmony_ci
2980d163575Sopenharmony_ci    if (mutex->muxCount == 0) {
2990d163575Sopenharmony_ci        mutex->muxCount++;
3000d163575Sopenharmony_ci        mutex->owner = (VOID *)runTask;
3010d163575Sopenharmony_ci        LOS_ListTailInsert(&runTask->lockList, &mutex->holdList);
3020d163575Sopenharmony_ci        if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {
3030d163575Sopenharmony_ci            SchedParam param = { 0 };
3040d163575Sopenharmony_ci            runTask->ops->schedParamGet(runTask, &param);
3050d163575Sopenharmony_ci            param.priority = mutex->attr.prioceiling;
3060d163575Sopenharmony_ci            runTask->ops->priorityInheritance(runTask, &param);
3070d163575Sopenharmony_ci        }
3080d163575Sopenharmony_ci        return LOS_OK;
3090d163575Sopenharmony_ci    }
3100d163575Sopenharmony_ci
3110d163575Sopenharmony_ci    if (((LosTaskCB *)mutex->owner == runTask) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {
3120d163575Sopenharmony_ci        mutex->muxCount++;
3130d163575Sopenharmony_ci        return LOS_OK;
3140d163575Sopenharmony_ci    }
3150d163575Sopenharmony_ci
3160d163575Sopenharmony_ci    if (!timeout) {
3170d163575Sopenharmony_ci        return LOS_EINVAL;
3180d163575Sopenharmony_ci    }
3190d163575Sopenharmony_ci
3200d163575Sopenharmony_ci    if (!OsPreemptableInSched()) {
3210d163575Sopenharmony_ci        return LOS_EDEADLK;
3220d163575Sopenharmony_ci    }
3230d163575Sopenharmony_ci
3240d163575Sopenharmony_ci    OsMuxBitmapSet(mutex, runTask);
3250d163575Sopenharmony_ci
3260d163575Sopenharmony_ci    runTask->taskMux = (VOID *)mutex;
3270d163575Sopenharmony_ci    LOS_DL_LIST *node = OsSchedLockPendFindPos(runTask, &mutex->muxList);
3280d163575Sopenharmony_ci    if (node == NULL) {
3290d163575Sopenharmony_ci        ret = LOS_NOK;
3300d163575Sopenharmony_ci        return ret;
3310d163575Sopenharmony_ci    }
3320d163575Sopenharmony_ci
3330d163575Sopenharmony_ci    OsTaskWaitSetPendMask(OS_TASK_WAIT_MUTEX, (UINTPTR)mutex, timeout);
3340d163575Sopenharmony_ci    ret = runTask->ops->wait(runTask, node, timeout);
3350d163575Sopenharmony_ci    if (ret == LOS_ERRNO_TSK_TIMEOUT) {
3360d163575Sopenharmony_ci        OsMuxBitmapRestore(mutex, NULL, runTask);
3370d163575Sopenharmony_ci        runTask->taskMux = NULL;
3380d163575Sopenharmony_ci        ret = LOS_ETIMEDOUT;
3390d163575Sopenharmony_ci    }
3400d163575Sopenharmony_ci
3410d163575Sopenharmony_ci    return ret;
3420d163575Sopenharmony_ci}
3430d163575Sopenharmony_ci
3440d163575Sopenharmony_ciUINT32 OsMuxLockUnsafe(LosMux *mutex, UINT32 timeout)
3450d163575Sopenharmony_ci{
3460d163575Sopenharmony_ci    LosTaskCB *runTask = OsCurrTaskGet();
3470d163575Sopenharmony_ci
3480d163575Sopenharmony_ci    if (mutex->magic != OS_MUX_MAGIC) {
3490d163575Sopenharmony_ci        return LOS_EBADF;
3500d163575Sopenharmony_ci    }
3510d163575Sopenharmony_ci
3520d163575Sopenharmony_ci    if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
3530d163575Sopenharmony_ci        return LOS_EINVAL;
3540d163575Sopenharmony_ci    }
3550d163575Sopenharmony_ci
3560d163575Sopenharmony_ci    if ((mutex->attr.type == LOS_MUX_ERRORCHECK) && (mutex->owner == (VOID *)runTask)) {
3570d163575Sopenharmony_ci        return LOS_EDEADLK;
3580d163575Sopenharmony_ci    }
3590d163575Sopenharmony_ci
3600d163575Sopenharmony_ci    return OsMuxPendOp(runTask, mutex, timeout);
3610d163575Sopenharmony_ci}
3620d163575Sopenharmony_ci
3630d163575Sopenharmony_ciUINT32 OsMuxTrylockUnsafe(LosMux *mutex, UINT32 timeout)
3640d163575Sopenharmony_ci{
3650d163575Sopenharmony_ci    LosTaskCB *runTask = OsCurrTaskGet();
3660d163575Sopenharmony_ci
3670d163575Sopenharmony_ci    if (mutex->magic != OS_MUX_MAGIC) {
3680d163575Sopenharmony_ci        return LOS_EBADF;
3690d163575Sopenharmony_ci    }
3700d163575Sopenharmony_ci
3710d163575Sopenharmony_ci    if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
3720d163575Sopenharmony_ci        return LOS_EINVAL;
3730d163575Sopenharmony_ci    }
3740d163575Sopenharmony_ci
3750d163575Sopenharmony_ci    if ((mutex->owner != NULL) &&
3760d163575Sopenharmony_ci        (((LosTaskCB *)mutex->owner != runTask) || (mutex->attr.type != LOS_MUX_RECURSIVE))) {
3770d163575Sopenharmony_ci        return LOS_EBUSY;
3780d163575Sopenharmony_ci    }
3790d163575Sopenharmony_ci
3800d163575Sopenharmony_ci    return OsMuxPendOp(runTask, mutex, timeout);
3810d163575Sopenharmony_ci}
3820d163575Sopenharmony_ci
3830d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxLock(LosMux *mutex, UINT32 timeout)
3840d163575Sopenharmony_ci{
3850d163575Sopenharmony_ci    LosTaskCB *runTask = NULL;
3860d163575Sopenharmony_ci    UINT32 intSave;
3870d163575Sopenharmony_ci    UINT32 ret;
3880d163575Sopenharmony_ci
3890d163575Sopenharmony_ci    if (mutex == NULL) {
3900d163575Sopenharmony_ci        return LOS_EINVAL;
3910d163575Sopenharmony_ci    }
3920d163575Sopenharmony_ci
3930d163575Sopenharmony_ci    if (OS_INT_ACTIVE) {
3940d163575Sopenharmony_ci        return LOS_EINTR;
3950d163575Sopenharmony_ci    }
3960d163575Sopenharmony_ci
3970d163575Sopenharmony_ci    runTask = (LosTaskCB *)OsCurrTaskGet();
3980d163575Sopenharmony_ci    /* DO NOT Call blocking API in system tasks */
3990d163575Sopenharmony_ci    if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
4000d163575Sopenharmony_ci        PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
4010d163575Sopenharmony_ci        OsBackTrace();
4020d163575Sopenharmony_ci    }
4030d163575Sopenharmony_ci
4040d163575Sopenharmony_ci    SCHEDULER_LOCK(intSave);
4050d163575Sopenharmony_ci    ret = OsMuxLockUnsafe(mutex, timeout);
4060d163575Sopenharmony_ci    SCHEDULER_UNLOCK(intSave);
4070d163575Sopenharmony_ci    return ret;
4080d163575Sopenharmony_ci}
4090d163575Sopenharmony_ci
4100d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxTrylock(LosMux *mutex)
4110d163575Sopenharmony_ci{
4120d163575Sopenharmony_ci    LosTaskCB *runTask = NULL;
4130d163575Sopenharmony_ci    UINT32 intSave;
4140d163575Sopenharmony_ci    UINT32 ret;
4150d163575Sopenharmony_ci
4160d163575Sopenharmony_ci    if (mutex == NULL) {
4170d163575Sopenharmony_ci        return LOS_EINVAL;
4180d163575Sopenharmony_ci    }
4190d163575Sopenharmony_ci
4200d163575Sopenharmony_ci    if (OS_INT_ACTIVE) {
4210d163575Sopenharmony_ci        return LOS_EINTR;
4220d163575Sopenharmony_ci    }
4230d163575Sopenharmony_ci
4240d163575Sopenharmony_ci    runTask = (LosTaskCB *)OsCurrTaskGet();
4250d163575Sopenharmony_ci    /* DO NOT Call blocking API in system tasks */
4260d163575Sopenharmony_ci    if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
4270d163575Sopenharmony_ci        PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
4280d163575Sopenharmony_ci        OsBackTrace();
4290d163575Sopenharmony_ci    }
4300d163575Sopenharmony_ci
4310d163575Sopenharmony_ci    SCHEDULER_LOCK(intSave);
4320d163575Sopenharmony_ci    ret = OsMuxTrylockUnsafe(mutex, 0);
4330d163575Sopenharmony_ci    SCHEDULER_UNLOCK(intSave);
4340d163575Sopenharmony_ci    return ret;
4350d163575Sopenharmony_ci}
4360d163575Sopenharmony_ci
4370d163575Sopenharmony_ciSTATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
4380d163575Sopenharmony_ci{
4390d163575Sopenharmony_ci    if (LOS_ListEmpty(&mutex->muxList)) {
4400d163575Sopenharmony_ci        LOS_ListDelete(&mutex->holdList);
4410d163575Sopenharmony_ci        mutex->owner = NULL;
4420d163575Sopenharmony_ci        return LOS_OK;
4430d163575Sopenharmony_ci    }
4440d163575Sopenharmony_ci
4450d163575Sopenharmony_ci    LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(mutex->muxList)));
4460d163575Sopenharmony_ci    OsMuxBitmapRestore(mutex, &mutex->muxList, resumedTask);
4470d163575Sopenharmony_ci
4480d163575Sopenharmony_ci    mutex->muxCount = 1;
4490d163575Sopenharmony_ci    mutex->owner = (VOID *)resumedTask;
4500d163575Sopenharmony_ci    LOS_ListDelete(&mutex->holdList);
4510d163575Sopenharmony_ci    LOS_ListTailInsert(&resumedTask->lockList, &mutex->holdList);
4520d163575Sopenharmony_ci    OsTaskWakeClearPendMask(resumedTask);
4530d163575Sopenharmony_ci    resumedTask->ops->wake(resumedTask);
4540d163575Sopenharmony_ci    resumedTask->taskMux = NULL;
4550d163575Sopenharmony_ci    if (needSched != NULL) {
4560d163575Sopenharmony_ci        *needSched = TRUE;
4570d163575Sopenharmony_ci    }
4580d163575Sopenharmony_ci
4590d163575Sopenharmony_ci    return LOS_OK;
4600d163575Sopenharmony_ci}
4610d163575Sopenharmony_ci
4620d163575Sopenharmony_ciUINT32 OsMuxUnlockUnsafe(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
4630d163575Sopenharmony_ci{
4640d163575Sopenharmony_ci    if (mutex->magic != OS_MUX_MAGIC) {
4650d163575Sopenharmony_ci        return LOS_EBADF;
4660d163575Sopenharmony_ci    }
4670d163575Sopenharmony_ci
4680d163575Sopenharmony_ci    if (OsCheckMutexAttr(&mutex->attr) != LOS_OK) {
4690d163575Sopenharmony_ci        return LOS_EINVAL;
4700d163575Sopenharmony_ci    }
4710d163575Sopenharmony_ci
4720d163575Sopenharmony_ci    if ((LosTaskCB *)mutex->owner != taskCB) {
4730d163575Sopenharmony_ci        return LOS_EPERM;
4740d163575Sopenharmony_ci    }
4750d163575Sopenharmony_ci
4760d163575Sopenharmony_ci    if (mutex->muxCount == 0) {
4770d163575Sopenharmony_ci        return LOS_EPERM;
4780d163575Sopenharmony_ci    }
4790d163575Sopenharmony_ci
4800d163575Sopenharmony_ci    if ((--mutex->muxCount != 0) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {
4810d163575Sopenharmony_ci        return LOS_OK;
4820d163575Sopenharmony_ci    }
4830d163575Sopenharmony_ci
4840d163575Sopenharmony_ci    if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {
4850d163575Sopenharmony_ci        SchedParam param = { 0 };
4860d163575Sopenharmony_ci        taskCB->ops->schedParamGet(taskCB, &param);
4870d163575Sopenharmony_ci        taskCB->ops->priorityRestore(taskCB, NULL, &param);
4880d163575Sopenharmony_ci    }
4890d163575Sopenharmony_ci
4900d163575Sopenharmony_ci    /* Whether a task block the mutex lock. */
4910d163575Sopenharmony_ci    return OsMuxPostOp(taskCB, mutex, needSched);
4920d163575Sopenharmony_ci}
4930d163575Sopenharmony_ci
4940d163575Sopenharmony_ciLITE_OS_SEC_TEXT UINT32 LOS_MuxUnlock(LosMux *mutex)
4950d163575Sopenharmony_ci{
4960d163575Sopenharmony_ci    LosTaskCB *runTask = NULL;
4970d163575Sopenharmony_ci    BOOL needSched = FALSE;
4980d163575Sopenharmony_ci    UINT32 intSave;
4990d163575Sopenharmony_ci    UINT32 ret;
5000d163575Sopenharmony_ci
5010d163575Sopenharmony_ci    if (mutex == NULL) {
5020d163575Sopenharmony_ci        return LOS_EINVAL;
5030d163575Sopenharmony_ci    }
5040d163575Sopenharmony_ci
5050d163575Sopenharmony_ci    if (OS_INT_ACTIVE) {
5060d163575Sopenharmony_ci        return LOS_EINTR;
5070d163575Sopenharmony_ci    }
5080d163575Sopenharmony_ci
5090d163575Sopenharmony_ci    runTask = (LosTaskCB *)OsCurrTaskGet();
5100d163575Sopenharmony_ci    /* DO NOT Call blocking API in system tasks */
5110d163575Sopenharmony_ci    if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
5120d163575Sopenharmony_ci        PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
5130d163575Sopenharmony_ci        OsBackTrace();
5140d163575Sopenharmony_ci    }
5150d163575Sopenharmony_ci
5160d163575Sopenharmony_ci    SCHEDULER_LOCK(intSave);
5170d163575Sopenharmony_ci    ret = OsMuxUnlockUnsafe(runTask, mutex, &needSched);
5180d163575Sopenharmony_ci    SCHEDULER_UNLOCK(intSave);
5190d163575Sopenharmony_ci    if (needSched == TRUE) {
5200d163575Sopenharmony_ci        LOS_MpSchedule(OS_MP_CPU_ALL);
5210d163575Sopenharmony_ci        LOS_Schedule();
5220d163575Sopenharmony_ci    }
5230d163575Sopenharmony_ci    return ret;
5240d163575Sopenharmony_ci}
5250d163575Sopenharmony_ci
5260d163575Sopenharmony_ci#endif /* LOSCFG_BASE_IPC_MUX */
5270d163575Sopenharmony_ci
528