13d8536b4Sopenharmony_ci/*
23d8536b4Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
33d8536b4Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
43d8536b4Sopenharmony_ci *
53d8536b4Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
63d8536b4Sopenharmony_ci * are permitted provided that the following conditions are met:
73d8536b4Sopenharmony_ci *
83d8536b4Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
93d8536b4Sopenharmony_ci *    conditions and the following disclaimer.
103d8536b4Sopenharmony_ci *
113d8536b4Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
123d8536b4Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
133d8536b4Sopenharmony_ci *    provided with the distribution.
143d8536b4Sopenharmony_ci *
153d8536b4Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
163d8536b4Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
173d8536b4Sopenharmony_ci *    permission.
183d8536b4Sopenharmony_ci *
193d8536b4Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
203d8536b4Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
213d8536b4Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223d8536b4Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
233d8536b4Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
243d8536b4Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
253d8536b4Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
263d8536b4Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
273d8536b4Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
283d8536b4Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
293d8536b4Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
303d8536b4Sopenharmony_ci */
313d8536b4Sopenharmony_ci
323d8536b4Sopenharmony_ci#include <pthread.h>
333d8536b4Sopenharmony_ci#include <time.h>
343d8536b4Sopenharmony_ci#include <securec.h>
353d8536b4Sopenharmony_ci#include "los_compiler.h"
363d8536b4Sopenharmony_ci#include "los_mux.h"
373d8536b4Sopenharmony_ci#include "errno.h"
383d8536b4Sopenharmony_ci#include "los_debug.h"
393d8536b4Sopenharmony_ci#include "los_hook.h"
403d8536b4Sopenharmony_ci#include "los_sched.h"
413d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
423d8536b4Sopenharmony_ci#include "los_arch.h"
433d8536b4Sopenharmony_ci#endif
443d8536b4Sopenharmony_ci
453d8536b4Sopenharmony_ci#define MUTEXATTR_TYPE_MASK   0x0FU
463d8536b4Sopenharmony_ci#define OS_SYS_NS_PER_MSECOND 1000000
473d8536b4Sopenharmony_ci#define OS_SYS_NS_PER_SECOND  1000000000
483d8536b4Sopenharmony_ci
493d8536b4Sopenharmony_cistatic inline int MapError(UINT32 err)
503d8536b4Sopenharmony_ci{
513d8536b4Sopenharmony_ci    switch (err) {
523d8536b4Sopenharmony_ci        case LOS_OK:
533d8536b4Sopenharmony_ci            return 0;
543d8536b4Sopenharmony_ci        case LOS_ERRNO_MUX_IN_INTERR:
553d8536b4Sopenharmony_ci            return EPERM;
563d8536b4Sopenharmony_ci        case LOS_ERRNO_MUX_PEND_IN_LOCK:
573d8536b4Sopenharmony_ci            return EDEADLK;
583d8536b4Sopenharmony_ci        case LOS_ERRNO_MUX_PENDED:
593d8536b4Sopenharmony_ci        case LOS_ERRNO_MUX_UNAVAILABLE:
603d8536b4Sopenharmony_ci            return EBUSY;
613d8536b4Sopenharmony_ci        case LOS_ERRNO_MUX_TIMEOUT:
623d8536b4Sopenharmony_ci            return ETIMEDOUT;
633d8536b4Sopenharmony_ci        case LOS_ERRNO_MUX_ALL_BUSY:
643d8536b4Sopenharmony_ci            return EAGAIN;
653d8536b4Sopenharmony_ci        case LOS_ERRNO_MUX_INVALID:
663d8536b4Sopenharmony_ci        default:
673d8536b4Sopenharmony_ci            return EINVAL;
683d8536b4Sopenharmony_ci    }
693d8536b4Sopenharmony_ci}
703d8536b4Sopenharmony_ci
713d8536b4Sopenharmony_ciint pthread_mutexattr_init(pthread_mutexattr_t *mutexAttr)
723d8536b4Sopenharmony_ci{
733d8536b4Sopenharmony_ci    if (mutexAttr == NULL) {
743d8536b4Sopenharmony_ci        return EINVAL;
753d8536b4Sopenharmony_ci    }
763d8536b4Sopenharmony_ci
773d8536b4Sopenharmony_ci    mutexAttr->type = PTHREAD_MUTEX_DEFAULT;
783d8536b4Sopenharmony_ci
793d8536b4Sopenharmony_ci    return 0;
803d8536b4Sopenharmony_ci}
813d8536b4Sopenharmony_ci
823d8536b4Sopenharmony_ciint pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *outType)
833d8536b4Sopenharmony_ci{
843d8536b4Sopenharmony_ci    INT32 type;
853d8536b4Sopenharmony_ci
863d8536b4Sopenharmony_ci    if ((attr == NULL) || (outType == NULL)) {
873d8536b4Sopenharmony_ci        return EINVAL;
883d8536b4Sopenharmony_ci    }
893d8536b4Sopenharmony_ci
903d8536b4Sopenharmony_ci    type = (INT32)(attr->type & MUTEXATTR_TYPE_MASK);
913d8536b4Sopenharmony_ci    if ((type != PTHREAD_MUTEX_NORMAL) &&
923d8536b4Sopenharmony_ci        (type != PTHREAD_MUTEX_RECURSIVE) &&
933d8536b4Sopenharmony_ci        (type != PTHREAD_MUTEX_ERRORCHECK)) {
943d8536b4Sopenharmony_ci        return EINVAL;
953d8536b4Sopenharmony_ci    }
963d8536b4Sopenharmony_ci
973d8536b4Sopenharmony_ci    *outType = type;
983d8536b4Sopenharmony_ci
993d8536b4Sopenharmony_ci    return 0;
1003d8536b4Sopenharmony_ci}
1013d8536b4Sopenharmony_ci
1023d8536b4Sopenharmony_ciint pthread_mutexattr_settype(pthread_mutexattr_t *mutexAttr, int type)
1033d8536b4Sopenharmony_ci{
1043d8536b4Sopenharmony_ci    if (mutexAttr == NULL) {
1053d8536b4Sopenharmony_ci        return EINVAL;
1063d8536b4Sopenharmony_ci    }
1073d8536b4Sopenharmony_ci
1083d8536b4Sopenharmony_ci    if (((unsigned)type != PTHREAD_MUTEX_NORMAL) &&
1093d8536b4Sopenharmony_ci        ((unsigned)type != PTHREAD_MUTEX_RECURSIVE) &&
1103d8536b4Sopenharmony_ci        ((unsigned)type != PTHREAD_MUTEX_ERRORCHECK)) {
1113d8536b4Sopenharmony_ci        return EINVAL;
1123d8536b4Sopenharmony_ci    }
1133d8536b4Sopenharmony_ci    mutexAttr->type = (UINT8)((mutexAttr->type & ~MUTEXATTR_TYPE_MASK) | (UINT32)type);
1143d8536b4Sopenharmony_ci
1153d8536b4Sopenharmony_ci    return 0;
1163d8536b4Sopenharmony_ci}
1173d8536b4Sopenharmony_ci
1183d8536b4Sopenharmony_ciint pthread_mutexattr_destroy(pthread_mutexattr_t *mutexAttr)
1193d8536b4Sopenharmony_ci{
1203d8536b4Sopenharmony_ci    if (mutexAttr == NULL) {
1213d8536b4Sopenharmony_ci        return EINVAL;
1223d8536b4Sopenharmony_ci    }
1233d8536b4Sopenharmony_ci
1243d8536b4Sopenharmony_ci    (VOID)memset_s(mutexAttr, sizeof(pthread_mutexattr_t), 0, sizeof(pthread_mutexattr_t));
1253d8536b4Sopenharmony_ci
1263d8536b4Sopenharmony_ci    return 0;
1273d8536b4Sopenharmony_ci}
1283d8536b4Sopenharmony_ci
1293d8536b4Sopenharmony_ci/* Initialize mutex. If mutexAttr is NULL, use default attributes. */
1303d8536b4Sopenharmony_ciint pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexAttr)
1313d8536b4Sopenharmony_ci{
1323d8536b4Sopenharmony_ci    pthread_mutexattr_t useAttr;
1333d8536b4Sopenharmony_ci    UINT32 muxHandle;
1343d8536b4Sopenharmony_ci    UINT32 ret;
1353d8536b4Sopenharmony_ci
1363d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
1373d8536b4Sopenharmony_ci    UINTPTR regLR = ArchLRGet();
1383d8536b4Sopenharmony_ci#endif
1393d8536b4Sopenharmony_ci
1403d8536b4Sopenharmony_ci    if (mutex == NULL) {
1413d8536b4Sopenharmony_ci        return EINVAL;
1423d8536b4Sopenharmony_ci    }
1433d8536b4Sopenharmony_ci
1443d8536b4Sopenharmony_ci    if (mutexAttr == NULL) {
1453d8536b4Sopenharmony_ci        (VOID)pthread_mutexattr_init(&useAttr);
1463d8536b4Sopenharmony_ci    } else {
1473d8536b4Sopenharmony_ci        useAttr = *mutexAttr;
1483d8536b4Sopenharmony_ci    }
1493d8536b4Sopenharmony_ci
1503d8536b4Sopenharmony_ci    ret = LOS_MuxCreate(&muxHandle);
1513d8536b4Sopenharmony_ci    if (ret != LOS_OK) {
1523d8536b4Sopenharmony_ci        return MapError(ret);
1533d8536b4Sopenharmony_ci    }
1543d8536b4Sopenharmony_ci
1553d8536b4Sopenharmony_ci    mutex->stAttr = useAttr;
1563d8536b4Sopenharmony_ci    mutex->magic = _MUX_MAGIC;
1573d8536b4Sopenharmony_ci    mutex->handle = muxHandle;
1583d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
1593d8536b4Sopenharmony_ci    OsSetMutexCreateInfo(GET_MUX(mutex->handle), regLR);
1603d8536b4Sopenharmony_ci#endif
1613d8536b4Sopenharmony_ci
1623d8536b4Sopenharmony_ci    return 0;
1633d8536b4Sopenharmony_ci}
1643d8536b4Sopenharmony_ci
1653d8536b4Sopenharmony_ciint pthread_mutex_destroy(pthread_mutex_t *mutex)
1663d8536b4Sopenharmony_ci{
1673d8536b4Sopenharmony_ci    UINT32 ret;
1683d8536b4Sopenharmony_ci    if ((mutex == NULL) || (mutex->magic != _MUX_MAGIC)) {
1693d8536b4Sopenharmony_ci        return EINVAL;
1703d8536b4Sopenharmony_ci    }
1713d8536b4Sopenharmony_ci    ret = LOS_MuxDelete(mutex->handle);
1723d8536b4Sopenharmony_ci    if (ret != LOS_OK) {
1733d8536b4Sopenharmony_ci        return MapError(ret);
1743d8536b4Sopenharmony_ci    }
1753d8536b4Sopenharmony_ci    mutex->handle = _MUX_INVALID_HANDLE;
1763d8536b4Sopenharmony_ci    mutex->magic = 0;
1773d8536b4Sopenharmony_ci
1783d8536b4Sopenharmony_ci    return 0;
1793d8536b4Sopenharmony_ci}
1803d8536b4Sopenharmony_ci
1813d8536b4Sopenharmony_ciSTATIC UINT32 CheckMutexAttr(const pthread_mutexattr_t *attr)
1823d8536b4Sopenharmony_ci{
1833d8536b4Sopenharmony_ci    if ((attr->type != PTHREAD_MUTEX_NORMAL) &&
1843d8536b4Sopenharmony_ci        (attr->type != PTHREAD_MUTEX_RECURSIVE) &&
1853d8536b4Sopenharmony_ci        (attr->type != PTHREAD_MUTEX_ERRORCHECK)) {
1863d8536b4Sopenharmony_ci        return LOS_NOK;
1873d8536b4Sopenharmony_ci    }
1883d8536b4Sopenharmony_ci
1893d8536b4Sopenharmony_ci    return LOS_OK;
1903d8536b4Sopenharmony_ci}
1913d8536b4Sopenharmony_ci
1923d8536b4Sopenharmony_ciSTATIC UINT32 MuxPreCheck(const pthread_mutex_t *mutex, const LosTaskCB *runTask)
1933d8536b4Sopenharmony_ci{
1943d8536b4Sopenharmony_ci    if ((mutex == NULL) || (mutex->magic != _MUX_MAGIC) ||
1953d8536b4Sopenharmony_ci        ((mutex->handle != _MUX_INVALID_HANDLE) && (mutex->handle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT))) {
1963d8536b4Sopenharmony_ci        return EINVAL;
1973d8536b4Sopenharmony_ci    }
1983d8536b4Sopenharmony_ci
1993d8536b4Sopenharmony_ci    if (OS_INT_ACTIVE) {
2003d8536b4Sopenharmony_ci        return EPERM;
2013d8536b4Sopenharmony_ci    }
2023d8536b4Sopenharmony_ci    /* DO NOT recommend to use blocking API in system tasks */
2033d8536b4Sopenharmony_ci    if ((runTask != NULL) && (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK)) {
2043d8536b4Sopenharmony_ci        PRINT_DEBUG("Warning: DO NOT recommend to use %s in system tasks.\n", __FUNCTION__);
2053d8536b4Sopenharmony_ci    }
2063d8536b4Sopenharmony_ci
2073d8536b4Sopenharmony_ci    if (CheckMutexAttr(&mutex->stAttr) != LOS_OK) {
2083d8536b4Sopenharmony_ci        return EINVAL;
2093d8536b4Sopenharmony_ci    }
2103d8536b4Sopenharmony_ci
2113d8536b4Sopenharmony_ci    return 0;
2123d8536b4Sopenharmony_ci}
2133d8536b4Sopenharmony_ci
2143d8536b4Sopenharmony_ciSTATIC UINT32 MuxPendForPosix(pthread_mutex_t *mutex, UINT32 timeout)
2153d8536b4Sopenharmony_ci{
2163d8536b4Sopenharmony_ci    UINT32 intSave;
2173d8536b4Sopenharmony_ci    LosMuxCB *muxPended = NULL;
2183d8536b4Sopenharmony_ci    UINT32 retErr;
2193d8536b4Sopenharmony_ci    LosTaskCB *runningTask = NULL;
2203d8536b4Sopenharmony_ci    UINT32 muxHandle = mutex->handle;
2213d8536b4Sopenharmony_ci
2223d8536b4Sopenharmony_ci    muxPended = GET_MUX(muxHandle);
2233d8536b4Sopenharmony_ci    intSave = LOS_IntLock();
2243d8536b4Sopenharmony_ci
2253d8536b4Sopenharmony_ci    if (muxPended->muxStat == OS_MUX_UNUSED) {
2263d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
2273d8536b4Sopenharmony_ci        OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
2283d8536b4Sopenharmony_ci    }
2293d8536b4Sopenharmony_ci
2303d8536b4Sopenharmony_ci    runningTask = (LosTaskCB *)g_losTask.runTask;
2313d8536b4Sopenharmony_ci    if (muxPended->muxCount == 0) {
2323d8536b4Sopenharmony_ci        muxPended->muxCount++;
2333d8536b4Sopenharmony_ci        muxPended->owner = runningTask;
2343d8536b4Sopenharmony_ci        muxPended->priority = runningTask->priority;
2353d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
2363d8536b4Sopenharmony_ci        OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout);
2373d8536b4Sopenharmony_ci        return LOS_OK;
2383d8536b4Sopenharmony_ci    }
2393d8536b4Sopenharmony_ci
2403d8536b4Sopenharmony_ci    if ((muxPended->owner == runningTask) && (mutex->stAttr.type == PTHREAD_MUTEX_RECURSIVE)) {
2413d8536b4Sopenharmony_ci        muxPended->muxCount++;
2423d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
2433d8536b4Sopenharmony_ci        OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout);
2443d8536b4Sopenharmony_ci        return LOS_OK;
2453d8536b4Sopenharmony_ci    }
2463d8536b4Sopenharmony_ci
2473d8536b4Sopenharmony_ci    if (!timeout) {
2483d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
2493d8536b4Sopenharmony_ci        OS_RETURN_ERROR(LOS_ERRNO_MUX_UNAVAILABLE);
2503d8536b4Sopenharmony_ci    }
2513d8536b4Sopenharmony_ci
2523d8536b4Sopenharmony_ci    runningTask->taskMux = (VOID *)muxPended;
2533d8536b4Sopenharmony_ci
2543d8536b4Sopenharmony_ci    if (muxPended->owner->priority > runningTask->priority) {
2553d8536b4Sopenharmony_ci        (VOID)OsSchedModifyTaskSchedParam(muxPended->owner, runningTask->priority);
2563d8536b4Sopenharmony_ci    }
2573d8536b4Sopenharmony_ci
2583d8536b4Sopenharmony_ci    OsSchedTaskWait(&muxPended->muxList, timeout);
2593d8536b4Sopenharmony_ci
2603d8536b4Sopenharmony_ci    LOS_IntRestore(intSave);
2613d8536b4Sopenharmony_ci    OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout);
2623d8536b4Sopenharmony_ci    LOS_Schedule();
2633d8536b4Sopenharmony_ci
2643d8536b4Sopenharmony_ci    intSave = LOS_IntLock();
2653d8536b4Sopenharmony_ci    if (runningTask->taskStatus & OS_TASK_STATUS_TIMEOUT) {
2663d8536b4Sopenharmony_ci        runningTask->taskStatus &= (~OS_TASK_STATUS_TIMEOUT);
2673d8536b4Sopenharmony_ci        retErr = LOS_ERRNO_MUX_TIMEOUT;
2683d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
2693d8536b4Sopenharmony_ci        OS_RETURN_ERROR(retErr);
2703d8536b4Sopenharmony_ci    }
2713d8536b4Sopenharmony_ci
2723d8536b4Sopenharmony_ci    LOS_IntRestore(intSave);
2733d8536b4Sopenharmony_ci    return LOS_OK;
2743d8536b4Sopenharmony_ci}
2753d8536b4Sopenharmony_ci
2763d8536b4Sopenharmony_ciSTATIC UINT32 MuxPostForPosix(pthread_mutex_t *mutex)
2773d8536b4Sopenharmony_ci{
2783d8536b4Sopenharmony_ci    UINT32 intSave;
2793d8536b4Sopenharmony_ci    LosMuxCB *muxPosted = NULL;
2803d8536b4Sopenharmony_ci    LosTaskCB *resumedTask = NULL;
2813d8536b4Sopenharmony_ci    LosTaskCB *runningTask = NULL;
2823d8536b4Sopenharmony_ci    UINT32 muxHandle = mutex->handle;
2833d8536b4Sopenharmony_ci
2843d8536b4Sopenharmony_ci    muxPosted = GET_MUX(muxHandle);
2853d8536b4Sopenharmony_ci    intSave = LOS_IntLock();
2863d8536b4Sopenharmony_ci
2873d8536b4Sopenharmony_ci    if (muxPosted->muxStat == OS_MUX_UNUSED) {
2883d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
2893d8536b4Sopenharmony_ci        OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
2903d8536b4Sopenharmony_ci    }
2913d8536b4Sopenharmony_ci
2923d8536b4Sopenharmony_ci    runningTask = (LosTaskCB *)g_losTask.runTask;
2933d8536b4Sopenharmony_ci    if ((muxPosted->muxCount == 0) || (muxPosted->owner != runningTask)) {
2943d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
2953d8536b4Sopenharmony_ci        OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID);
2963d8536b4Sopenharmony_ci    }
2973d8536b4Sopenharmony_ci
2983d8536b4Sopenharmony_ci    if ((--(muxPosted->muxCount) != 0) && (mutex->stAttr.type == PTHREAD_MUTEX_RECURSIVE)) {
2993d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
3003d8536b4Sopenharmony_ci        OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted);
3013d8536b4Sopenharmony_ci        return LOS_OK;
3023d8536b4Sopenharmony_ci    }
3033d8536b4Sopenharmony_ci
3043d8536b4Sopenharmony_ci    if ((muxPosted->owner->priority) != muxPosted->priority) {
3053d8536b4Sopenharmony_ci        (VOID)OsSchedModifyTaskSchedParam(muxPosted->owner, muxPosted->priority);
3063d8536b4Sopenharmony_ci    }
3073d8536b4Sopenharmony_ci
3083d8536b4Sopenharmony_ci    if (!LOS_ListEmpty(&muxPosted->muxList)) {
3093d8536b4Sopenharmony_ci        resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(muxPosted->muxList)));
3103d8536b4Sopenharmony_ci
3113d8536b4Sopenharmony_ci        muxPosted->muxCount = 1;
3123d8536b4Sopenharmony_ci        muxPosted->owner = resumedTask;
3133d8536b4Sopenharmony_ci        muxPosted->priority = resumedTask->priority;
3143d8536b4Sopenharmony_ci        resumedTask->taskMux = NULL;
3153d8536b4Sopenharmony_ci
3163d8536b4Sopenharmony_ci        OsSchedTaskWake(resumedTask);
3173d8536b4Sopenharmony_ci
3183d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
3193d8536b4Sopenharmony_ci        OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted);
3203d8536b4Sopenharmony_ci        LOS_Schedule();
3213d8536b4Sopenharmony_ci    } else {
3223d8536b4Sopenharmony_ci        muxPosted->owner = NULL;
3233d8536b4Sopenharmony_ci        LOS_IntRestore(intSave);
3243d8536b4Sopenharmony_ci    }
3253d8536b4Sopenharmony_ci
3263d8536b4Sopenharmony_ci    return LOS_OK;
3273d8536b4Sopenharmony_ci}
3283d8536b4Sopenharmony_ci
3293d8536b4Sopenharmony_ciint pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *absTimeout)
3303d8536b4Sopenharmony_ci{
3313d8536b4Sopenharmony_ci    UINT32 ret;
3323d8536b4Sopenharmony_ci    UINT32 timeout;
3333d8536b4Sopenharmony_ci    UINT64 timeoutNs;
3343d8536b4Sopenharmony_ci    struct timespec curTime = {0};
3353d8536b4Sopenharmony_ci    LosMuxCB *muxPended = NULL;
3363d8536b4Sopenharmony_ci
3373d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
3383d8536b4Sopenharmony_ci    UINTPTR regLR = ArchLRGet();
3393d8536b4Sopenharmony_ci#endif
3403d8536b4Sopenharmony_ci
3413d8536b4Sopenharmony_ci    ret = MuxPreCheck(mutex, OS_TCB_FROM_TID(LOS_CurTaskIDGet()));
3423d8536b4Sopenharmony_ci    if (ret != 0) {
3433d8536b4Sopenharmony_ci        return (INT32)ret;
3443d8536b4Sopenharmony_ci    }
3453d8536b4Sopenharmony_ci
3463d8536b4Sopenharmony_ci    if ((absTimeout == NULL) || (absTimeout->tv_nsec < 0) || (absTimeout->tv_nsec >= OS_SYS_NS_PER_SECOND)) {
3473d8536b4Sopenharmony_ci        return EINVAL;
3483d8536b4Sopenharmony_ci    }
3493d8536b4Sopenharmony_ci    if (mutex->handle == _MUX_INVALID_HANDLE) {
3503d8536b4Sopenharmony_ci        ret = LOS_MuxCreate(&mutex->handle);
3513d8536b4Sopenharmony_ci        if (ret != LOS_OK) {
3523d8536b4Sopenharmony_ci            return MapError(ret);
3533d8536b4Sopenharmony_ci        }
3543d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
3553d8536b4Sopenharmony_ci        OsSetMutexCreateInfo(GET_MUX(mutex->handle), regLR);
3563d8536b4Sopenharmony_ci#endif
3573d8536b4Sopenharmony_ci    } else {
3583d8536b4Sopenharmony_ci        muxPended = GET_MUX(mutex->handle);
3593d8536b4Sopenharmony_ci        if ((mutex->stAttr.type == PTHREAD_MUTEX_ERRORCHECK) &&
3603d8536b4Sopenharmony_ci            (muxPended->muxCount != 0) &&
3613d8536b4Sopenharmony_ci            (muxPended->owner == OS_TCB_FROM_TID(LOS_CurTaskIDGet()))) {
3623d8536b4Sopenharmony_ci            return EDEADLK;
3633d8536b4Sopenharmony_ci        }
3643d8536b4Sopenharmony_ci    }
3653d8536b4Sopenharmony_ci    ret = clock_gettime(CLOCK_REALTIME, &curTime);
3663d8536b4Sopenharmony_ci    if (ret != LOS_OK) {
3673d8536b4Sopenharmony_ci        return EINVAL;
3683d8536b4Sopenharmony_ci    }
3693d8536b4Sopenharmony_ci    timeoutNs = (absTimeout->tv_sec - curTime.tv_sec) * OS_SYS_NS_PER_SECOND + (absTimeout->tv_nsec - curTime.tv_nsec);
3703d8536b4Sopenharmony_ci    if (timeoutNs <= 0) {
3713d8536b4Sopenharmony_ci        return ETIMEDOUT;
3723d8536b4Sopenharmony_ci    }
3733d8536b4Sopenharmony_ci    timeout = (timeoutNs + (OS_SYS_NS_PER_MSECOND - 1)) / OS_SYS_NS_PER_MSECOND;
3743d8536b4Sopenharmony_ci    ret = MuxPendForPosix(mutex, timeout);
3753d8536b4Sopenharmony_ci
3763d8536b4Sopenharmony_ci    return MapError(ret);
3773d8536b4Sopenharmony_ci}
3783d8536b4Sopenharmony_ci
3793d8536b4Sopenharmony_ci/* Lock mutex, waiting for it if necessary. */
3803d8536b4Sopenharmony_ciint pthread_mutex_lock(pthread_mutex_t *mutex)
3813d8536b4Sopenharmony_ci{
3823d8536b4Sopenharmony_ci    UINT32 ret;
3833d8536b4Sopenharmony_ci    LosMuxCB *muxPended = NULL;
3843d8536b4Sopenharmony_ci
3853d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
3863d8536b4Sopenharmony_ci    UINTPTR regLR = ArchLRGet();
3873d8536b4Sopenharmony_ci#endif
3883d8536b4Sopenharmony_ci
3893d8536b4Sopenharmony_ci    LosTaskCB *runTask = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
3903d8536b4Sopenharmony_ci
3913d8536b4Sopenharmony_ci    ret = MuxPreCheck(mutex, runTask);
3923d8536b4Sopenharmony_ci    if (ret != 0) {
3933d8536b4Sopenharmony_ci        return (INT32)ret;
3943d8536b4Sopenharmony_ci    }
3953d8536b4Sopenharmony_ci
3963d8536b4Sopenharmony_ci    if (mutex->handle == _MUX_INVALID_HANDLE) {
3973d8536b4Sopenharmony_ci        ret = LOS_MuxCreate(&mutex->handle);
3983d8536b4Sopenharmony_ci        if (ret != LOS_OK) {
3993d8536b4Sopenharmony_ci            return MapError(ret);
4003d8536b4Sopenharmony_ci        }
4013d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
4023d8536b4Sopenharmony_ci        OsSetMutexCreateInfo(GET_MUX(mutex->handle), regLR);
4033d8536b4Sopenharmony_ci#endif
4043d8536b4Sopenharmony_ci    } else {
4053d8536b4Sopenharmony_ci        muxPended = GET_MUX(mutex->handle);
4063d8536b4Sopenharmony_ci        if ((mutex->stAttr.type == PTHREAD_MUTEX_ERRORCHECK) &&
4073d8536b4Sopenharmony_ci            (muxPended->muxCount != 0) &&
4083d8536b4Sopenharmony_ci            (muxPended->owner == runTask)) {
4093d8536b4Sopenharmony_ci            return EDEADLK;
4103d8536b4Sopenharmony_ci        }
4113d8536b4Sopenharmony_ci    }
4123d8536b4Sopenharmony_ci    ret = MuxPendForPosix(mutex, LOS_WAIT_FOREVER);
4133d8536b4Sopenharmony_ci
4143d8536b4Sopenharmony_ci    return MapError(ret);
4153d8536b4Sopenharmony_ci}
4163d8536b4Sopenharmony_ci
4173d8536b4Sopenharmony_ciint pthread_mutex_trylock(pthread_mutex_t *mutex)
4183d8536b4Sopenharmony_ci{
4193d8536b4Sopenharmony_ci    UINT32 ret;
4203d8536b4Sopenharmony_ci    LosMuxCB *muxPended = NULL;
4213d8536b4Sopenharmony_ci
4223d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
4233d8536b4Sopenharmony_ci    UINTPTR regLR = ArchLRGet();
4243d8536b4Sopenharmony_ci#endif
4253d8536b4Sopenharmony_ci
4263d8536b4Sopenharmony_ci    ret = MuxPreCheck(mutex, OS_TCB_FROM_TID(LOS_CurTaskIDGet()));
4273d8536b4Sopenharmony_ci    if (ret != 0) {
4283d8536b4Sopenharmony_ci        return (INT32)ret;
4293d8536b4Sopenharmony_ci    }
4303d8536b4Sopenharmony_ci
4313d8536b4Sopenharmony_ci    if (mutex->handle == _MUX_INVALID_HANDLE) {
4323d8536b4Sopenharmony_ci        ret = LOS_MuxCreate(&mutex->handle);
4333d8536b4Sopenharmony_ci        if (ret != LOS_OK) {
4343d8536b4Sopenharmony_ci            return MapError(ret);
4353d8536b4Sopenharmony_ci        }
4363d8536b4Sopenharmony_ci#if (LOSCFG_MUTEX_CREATE_TRACE == 1)
4373d8536b4Sopenharmony_ci        OsSetMutexCreateInfo(GET_MUX(mutex->handle), regLR);
4383d8536b4Sopenharmony_ci#endif
4393d8536b4Sopenharmony_ci    } else {
4403d8536b4Sopenharmony_ci        muxPended = GET_MUX(mutex->handle);
4413d8536b4Sopenharmony_ci        if ((mutex->stAttr.type != PTHREAD_MUTEX_RECURSIVE) && (muxPended->muxCount != 0)) {
4423d8536b4Sopenharmony_ci            return EBUSY;
4433d8536b4Sopenharmony_ci        }
4443d8536b4Sopenharmony_ci    }
4453d8536b4Sopenharmony_ci    ret = MuxPendForPosix(mutex, 0);
4463d8536b4Sopenharmony_ci
4473d8536b4Sopenharmony_ci    return MapError(ret);
4483d8536b4Sopenharmony_ci}
4493d8536b4Sopenharmony_ci
4503d8536b4Sopenharmony_ciint pthread_mutex_unlock(pthread_mutex_t *mutex)
4513d8536b4Sopenharmony_ci{
4523d8536b4Sopenharmony_ci    UINT32 ret;
4533d8536b4Sopenharmony_ci    ret = MuxPreCheck(mutex, OS_TCB_FROM_TID(LOS_CurTaskIDGet()));
4543d8536b4Sopenharmony_ci    if (ret != 0) {
4553d8536b4Sopenharmony_ci        return (INT32)ret;
4563d8536b4Sopenharmony_ci    }
4573d8536b4Sopenharmony_ci
4583d8536b4Sopenharmony_ci    if (mutex->handle == _MUX_INVALID_HANDLE) {
4593d8536b4Sopenharmony_ci        return EINVAL;
4603d8536b4Sopenharmony_ci    }
4613d8536b4Sopenharmony_ci
4623d8536b4Sopenharmony_ci    ret = MuxPostForPosix(mutex);
4633d8536b4Sopenharmony_ci
4643d8536b4Sopenharmony_ci    return MapError(ret);
4653d8536b4Sopenharmony_ci}
4663d8536b4Sopenharmony_ci
467