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