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 "pprivate.h"
330d163575Sopenharmony_ci#include "pthread.h"
340d163575Sopenharmony_ci#include "sched.h"
350d163575Sopenharmony_ci
360d163575Sopenharmony_ci#include "stdio.h"
370d163575Sopenharmony_ci#include "map_error.h"
380d163575Sopenharmony_ci#include "los_process_pri.h"
390d163575Sopenharmony_ci#include "los_sched_pri.h"
400d163575Sopenharmony_ci
410d163575Sopenharmony_ci
420d163575Sopenharmony_ci/*
430d163575Sopenharmony_ci * Array of pthread control structures. A pthread_t object is
440d163575Sopenharmony_ci * "just" an index into this array.
450d163575Sopenharmony_ci */
460d163575Sopenharmony_ciSTATIC _pthread_data g_pthreadData[LOSCFG_BASE_CORE_TSK_LIMIT + 1];
470d163575Sopenharmony_ci
480d163575Sopenharmony_ci/* Count of number of threads that have exited and not been reaped. */
490d163575Sopenharmony_ciSTATIC INT32 g_pthreadsExited = 0;
500d163575Sopenharmony_ci
510d163575Sopenharmony_ci/* this is to protect the pthread data */
520d163575Sopenharmony_ciSTATIC pthread_mutex_t g_pthreadsDataMutex = PTHREAD_MUTEX_INITIALIZER;
530d163575Sopenharmony_ci
540d163575Sopenharmony_ci/* pointed to by PTHREAD_CANCELED */
550d163575Sopenharmony_ciUINTPTR g_pthreadCanceledDummyVar;
560d163575Sopenharmony_ci
570d163575Sopenharmony_ci/*
580d163575Sopenharmony_ci * Private version of pthread_self() that returns a pointer to our internal
590d163575Sopenharmony_ci * control structure.
600d163575Sopenharmony_ci */
610d163575Sopenharmony_ci_pthread_data *pthread_get_self_data(void)
620d163575Sopenharmony_ci{
630d163575Sopenharmony_ci    UINT32 runningTaskPID = ((LosTaskCB *)(OsCurrTaskGet()))->taskID;
640d163575Sopenharmony_ci    _pthread_data *data = &g_pthreadData[runningTaskPID];
650d163575Sopenharmony_ci
660d163575Sopenharmony_ci    return data;
670d163575Sopenharmony_ci}
680d163575Sopenharmony_ci
690d163575Sopenharmony_ci_pthread_data *pthread_get_data(pthread_t id)
700d163575Sopenharmony_ci{
710d163575Sopenharmony_ci    _pthread_data *data = NULL;
720d163575Sopenharmony_ci
730d163575Sopenharmony_ci    if (OS_TID_CHECK_INVALID(id)) {
740d163575Sopenharmony_ci        return NULL;
750d163575Sopenharmony_ci    }
760d163575Sopenharmony_ci
770d163575Sopenharmony_ci    data = &g_pthreadData[id];
780d163575Sopenharmony_ci    /* Check that this is a valid entry */
790d163575Sopenharmony_ci    if ((data->state == PTHREAD_STATE_FREE) || (data->state == PTHREAD_STATE_EXITED)) {
800d163575Sopenharmony_ci        return NULL;
810d163575Sopenharmony_ci    }
820d163575Sopenharmony_ci
830d163575Sopenharmony_ci    /* Check that the entry matches the id */
840d163575Sopenharmony_ci    if (data->id != id) {
850d163575Sopenharmony_ci        return NULL;
860d163575Sopenharmony_ci    }
870d163575Sopenharmony_ci
880d163575Sopenharmony_ci    /* Return the pointer */
890d163575Sopenharmony_ci    return data;
900d163575Sopenharmony_ci}
910d163575Sopenharmony_ci
920d163575Sopenharmony_ci/*
930d163575Sopenharmony_ci * Check whether there is a cancel pending and if so, whether
940d163575Sopenharmony_ci * cancellations are enabled. We do it in this order to reduce the
950d163575Sopenharmony_ci * number of tests in the common case - when no cancellations are
960d163575Sopenharmony_ci * pending. We make this inline so it can be called directly below for speed
970d163575Sopenharmony_ci */
980d163575Sopenharmony_ciSTATIC INT32 CheckForCancel(VOID)
990d163575Sopenharmony_ci{
1000d163575Sopenharmony_ci    _pthread_data *self = pthread_get_self_data();
1010d163575Sopenharmony_ci    if (self->canceled && (self->cancelstate == PTHREAD_CANCEL_ENABLE)) {
1020d163575Sopenharmony_ci        return 1;
1030d163575Sopenharmony_ci    }
1040d163575Sopenharmony_ci    return 0;
1050d163575Sopenharmony_ci}
1060d163575Sopenharmony_ci
1070d163575Sopenharmony_ciSTATIC VOID ProcessUnusedStatusTask(_pthread_data *data)
1080d163575Sopenharmony_ci{
1090d163575Sopenharmony_ci    data->state = PTHREAD_STATE_FREE;
1100d163575Sopenharmony_ci    (VOID)memset_s(data, sizeof(_pthread_data), 0, sizeof(_pthread_data));
1110d163575Sopenharmony_ci}
1120d163575Sopenharmony_ci
1130d163575Sopenharmony_ci/*
1140d163575Sopenharmony_ci * This function is called to tidy up and dispose of any threads that have
1150d163575Sopenharmony_ci * exited. This work must be done from a thread other than the one exiting.
1160d163575Sopenharmony_ci * Note: this function must be called with pthread_mutex locked.
1170d163575Sopenharmony_ci */
1180d163575Sopenharmony_ciSTATIC VOID PthreadReap(VOID)
1190d163575Sopenharmony_ci{
1200d163575Sopenharmony_ci    UINT32 i;
1210d163575Sopenharmony_ci    _pthread_data *data = NULL;
1220d163575Sopenharmony_ci    /*
1230d163575Sopenharmony_ci     * Loop over the thread table looking for exited threads. The
1240d163575Sopenharmony_ci     * g_pthreadsExited counter springs us out of this once we have
1250d163575Sopenharmony_ci     * found them all (and keeps us out if there are none to do).
1260d163575Sopenharmony_ci     */
1270d163575Sopenharmony_ci    for (i = 0; g_pthreadsExited && (i < g_taskMaxNum); i++) {
1280d163575Sopenharmony_ci        data = &g_pthreadData[i];
1290d163575Sopenharmony_ci        if (data->state == PTHREAD_STATE_EXITED) {
1300d163575Sopenharmony_ci            /* the Huawei LiteOS not delete the dead TCB,so need to delete the TCB */
1310d163575Sopenharmony_ci            (VOID)LOS_TaskDelete(data->task->taskID);
1320d163575Sopenharmony_ci            if (data->task->taskStatus & OS_TASK_STATUS_UNUSED) {
1330d163575Sopenharmony_ci                ProcessUnusedStatusTask(data);
1340d163575Sopenharmony_ci                g_pthreadsExited--;
1350d163575Sopenharmony_ci            }
1360d163575Sopenharmony_ci        }
1370d163575Sopenharmony_ci    }
1380d163575Sopenharmony_ci}
1390d163575Sopenharmony_ci
1400d163575Sopenharmony_ciSTATIC VOID SetPthreadAttr(const _pthread_data *self, const pthread_attr_t *attr, pthread_attr_t *outAttr)
1410d163575Sopenharmony_ci{
1420d163575Sopenharmony_ci    /*
1430d163575Sopenharmony_ci     * Set use_attr to the set of attributes we are going to
1440d163575Sopenharmony_ci     * actually use. Either those passed in, or the default set.
1450d163575Sopenharmony_ci     */
1460d163575Sopenharmony_ci    if (attr == NULL) {
1470d163575Sopenharmony_ci        (VOID)pthread_attr_init(outAttr);
1480d163575Sopenharmony_ci    } else {
1490d163575Sopenharmony_ci        (VOID)memcpy_s(outAttr, sizeof(pthread_attr_t), attr, sizeof(pthread_attr_t));
1500d163575Sopenharmony_ci    }
1510d163575Sopenharmony_ci
1520d163575Sopenharmony_ci    /*
1530d163575Sopenharmony_ci     * If the stack size is not valid, we can assume that it is at
1540d163575Sopenharmony_ci     * least PTHREAD_STACK_MIN bytes.
1550d163575Sopenharmony_ci     */
1560d163575Sopenharmony_ci    if (!outAttr->stacksize_set) {
1570d163575Sopenharmony_ci        outAttr->stacksize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
1580d163575Sopenharmony_ci    }
1590d163575Sopenharmony_ci    if (outAttr->inheritsched == PTHREAD_INHERIT_SCHED) {
1600d163575Sopenharmony_ci        if (self->task == NULL) {
1610d163575Sopenharmony_ci            outAttr->schedparam.sched_priority = LOS_TaskPriGet(OsCurrTaskGet()->taskID);
1620d163575Sopenharmony_ci        } else {
1630d163575Sopenharmony_ci            outAttr->schedpolicy = self->attr.schedpolicy;
1640d163575Sopenharmony_ci            outAttr->schedparam  = self->attr.schedparam;
1650d163575Sopenharmony_ci            outAttr->scope       = self->attr.scope;
1660d163575Sopenharmony_ci        }
1670d163575Sopenharmony_ci    }
1680d163575Sopenharmony_ci}
1690d163575Sopenharmony_ci
1700d163575Sopenharmony_ciSTATIC VOID SetPthreadDataAttr(const pthread_attr_t *userAttr, const pthread_t threadID,
1710d163575Sopenharmony_ci                               LosTaskCB *taskCB, _pthread_data *created)
1720d163575Sopenharmony_ci{
1730d163575Sopenharmony_ci    created->attr         = *userAttr;
1740d163575Sopenharmony_ci    created->id           = threadID;
1750d163575Sopenharmony_ci    created->task         = taskCB;
1760d163575Sopenharmony_ci    created->state        = (userAttr->detachstate == PTHREAD_CREATE_JOINABLE) ?
1770d163575Sopenharmony_ci                            PTHREAD_STATE_RUNNING : PTHREAD_STATE_DETACHED;
1780d163575Sopenharmony_ci    /* need to confirmation */
1790d163575Sopenharmony_ci    created->cancelstate  = PTHREAD_CANCEL_ENABLE;
1800d163575Sopenharmony_ci    created->canceltype   = PTHREAD_CANCEL_DEFERRED;
1810d163575Sopenharmony_ci    created->cancelbuffer = NULL;
1820d163575Sopenharmony_ci    created->canceled     = 0;
1830d163575Sopenharmony_ci    created->freestack    = 0; /* no use default : 0 */
1840d163575Sopenharmony_ci    created->stackmem     = taskCB->topOfStack;
1850d163575Sopenharmony_ci    created->thread_data  = NULL;
1860d163575Sopenharmony_ci}
1870d163575Sopenharmony_ci
1880d163575Sopenharmony_ciSTATIC UINT32 InitPthreadData(pthread_t threadID, pthread_attr_t *userAttr,
1890d163575Sopenharmony_ci                              const CHAR name[], size_t len)
1900d163575Sopenharmony_ci{
1910d163575Sopenharmony_ci    errno_t err;
1920d163575Sopenharmony_ci    UINT32 ret = LOS_OK;
1930d163575Sopenharmony_ci    LosTaskCB *taskCB = OS_TCB_FROM_TID(threadID);
1940d163575Sopenharmony_ci    _pthread_data *created = &g_pthreadData[threadID];
1950d163575Sopenharmony_ci
1960d163575Sopenharmony_ci    err = strncpy_s(created->name, sizeof(created->name), name, len);
1970d163575Sopenharmony_ci    if (err != EOK) {
1980d163575Sopenharmony_ci        PRINT_ERR("%s: %d, err: %d\n", __FUNCTION__, __LINE__, err);
1990d163575Sopenharmony_ci        return LOS_NOK;
2000d163575Sopenharmony_ci    }
2010d163575Sopenharmony_ci    userAttr->stacksize   = taskCB->stackSize;
2020d163575Sopenharmony_ci    err = OsSetTaskName(taskCB, created->name, FALSE);
2030d163575Sopenharmony_ci    if (err != LOS_OK) {
2040d163575Sopenharmony_ci        PRINT_ERR("%s: %d, err: %d\n", __FUNCTION__, __LINE__, err);
2050d163575Sopenharmony_ci        return LOS_NOK;
2060d163575Sopenharmony_ci    }
2070d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP
2080d163575Sopenharmony_ci    if (userAttr->cpuset.__bits[0] > 0) {
2090d163575Sopenharmony_ci        taskCB->cpuAffiMask = (UINT16)userAttr->cpuset.__bits[0];
2100d163575Sopenharmony_ci    }
2110d163575Sopenharmony_ci#endif
2120d163575Sopenharmony_ci
2130d163575Sopenharmony_ci    SetPthreadDataAttr(userAttr, threadID, taskCB, created);
2140d163575Sopenharmony_ci    return ret;
2150d163575Sopenharmony_ci}
2160d163575Sopenharmony_ci
2170d163575Sopenharmony_ciint pthread_create(pthread_t *thread, const pthread_attr_t *attr,
2180d163575Sopenharmony_ci                   void *(*startRoutine)(void *), void *arg)
2190d163575Sopenharmony_ci{
2200d163575Sopenharmony_ci    pthread_attr_t userAttr;
2210d163575Sopenharmony_ci    UINT32 ret;
2220d163575Sopenharmony_ci    CHAR name[PTHREAD_DATA_NAME_MAX] = {0};
2230d163575Sopenharmony_ci    STATIC UINT16 pthreadNumber = 1;
2240d163575Sopenharmony_ci    TSK_INIT_PARAM_S taskInitParam = {0};
2250d163575Sopenharmony_ci    UINT32 taskHandle;
2260d163575Sopenharmony_ci    _pthread_data *self = pthread_get_self_data();
2270d163575Sopenharmony_ci
2280d163575Sopenharmony_ci    if ((thread == NULL) || (startRoutine == NULL)) {
2290d163575Sopenharmony_ci        return EINVAL;
2300d163575Sopenharmony_ci    }
2310d163575Sopenharmony_ci
2320d163575Sopenharmony_ci    SetPthreadAttr(self, attr, &userAttr);
2330d163575Sopenharmony_ci
2340d163575Sopenharmony_ci    (VOID)snprintf_s(name, sizeof(name), sizeof(name) - 1, "pth%02d", pthreadNumber);
2350d163575Sopenharmony_ci    pthreadNumber++;
2360d163575Sopenharmony_ci
2370d163575Sopenharmony_ci    taskInitParam.pcName       = name;
2380d163575Sopenharmony_ci    taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)startRoutine;
2390d163575Sopenharmony_ci    taskInitParam.auwArgs[0]   = (UINTPTR)arg;
2400d163575Sopenharmony_ci    taskInitParam.usTaskPrio   = (UINT16)userAttr.schedparam.sched_priority;
2410d163575Sopenharmony_ci    taskInitParam.uwStackSize  = userAttr.stacksize;
2420d163575Sopenharmony_ci    if (OsProcessIsUserMode(OsCurrProcessGet())) {
2430d163575Sopenharmony_ci        taskInitParam.processID = (UINTPTR)OsGetKernelInitProcess();
2440d163575Sopenharmony_ci    } else {
2450d163575Sopenharmony_ci        taskInitParam.processID = (UINTPTR)OsCurrProcessGet();
2460d163575Sopenharmony_ci    }
2470d163575Sopenharmony_ci    if (userAttr.detachstate == PTHREAD_CREATE_DETACHED) {
2480d163575Sopenharmony_ci        taskInitParam.uwResved = LOS_TASK_STATUS_DETACHED;
2490d163575Sopenharmony_ci    } else {
2500d163575Sopenharmony_ci        /* Set the pthread default joinable */
2510d163575Sopenharmony_ci        taskInitParam.uwResved = LOS_TASK_ATTR_JOINABLE;
2520d163575Sopenharmony_ci    }
2530d163575Sopenharmony_ci
2540d163575Sopenharmony_ci    PthreadReap();
2550d163575Sopenharmony_ci    ret = LOS_TaskCreateOnly(&taskHandle, &taskInitParam);
2560d163575Sopenharmony_ci    if (ret == LOS_OK) {
2570d163575Sopenharmony_ci        *thread = (pthread_t)taskHandle;
2580d163575Sopenharmony_ci        ret = InitPthreadData(*thread, &userAttr, name, PTHREAD_DATA_NAME_MAX);
2590d163575Sopenharmony_ci        if (ret != LOS_OK) {
2600d163575Sopenharmony_ci            goto ERROR_OUT_WITH_TASK;
2610d163575Sopenharmony_ci        }
2620d163575Sopenharmony_ci        (VOID)LOS_SetTaskScheduler(taskHandle, SCHED_RR, taskInitParam.usTaskPrio);
2630d163575Sopenharmony_ci    }
2640d163575Sopenharmony_ci
2650d163575Sopenharmony_ci    if (ret == LOS_OK) {
2660d163575Sopenharmony_ci        return ENOERR;
2670d163575Sopenharmony_ci    } else {
2680d163575Sopenharmony_ci        goto ERROR_OUT;
2690d163575Sopenharmony_ci    }
2700d163575Sopenharmony_ci
2710d163575Sopenharmony_ciERROR_OUT_WITH_TASK:
2720d163575Sopenharmony_ci    (VOID)LOS_TaskDelete(taskHandle);
2730d163575Sopenharmony_ciERROR_OUT:
2740d163575Sopenharmony_ci    *thread = (pthread_t)-1;
2750d163575Sopenharmony_ci
2760d163575Sopenharmony_ci    return map_errno(ret);
2770d163575Sopenharmony_ci}
2780d163575Sopenharmony_ci
2790d163575Sopenharmony_civoid pthread_exit(void *retVal)
2800d163575Sopenharmony_ci{
2810d163575Sopenharmony_ci    _pthread_data *self = pthread_get_self_data();
2820d163575Sopenharmony_ci    UINT32 intSave;
2830d163575Sopenharmony_ci
2840d163575Sopenharmony_ci    if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, (int *)0) != ENOERR) {
2850d163575Sopenharmony_ci        PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
2860d163575Sopenharmony_ci    }
2870d163575Sopenharmony_ci
2880d163575Sopenharmony_ci    if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) {
2890d163575Sopenharmony_ci        PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
2900d163575Sopenharmony_ci    }
2910d163575Sopenharmony_ci
2920d163575Sopenharmony_ci    self->task->joinRetval = retVal;
2930d163575Sopenharmony_ci    /*
2940d163575Sopenharmony_ci     * If we are already detached, go to EXITED state, otherwise
2950d163575Sopenharmony_ci     * go into JOIN state.
2960d163575Sopenharmony_ci     */
2970d163575Sopenharmony_ci    if (self->state == PTHREAD_STATE_DETACHED) {
2980d163575Sopenharmony_ci        self->state = PTHREAD_STATE_EXITED;
2990d163575Sopenharmony_ci        g_pthreadsExited++;
3000d163575Sopenharmony_ci    } else {
3010d163575Sopenharmony_ci        self->state = PTHREAD_STATE_JOIN;
3020d163575Sopenharmony_ci    }
3030d163575Sopenharmony_ci
3040d163575Sopenharmony_ci    if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
3050d163575Sopenharmony_ci        PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
3060d163575Sopenharmony_ci    }
3070d163575Sopenharmony_ci    SCHEDULER_LOCK(intSave);
3080d163575Sopenharmony_ci    /* If the thread is the highest thread,it can't schedule in LOS_SemPost. */
3090d163575Sopenharmony_ci    OsTaskJoinPostUnsafe(self->task);
3100d163575Sopenharmony_ci    if (self->task->taskStatus & OS_TASK_STATUS_RUNNING) {
3110d163575Sopenharmony_ci        OsSchedResched();
3120d163575Sopenharmony_ci    }
3130d163575Sopenharmony_ci    SCHEDULER_UNLOCK(intSave);
3140d163575Sopenharmony_ci}
3150d163575Sopenharmony_ci
3160d163575Sopenharmony_ciSTATIC INT32 ProcessByJoinState(_pthread_data *joined)
3170d163575Sopenharmony_ci{
3180d163575Sopenharmony_ci    UINT32 intSave;
3190d163575Sopenharmony_ci    INT32 err = 0;
3200d163575Sopenharmony_ci    UINT32 ret;
3210d163575Sopenharmony_ci    switch (joined->state) {
3220d163575Sopenharmony_ci        case PTHREAD_STATE_RUNNING:
3230d163575Sopenharmony_ci            /* The thread is still running, we must wait for it. */
3240d163575Sopenharmony_ci            SCHEDULER_LOCK(intSave);
3250d163575Sopenharmony_ci            ret = OsTaskJoinPendUnsafe(joined->task);
3260d163575Sopenharmony_ci            SCHEDULER_UNLOCK(intSave);
3270d163575Sopenharmony_ci            if (ret != LOS_OK) {
3280d163575Sopenharmony_ci                err = (INT32)ret;
3290d163575Sopenharmony_ci                break;
3300d163575Sopenharmony_ci            }
3310d163575Sopenharmony_ci
3320d163575Sopenharmony_ci            joined->state = PTHREAD_STATE_ALRDY_JOIN;
3330d163575Sopenharmony_ci            break;
3340d163575Sopenharmony_ci           /*
3350d163575Sopenharmony_ci            * The thread has become unjoinable while we waited, so we
3360d163575Sopenharmony_ci            * fall through to complain.
3370d163575Sopenharmony_ci            */
3380d163575Sopenharmony_ci        case PTHREAD_STATE_FREE:
3390d163575Sopenharmony_ci        case PTHREAD_STATE_DETACHED:
3400d163575Sopenharmony_ci        case PTHREAD_STATE_EXITED:
3410d163575Sopenharmony_ci            /* None of these may be joined. */
3420d163575Sopenharmony_ci            err = EINVAL;
3430d163575Sopenharmony_ci            break;
3440d163575Sopenharmony_ci        case PTHREAD_STATE_ALRDY_JOIN:
3450d163575Sopenharmony_ci            err = EINVAL;
3460d163575Sopenharmony_ci            break;
3470d163575Sopenharmony_ci        case PTHREAD_STATE_JOIN:
3480d163575Sopenharmony_ci            break;
3490d163575Sopenharmony_ci        default:
3500d163575Sopenharmony_ci            PRINT_ERR("state: %u is not supported\n", (UINT32)joined->state);
3510d163575Sopenharmony_ci            break;
3520d163575Sopenharmony_ci    }
3530d163575Sopenharmony_ci    return err;
3540d163575Sopenharmony_ci}
3550d163575Sopenharmony_ci
3560d163575Sopenharmony_ciint pthread_join(pthread_t thread, void **retVal)
3570d163575Sopenharmony_ci{
3580d163575Sopenharmony_ci    INT32 err;
3590d163575Sopenharmony_ci    UINT8 status;
3600d163575Sopenharmony_ci    _pthread_data *self = NULL;
3610d163575Sopenharmony_ci    _pthread_data *joined = NULL;
3620d163575Sopenharmony_ci
3630d163575Sopenharmony_ci    /* Check for cancellation first. */
3640d163575Sopenharmony_ci    pthread_testcancel();
3650d163575Sopenharmony_ci
3660d163575Sopenharmony_ci    /* Dispose of any dead threads */
3670d163575Sopenharmony_ci    (VOID)pthread_mutex_lock(&g_pthreadsDataMutex);
3680d163575Sopenharmony_ci    PthreadReap();
3690d163575Sopenharmony_ci    (VOID)pthread_mutex_unlock(&g_pthreadsDataMutex);
3700d163575Sopenharmony_ci
3710d163575Sopenharmony_ci    self   = pthread_get_self_data();
3720d163575Sopenharmony_ci    joined = pthread_get_data(thread);
3730d163575Sopenharmony_ci    if (joined == NULL) {
3740d163575Sopenharmony_ci        return ESRCH;
3750d163575Sopenharmony_ci    }
3760d163575Sopenharmony_ci    status = joined->state;
3770d163575Sopenharmony_ci
3780d163575Sopenharmony_ci    if (joined == self) {
3790d163575Sopenharmony_ci        return EDEADLK;
3800d163575Sopenharmony_ci    }
3810d163575Sopenharmony_ci
3820d163575Sopenharmony_ci    err = ProcessByJoinState(joined);
3830d163575Sopenharmony_ci    (VOID)pthread_mutex_lock(&g_pthreadsDataMutex);
3840d163575Sopenharmony_ci
3850d163575Sopenharmony_ci    if (!err) {
3860d163575Sopenharmony_ci        /*
3870d163575Sopenharmony_ci         * Here, we know that joinee is a thread that has exited and is
3880d163575Sopenharmony_ci         * ready to be joined.
3890d163575Sopenharmony_ci         */
3900d163575Sopenharmony_ci        if (retVal != NULL) {
3910d163575Sopenharmony_ci            /* Get the retVal */
3920d163575Sopenharmony_ci            *retVal = joined->task->joinRetval;
3930d163575Sopenharmony_ci        }
3940d163575Sopenharmony_ci
3950d163575Sopenharmony_ci        /* Set state to exited. */
3960d163575Sopenharmony_ci        joined->state = PTHREAD_STATE_EXITED;
3970d163575Sopenharmony_ci        g_pthreadsExited++;
3980d163575Sopenharmony_ci
3990d163575Sopenharmony_ci        /* Dispose of any dead threads */
4000d163575Sopenharmony_ci        PthreadReap();
4010d163575Sopenharmony_ci    } else {
4020d163575Sopenharmony_ci        joined->state = status;
4030d163575Sopenharmony_ci    }
4040d163575Sopenharmony_ci
4050d163575Sopenharmony_ci    (VOID)pthread_mutex_unlock(&g_pthreadsDataMutex);
4060d163575Sopenharmony_ci    /* Check for cancellation before returning */
4070d163575Sopenharmony_ci    pthread_testcancel();
4080d163575Sopenharmony_ci
4090d163575Sopenharmony_ci    return err;
4100d163575Sopenharmony_ci}
4110d163575Sopenharmony_ci
4120d163575Sopenharmony_ci/*
4130d163575Sopenharmony_ci * Set the detachstate of the thread to "detached". The thread then does not
4140d163575Sopenharmony_ci * need to be joined and its resources will be freed when it exits.
4150d163575Sopenharmony_ci */
4160d163575Sopenharmony_ciint pthread_detach(pthread_t thread)
4170d163575Sopenharmony_ci{
4180d163575Sopenharmony_ci    int ret = 0;
4190d163575Sopenharmony_ci    UINT32 intSave;
4200d163575Sopenharmony_ci
4210d163575Sopenharmony_ci    _pthread_data *detached = NULL;
4220d163575Sopenharmony_ci
4230d163575Sopenharmony_ci    if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) {
4240d163575Sopenharmony_ci        ret = ESRCH;
4250d163575Sopenharmony_ci    }
4260d163575Sopenharmony_ci    detached = pthread_get_data(thread);
4270d163575Sopenharmony_ci    if (detached == NULL) {
4280d163575Sopenharmony_ci        ret = ESRCH; /* No such thread */
4290d163575Sopenharmony_ci    } else if (detached->state == PTHREAD_STATE_DETACHED) {
4300d163575Sopenharmony_ci        ret = EINVAL; /* Already detached! */
4310d163575Sopenharmony_ci    } else if (detached->state == PTHREAD_STATE_JOIN) {
4320d163575Sopenharmony_ci        detached->state = PTHREAD_STATE_EXITED;
4330d163575Sopenharmony_ci        g_pthreadsExited++;
4340d163575Sopenharmony_ci    } else {
4350d163575Sopenharmony_ci        /* Set state to detached and kick any joinees to make them return. */
4360d163575Sopenharmony_ci        SCHEDULER_LOCK(intSave);
4370d163575Sopenharmony_ci        if (!(detached->task->taskStatus & OS_TASK_STATUS_EXIT)) {
4380d163575Sopenharmony_ci            ret = OsTaskSetDetachUnsafe(detached->task);
4390d163575Sopenharmony_ci            if (ret == ESRCH) {
4400d163575Sopenharmony_ci                ret = LOS_OK;
4410d163575Sopenharmony_ci            } else if (ret == LOS_OK) {
4420d163575Sopenharmony_ci                detached->state = PTHREAD_STATE_DETACHED;
4430d163575Sopenharmony_ci            }
4440d163575Sopenharmony_ci        } else {
4450d163575Sopenharmony_ci            detached->state = PTHREAD_STATE_EXITED;
4460d163575Sopenharmony_ci            g_pthreadsExited++;
4470d163575Sopenharmony_ci        }
4480d163575Sopenharmony_ci        SCHEDULER_UNLOCK(intSave);
4490d163575Sopenharmony_ci    }
4500d163575Sopenharmony_ci
4510d163575Sopenharmony_ci    /* Dispose of any dead threads */
4520d163575Sopenharmony_ci    PthreadReap();
4530d163575Sopenharmony_ci    if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
4540d163575Sopenharmony_ci        ret = ESRCH;
4550d163575Sopenharmony_ci    }
4560d163575Sopenharmony_ci
4570d163575Sopenharmony_ci    return ret;
4580d163575Sopenharmony_ci}
4590d163575Sopenharmony_ci
4600d163575Sopenharmony_ciint pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param)
4610d163575Sopenharmony_ci{
4620d163575Sopenharmony_ci    _pthread_data *data = NULL;
4630d163575Sopenharmony_ci    int ret;
4640d163575Sopenharmony_ci
4650d163575Sopenharmony_ci    if ((param == NULL) || (param->sched_priority > OS_TASK_PRIORITY_LOWEST)) {
4660d163575Sopenharmony_ci        return EINVAL;
4670d163575Sopenharmony_ci    }
4680d163575Sopenharmony_ci
4690d163575Sopenharmony_ci    if (policy != SCHED_RR) {
4700d163575Sopenharmony_ci        return EINVAL;
4710d163575Sopenharmony_ci    }
4720d163575Sopenharmony_ci
4730d163575Sopenharmony_ci    /* The parameters seem OK, change the thread. */
4740d163575Sopenharmony_ci    ret = pthread_mutex_lock(&g_pthreadsDataMutex);
4750d163575Sopenharmony_ci    if (ret != ENOERR) {
4760d163575Sopenharmony_ci        return ret;
4770d163575Sopenharmony_ci    }
4780d163575Sopenharmony_ci
4790d163575Sopenharmony_ci    data = pthread_get_data(thread);
4800d163575Sopenharmony_ci    if (data == NULL) {
4810d163575Sopenharmony_ci        ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
4820d163575Sopenharmony_ci        if (ret != ENOERR) {
4830d163575Sopenharmony_ci            return ret;
4840d163575Sopenharmony_ci        }
4850d163575Sopenharmony_ci        return ESRCH;
4860d163575Sopenharmony_ci    }
4870d163575Sopenharmony_ci
4880d163575Sopenharmony_ci    /* Only support one policy now */
4890d163575Sopenharmony_ci    data->attr.schedpolicy = SCHED_RR;
4900d163575Sopenharmony_ci    data->attr.schedparam  = *param;
4910d163575Sopenharmony_ci
4920d163575Sopenharmony_ci    ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
4930d163575Sopenharmony_ci    if (ret != ENOERR) {
4940d163575Sopenharmony_ci        return ret;
4950d163575Sopenharmony_ci    }
4960d163575Sopenharmony_ci    (VOID)LOS_TaskPriSet((UINT32)thread, (UINT16)param->sched_priority);
4970d163575Sopenharmony_ci
4980d163575Sopenharmony_ci    return ENOERR;
4990d163575Sopenharmony_ci}
5000d163575Sopenharmony_ci
5010d163575Sopenharmony_ciint pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param)
5020d163575Sopenharmony_ci{
5030d163575Sopenharmony_ci    _pthread_data *data = NULL;
5040d163575Sopenharmony_ci    int ret;
5050d163575Sopenharmony_ci
5060d163575Sopenharmony_ci    if ((policy == NULL) || (param == NULL)) {
5070d163575Sopenharmony_ci        return EINVAL;
5080d163575Sopenharmony_ci    }
5090d163575Sopenharmony_ci
5100d163575Sopenharmony_ci    ret = pthread_mutex_lock(&g_pthreadsDataMutex);
5110d163575Sopenharmony_ci    if (ret != ENOERR) {
5120d163575Sopenharmony_ci        return ret;
5130d163575Sopenharmony_ci    }
5140d163575Sopenharmony_ci
5150d163575Sopenharmony_ci    data = pthread_get_data(thread);
5160d163575Sopenharmony_ci    if (data == NULL) {
5170d163575Sopenharmony_ci        goto ERR_OUT;
5180d163575Sopenharmony_ci    }
5190d163575Sopenharmony_ci
5200d163575Sopenharmony_ci    *policy = data->attr.schedpolicy;
5210d163575Sopenharmony_ci    *param = data->attr.schedparam;
5220d163575Sopenharmony_ci
5230d163575Sopenharmony_ci    ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
5240d163575Sopenharmony_ci    return ret;
5250d163575Sopenharmony_ciERR_OUT:
5260d163575Sopenharmony_ci    ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
5270d163575Sopenharmony_ci    if (ret != ENOERR) {
5280d163575Sopenharmony_ci        return ret;
5290d163575Sopenharmony_ci    }
5300d163575Sopenharmony_ci    return ESRCH;
5310d163575Sopenharmony_ci}
5320d163575Sopenharmony_ci
5330d163575Sopenharmony_ci/* Call initRoutine just the once per control variable. */
5340d163575Sopenharmony_ciint pthread_once(pthread_once_t *onceControl, void (*initRoutine)(void))
5350d163575Sopenharmony_ci{
5360d163575Sopenharmony_ci    pthread_once_t old;
5370d163575Sopenharmony_ci    int ret;
5380d163575Sopenharmony_ci
5390d163575Sopenharmony_ci    if ((onceControl == NULL) || (initRoutine == NULL)) {
5400d163575Sopenharmony_ci        return EINVAL;
5410d163575Sopenharmony_ci    }
5420d163575Sopenharmony_ci
5430d163575Sopenharmony_ci    /* Do a test and set on the onceControl object. */
5440d163575Sopenharmony_ci    ret = pthread_mutex_lock(&g_pthreadsDataMutex);
5450d163575Sopenharmony_ci    if (ret != ENOERR) {
5460d163575Sopenharmony_ci        return ret;
5470d163575Sopenharmony_ci    }
5480d163575Sopenharmony_ci
5490d163575Sopenharmony_ci    old = *onceControl;
5500d163575Sopenharmony_ci    *onceControl = 1;
5510d163575Sopenharmony_ci
5520d163575Sopenharmony_ci    ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
5530d163575Sopenharmony_ci    if (ret != ENOERR) {
5540d163575Sopenharmony_ci        return ret;
5550d163575Sopenharmony_ci    }
5560d163575Sopenharmony_ci    /* If the onceControl was zero, call the initRoutine(). */
5570d163575Sopenharmony_ci    if (!old) {
5580d163575Sopenharmony_ci        initRoutine();
5590d163575Sopenharmony_ci    }
5600d163575Sopenharmony_ci
5610d163575Sopenharmony_ci    return ENOERR;
5620d163575Sopenharmony_ci}
5630d163575Sopenharmony_ci
5640d163575Sopenharmony_ci/* Thread specific data */
5650d163575Sopenharmony_ciint pthread_key_create(pthread_key_t *key, void (*destructor)(void *))
5660d163575Sopenharmony_ci{
5670d163575Sopenharmony_ci    (VOID)key;
5680d163575Sopenharmony_ci    (VOID)destructor;
5690d163575Sopenharmony_ci    PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
5700d163575Sopenharmony_ci    return 0;
5710d163575Sopenharmony_ci}
5720d163575Sopenharmony_ci
5730d163575Sopenharmony_ci/* Store the pointer value in the thread-specific data slot addressed by the key. */
5740d163575Sopenharmony_ciint pthread_setspecific(pthread_key_t key, const void *pointer)
5750d163575Sopenharmony_ci{
5760d163575Sopenharmony_ci    (VOID)key;
5770d163575Sopenharmony_ci    (VOID)pointer;
5780d163575Sopenharmony_ci    PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
5790d163575Sopenharmony_ci    return 0;
5800d163575Sopenharmony_ci}
5810d163575Sopenharmony_ci
5820d163575Sopenharmony_ci/* Retrieve the pointer value in the thread-specific data slot addressed by the key. */
5830d163575Sopenharmony_civoid *pthread_getspecific(pthread_key_t key)
5840d163575Sopenharmony_ci{
5850d163575Sopenharmony_ci    (VOID)key;
5860d163575Sopenharmony_ci    PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
5870d163575Sopenharmony_ci    return NULL;
5880d163575Sopenharmony_ci}
5890d163575Sopenharmony_ci
5900d163575Sopenharmony_ci/*
5910d163575Sopenharmony_ci * Set cancel state of current thread to ENABLE or DISABLE.
5920d163575Sopenharmony_ci * Returns old state in *oldState.
5930d163575Sopenharmony_ci */
5940d163575Sopenharmony_ciint pthread_setcancelstate(int state, int *oldState)
5950d163575Sopenharmony_ci{
5960d163575Sopenharmony_ci    _pthread_data *self = NULL;
5970d163575Sopenharmony_ci    int ret;
5980d163575Sopenharmony_ci
5990d163575Sopenharmony_ci    if ((state != PTHREAD_CANCEL_ENABLE) && (state != PTHREAD_CANCEL_DISABLE)) {
6000d163575Sopenharmony_ci        return EINVAL;
6010d163575Sopenharmony_ci    }
6020d163575Sopenharmony_ci
6030d163575Sopenharmony_ci    ret = pthread_mutex_lock(&g_pthreadsDataMutex);
6040d163575Sopenharmony_ci    if (ret != ENOERR) {
6050d163575Sopenharmony_ci        return ret;
6060d163575Sopenharmony_ci    }
6070d163575Sopenharmony_ci
6080d163575Sopenharmony_ci    self = pthread_get_self_data();
6090d163575Sopenharmony_ci
6100d163575Sopenharmony_ci    if (oldState != NULL) {
6110d163575Sopenharmony_ci        *oldState = self->cancelstate;
6120d163575Sopenharmony_ci    }
6130d163575Sopenharmony_ci
6140d163575Sopenharmony_ci    self->cancelstate = (UINT8)state;
6150d163575Sopenharmony_ci
6160d163575Sopenharmony_ci    ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
6170d163575Sopenharmony_ci    if (ret != ENOERR) {
6180d163575Sopenharmony_ci        return ret;
6190d163575Sopenharmony_ci    }
6200d163575Sopenharmony_ci
6210d163575Sopenharmony_ci    return ENOERR;
6220d163575Sopenharmony_ci}
6230d163575Sopenharmony_ci
6240d163575Sopenharmony_ci/*
6250d163575Sopenharmony_ci * Set cancel type of current thread to ASYNCHRONOUS or DEFERRED.
6260d163575Sopenharmony_ci * Returns old type in *oldType.
6270d163575Sopenharmony_ci */
6280d163575Sopenharmony_ciint pthread_setcanceltype(int type, int *oldType)
6290d163575Sopenharmony_ci{
6300d163575Sopenharmony_ci    _pthread_data *self = NULL;
6310d163575Sopenharmony_ci    int ret;
6320d163575Sopenharmony_ci
6330d163575Sopenharmony_ci    if ((type != PTHREAD_CANCEL_ASYNCHRONOUS) && (type != PTHREAD_CANCEL_DEFERRED)) {
6340d163575Sopenharmony_ci        return EINVAL;
6350d163575Sopenharmony_ci    }
6360d163575Sopenharmony_ci
6370d163575Sopenharmony_ci    ret = pthread_mutex_lock(&g_pthreadsDataMutex);
6380d163575Sopenharmony_ci    if (ret != ENOERR) {
6390d163575Sopenharmony_ci        return ret;
6400d163575Sopenharmony_ci    }
6410d163575Sopenharmony_ci
6420d163575Sopenharmony_ci    self = pthread_get_self_data();
6430d163575Sopenharmony_ci    if (oldType != NULL) {
6440d163575Sopenharmony_ci        *oldType = self->canceltype;
6450d163575Sopenharmony_ci    }
6460d163575Sopenharmony_ci
6470d163575Sopenharmony_ci    self->canceltype = (UINT8)type;
6480d163575Sopenharmony_ci
6490d163575Sopenharmony_ci    ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
6500d163575Sopenharmony_ci    if (ret != ENOERR) {
6510d163575Sopenharmony_ci        return ret;
6520d163575Sopenharmony_ci    }
6530d163575Sopenharmony_ci
6540d163575Sopenharmony_ci    return ENOERR;
6550d163575Sopenharmony_ci}
6560d163575Sopenharmony_ci
6570d163575Sopenharmony_ciSTATIC UINT32 DoPthreadCancel(_pthread_data *data)
6580d163575Sopenharmony_ci{
6590d163575Sopenharmony_ci    UINT32 ret = LOS_OK;
6600d163575Sopenharmony_ci    UINT32 intSave;
6610d163575Sopenharmony_ci    LOS_TaskLock();
6620d163575Sopenharmony_ci    data->canceled = 0;
6630d163575Sopenharmony_ci    if ((data->task->taskStatus & OS_TASK_STATUS_EXIT) || (LOS_TaskSuspend(data->task->taskID) != ENOERR)) {
6640d163575Sopenharmony_ci        ret = LOS_NOK;
6650d163575Sopenharmony_ci        goto OUT;
6660d163575Sopenharmony_ci    }
6670d163575Sopenharmony_ci
6680d163575Sopenharmony_ci    if (data->task->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
6690d163575Sopenharmony_ci        SCHEDULER_LOCK(intSave);
6700d163575Sopenharmony_ci        OsTaskJoinPostUnsafe(data->task);
6710d163575Sopenharmony_ci        SCHEDULER_UNLOCK(intSave);
6720d163575Sopenharmony_ci        g_pthreadCanceledDummyVar = (UINTPTR)PTHREAD_CANCELED;
6730d163575Sopenharmony_ci        data->task->joinRetval = (VOID *)g_pthreadCanceledDummyVar;
6740d163575Sopenharmony_ci    } else if (data->state && !(data->task->taskStatus & OS_TASK_STATUS_UNUSED)) {
6750d163575Sopenharmony_ci        data->state = PTHREAD_STATE_EXITED;
6760d163575Sopenharmony_ci        g_pthreadsExited++;
6770d163575Sopenharmony_ci        PthreadReap();
6780d163575Sopenharmony_ci    } else {
6790d163575Sopenharmony_ci        ret = LOS_NOK;
6800d163575Sopenharmony_ci    }
6810d163575Sopenharmony_ciOUT:
6820d163575Sopenharmony_ci    LOS_TaskUnlock();
6830d163575Sopenharmony_ci    return ret;
6840d163575Sopenharmony_ci}
6850d163575Sopenharmony_ci
6860d163575Sopenharmony_ciint pthread_cancel(pthread_t thread)
6870d163575Sopenharmony_ci{
6880d163575Sopenharmony_ci    _pthread_data *data = NULL;
6890d163575Sopenharmony_ci
6900d163575Sopenharmony_ci    if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) {
6910d163575Sopenharmony_ci        PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
6920d163575Sopenharmony_ci    }
6930d163575Sopenharmony_ci
6940d163575Sopenharmony_ci    data = pthread_get_data(thread);
6950d163575Sopenharmony_ci    if (data == NULL) {
6960d163575Sopenharmony_ci        if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
6970d163575Sopenharmony_ci            PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
6980d163575Sopenharmony_ci        }
6990d163575Sopenharmony_ci        return ESRCH;
7000d163575Sopenharmony_ci    }
7010d163575Sopenharmony_ci
7020d163575Sopenharmony_ci    data->canceled = 1;
7030d163575Sopenharmony_ci
7040d163575Sopenharmony_ci    if ((data->cancelstate == PTHREAD_CANCEL_ENABLE) &&
7050d163575Sopenharmony_ci        (data->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)) {
7060d163575Sopenharmony_ci        /*
7070d163575Sopenharmony_ci         * If the thread has cancellation enabled, and it is in
7080d163575Sopenharmony_ci         * asynchronous mode, suspend it and set corresponding thread's status.
7090d163575Sopenharmony_ci         * We also release the thread out of any current wait to make it wake up.
7100d163575Sopenharmony_ci         */
7110d163575Sopenharmony_ci        if (DoPthreadCancel(data) == LOS_NOK) {
7120d163575Sopenharmony_ci            goto ERROR_OUT;
7130d163575Sopenharmony_ci        }
7140d163575Sopenharmony_ci    }
7150d163575Sopenharmony_ci
7160d163575Sopenharmony_ci    /*
7170d163575Sopenharmony_ci     * Otherwise the thread has cancellation disabled, in which case
7180d163575Sopenharmony_ci     * it is up to the thread to enable cancellation
7190d163575Sopenharmony_ci     */
7200d163575Sopenharmony_ci    if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
7210d163575Sopenharmony_ci        PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
7220d163575Sopenharmony_ci    }
7230d163575Sopenharmony_ci
7240d163575Sopenharmony_ci    return ENOERR;
7250d163575Sopenharmony_ciERROR_OUT:
7260d163575Sopenharmony_ci    if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
7270d163575Sopenharmony_ci        PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
7280d163575Sopenharmony_ci    }
7290d163575Sopenharmony_ci    return ESRCH;
7300d163575Sopenharmony_ci}
7310d163575Sopenharmony_ci
7320d163575Sopenharmony_ci/*
7330d163575Sopenharmony_ci * Test for a pending cancellation for the current thread and terminate
7340d163575Sopenharmony_ci * the thread if there is one.
7350d163575Sopenharmony_ci */
7360d163575Sopenharmony_civoid pthread_testcancel(void)
7370d163575Sopenharmony_ci{
7380d163575Sopenharmony_ci    if (CheckForCancel()) {
7390d163575Sopenharmony_ci        /*
7400d163575Sopenharmony_ci         * If we have cancellation enabled, and there is a cancellation
7410d163575Sopenharmony_ci         * pending, then go ahead and do the deed.
7420d163575Sopenharmony_ci         * Exit now with special retVal. pthread_exit() calls the
7430d163575Sopenharmony_ci         * cancellation handlers implicitly.
7440d163575Sopenharmony_ci         */
7450d163575Sopenharmony_ci        pthread_exit((void *)PTHREAD_CANCELED);
7460d163575Sopenharmony_ci    }
7470d163575Sopenharmony_ci}
7480d163575Sopenharmony_ci
7490d163575Sopenharmony_ci/* Get current thread id. */
7500d163575Sopenharmony_cipthread_t pthread_self(void)
7510d163575Sopenharmony_ci{
7520d163575Sopenharmony_ci    _pthread_data *data = pthread_get_self_data();
7530d163575Sopenharmony_ci
7540d163575Sopenharmony_ci    return data->id;
7550d163575Sopenharmony_ci}
7560d163575Sopenharmony_ci
7570d163575Sopenharmony_ci/* Compare two thread identifiers. */
7580d163575Sopenharmony_ciint pthread_equal(pthread_t thread1, pthread_t thread2)
7590d163575Sopenharmony_ci{
7600d163575Sopenharmony_ci    return thread1 == thread2;
7610d163575Sopenharmony_ci}
7620d163575Sopenharmony_ci
7630d163575Sopenharmony_civoid pthread_cleanup_push_inner(struct pthread_cleanup_buffer *buffer,
7640d163575Sopenharmony_ci                                void (*routine)(void *), void *arg)
7650d163575Sopenharmony_ci{
7660d163575Sopenharmony_ci    (VOID)buffer;
7670d163575Sopenharmony_ci    (VOID)routine;
7680d163575Sopenharmony_ci    (VOID)arg;
7690d163575Sopenharmony_ci    PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
7700d163575Sopenharmony_ci    return;
7710d163575Sopenharmony_ci}
7720d163575Sopenharmony_ci
7730d163575Sopenharmony_civoid pthread_cleanup_pop_inner(struct pthread_cleanup_buffer *buffer, int execute)
7740d163575Sopenharmony_ci{
7750d163575Sopenharmony_ci    (VOID)buffer;
7760d163575Sopenharmony_ci    (VOID)execute;
7770d163575Sopenharmony_ci    PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
7780d163575Sopenharmony_ci    return;
7790d163575Sopenharmony_ci}
7800d163575Sopenharmony_ci
7810d163575Sopenharmony_ci/*
7820d163575Sopenharmony_ci * Set the cpu affinity mask for the thread
7830d163575Sopenharmony_ci */
7840d163575Sopenharmony_ciint pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t* cpuset)
7850d163575Sopenharmony_ci{
7860d163575Sopenharmony_ci    INT32 ret = sched_setaffinity(thread, cpusetsize, cpuset);
7870d163575Sopenharmony_ci    if (ret == -1) {
7880d163575Sopenharmony_ci        return errno;
7890d163575Sopenharmony_ci    } else {
7900d163575Sopenharmony_ci        return ENOERR;
7910d163575Sopenharmony_ci    }
7920d163575Sopenharmony_ci}
7930d163575Sopenharmony_ci
7940d163575Sopenharmony_ci/*
7950d163575Sopenharmony_ci * Get the cpu affinity mask from the thread
7960d163575Sopenharmony_ci */
7970d163575Sopenharmony_ciint pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t* cpuset)
7980d163575Sopenharmony_ci{
7990d163575Sopenharmony_ci    INT32 ret = sched_getaffinity(thread, cpusetsize, cpuset);
8000d163575Sopenharmony_ci    if (ret == -1) {
8010d163575Sopenharmony_ci        return errno;
8020d163575Sopenharmony_ci    } else {
8030d163575Sopenharmony_ci        return ENOERR;
8040d163575Sopenharmony_ci    }
8050d163575Sopenharmony_ci}
8060d163575Sopenharmony_ci
807