diff --git a/compat/posix/src/pthread.c b/compat/posix/src/pthread.c index f8ee1bf6..1fd5c4ff 100644 --- a/compat/posix/src/pthread.c +++ b/compat/posix/src/pthread.c @@ -248,7 +248,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, taskInitParam.uwResved = LOS_TASK_STATUS_DETACHED; } else { /* Set the pthread default joinable */ - taskInitParam.uwResved = 0; + taskInitParam.uwResved = LOS_TASK_ATTR_JOINABLE; } PthreadReap(); diff --git a/kernel/base/core/los_process.c b/kernel/base/core/los_process.c index 40c1e56b..3098d3db 100644 --- a/kernel/base/core/los_process.c +++ b/kernel/base/core/los_process.c @@ -1668,9 +1668,7 @@ STATIC VOID OsInitCopyTaskParam(LosProcessCB *childProcessCB, const CHAR *name, childPara->usTaskPrio = mainThread->priority; childPara->processID = childProcessCB->processID; if (mainThread->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) { - childPara->uwResved = OS_TASK_FLAG_PTHREAD_JOIN; - } else if (mainThread->taskStatus & OS_TASK_FLAG_DETACHED) { - childPara->uwResved = OS_TASK_FLAG_DETACHED; + childPara->uwResved = LOS_TASK_ATTR_JOINABLE; } SCHEDULER_UNLOCK(intSave); diff --git a/kernel/base/core/los_task.c b/kernel/base/core/los_task.c index 67b7ab64..a1000221 100644 --- a/kernel/base/core/los_task.c +++ b/kernel/base/core/los_task.c @@ -135,7 +135,6 @@ LITE_OS_SEC_TEXT_INIT VOID OsTaskJoinPostUnsafe(LosTaskCB *taskCB) OsTaskWakeClearPendMask(resumedTask); OsSchedTaskWake(resumedTask); } - taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN; } taskCB->taskStatus |= OS_TASK_STATUS_EXIT; } @@ -151,11 +150,13 @@ LITE_OS_SEC_TEXT UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB) return LOS_EINVAL; } + if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) { + return LOS_OK; + } + if ((taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) && LOS_ListEmpty(&taskCB->joinList)) { OsTaskWaitSetPendMask(OS_TASK_WAIT_JOIN, taskCB->taskID, LOS_WAIT_FOREVER); return OsSchedTaskWait(&taskCB->joinList, LOS_WAIT_FOREVER, TRUE); - } else if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) { - return LOS_OK; } return LOS_EINVAL; @@ -172,7 +173,6 @@ LITE_OS_SEC_TEXT UINT32 OsTaskSetDetachUnsafe(LosTaskCB *taskCB) if (LOS_ListEmpty(&(taskCB->joinList))) { LOS_ListDelete(&(taskCB->joinList)); taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN; - taskCB->taskStatus |= OS_TASK_FLAG_DETACHED; return LOS_OK; } /* This error code has a special purpose and is not allowed to appear again on the interface */ @@ -262,6 +262,89 @@ LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID) return runTask->taskID; } +STATIC INLINE UINT32 OsTaskSyncCreate(LosTaskCB *taskCB) +{ +#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC + UINT32 ret = LOS_SemCreate(0, &taskCB->syncSignal); + if (ret != LOS_OK) { + return LOS_ERRNO_TSK_MP_SYNC_RESOURCE; + } +#else + (VOID)taskCB; +#endif + return LOS_OK; +} + +STATIC INLINE VOID OsTaskSyncDestroy(UINT32 syncSignal) +{ +#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC + (VOID)LOS_SemDelete(syncSignal); +#else + (VOID)syncSignal; +#endif +} + +#ifdef LOSCFG_KERNEL_SMP +STATIC INLINE UINT32 OsTaskSyncWait(const LosTaskCB *taskCB) +{ +#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC + UINT32 ret = LOS_OK; + + LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); + LOS_SpinUnlock(&g_taskSpin); + /* + * gc soft timer works every OS_MP_GC_PERIOD period, to prevent this timer + * triggered right at the timeout has reached, we set the timeout as double + * of the gc peroid. + */ + if (LOS_SemPend(taskCB->syncSignal, OS_MP_GC_PERIOD * 2) != LOS_OK) { + ret = LOS_ERRNO_TSK_MP_SYNC_FAILED; + } + + LOS_SpinLock(&g_taskSpin); + + return ret; +#else + (VOID)taskCB; + return LOS_OK; +#endif +} +#endif + +STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB) +{ +#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC + (VOID)OsSemPostUnsafe(taskCB->syncSignal, NULL); +#else + (VOID)taskCB; +#endif +} + +STATIC VOID OsTaskReleaseHoldLock(LosProcessCB *processCB, LosTaskCB *taskCB) +{ + LosMux *mux = NULL; + UINT32 ret; + + while (!LOS_ListEmpty(&taskCB->lockList)) { + mux = LOS_DL_LIST_ENTRY(LOS_DL_LIST_FIRST(&taskCB->lockList), LosMux, holdList); + ret = OsMuxUnlockUnsafe(taskCB, mux, NULL); + if (ret != LOS_OK) { + LOS_ListDelete(&mux->holdList); + PRINT_ERR("mux ulock failed! : %u\n", ret); + } + } + +#ifdef LOSCFG_KERNEL_VM + if (processCB->processMode == OS_USER_MODE) { + OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL); + } +#endif + + OsTaskJoinPostUnsafe(taskCB); + + OsTaskSyncWake(taskCB); +} + LITE_OS_SEC_TEXT VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status) { UINT32 intSave; @@ -280,14 +363,14 @@ LITE_OS_SEC_TEXT VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status) return; } - /* The thread being killed must be able to exit automatically and will have the detached property */ - OsTaskJoinPostUnsafe(taskCB); - - if (taskCB->taskStatus & (OS_TASK_FLAG_DETACHED | OS_TASK_FLAG_EXIT_KILL)) { + if ((taskCB->taskStatus & OS_TASK_FLAG_EXIT_KILL) || !(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) { UINT32 ret = OsTaskDeleteUnsafe(taskCB, status, intSave); LOS_Panic("Task delete failed! ERROR : 0x%x\n", ret); + return; } + OsTaskReleaseHoldLock(runProcess, taskCB); + OsSchedResched(); SCHEDULER_UNLOCK(intSave); return; @@ -314,7 +397,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsTaskEntry(UINT32 taskID) taskCB = OS_TCB_FROM_TID(taskID); taskCB->joinRetval = taskCB->taskEntry(taskCB->args[0], taskCB->args[1], taskCB->args[2], taskCB->args[3]); /* 2 & 3: just for args array index */ - if (taskCB->taskStatus & OS_TASK_FLAG_DETACHED) { + if (!(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) { taskCB->joinRetval = 0; } @@ -376,62 +459,6 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskStackAlloc(VOID **topStack, UINT32 stack *topStack = (VOID *)LOS_MemAllocAlign(pool, stackSize, LOSCFG_STACK_POINT_ALIGN_SIZE); } -STATIC INLINE UINT32 OsTaskSyncCreate(LosTaskCB *taskCB) -{ -#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - UINT32 ret = LOS_SemCreate(0, &taskCB->syncSignal); - if (ret != LOS_OK) { - return LOS_ERRNO_TSK_MP_SYNC_RESOURCE; - } -#else - (VOID)taskCB; -#endif - return LOS_OK; -} - -STATIC INLINE VOID OsTaskSyncDestroy(UINT32 syncSignal) -{ -#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - (VOID)LOS_SemDelete(syncSignal); -#else - (VOID)syncSignal; -#endif -} - -LITE_OS_SEC_TEXT UINT32 OsTaskSyncWait(const LosTaskCB *taskCB) -{ -#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - UINT32 ret = LOS_OK; - - LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); - LOS_SpinUnlock(&g_taskSpin); - /* - * gc soft timer works every OS_MP_GC_PERIOD period, to prevent this timer - * triggered right at the timeout has reached, we set the timeout as double - * of the gc peroid. - */ - if (LOS_SemPend(taskCB->syncSignal, OS_MP_GC_PERIOD * 2) != LOS_OK) { - ret = LOS_ERRNO_TSK_MP_SYNC_FAILED; - } - - LOS_SpinLock(&g_taskSpin); - - return ret; -#else - (VOID)taskCB; - return LOS_OK; -#endif -} - -STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB) -{ -#ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - (VOID)OsSemPostUnsafe(taskCB->syncSignal, NULL); -#else - (VOID)taskCB; -#endif -} - STATIC VOID OsTaskKernelResourcesToFree(UINT32 syncSignal, UINTPTR topOfStack) { VOID *poolTmp = (VOID *)m_aucSysMem1; @@ -531,9 +558,7 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB *taskCB, #endif taskCB->policy = (initParam->policy == LOS_SCHED_FIFO) ? LOS_SCHED_FIFO : LOS_SCHED_RR; taskCB->taskStatus = OS_TASK_STATUS_INIT; - if (initParam->uwResved & OS_TASK_FLAG_DETACHED) { - taskCB->taskStatus |= OS_TASK_FLAG_DETACHED; - } else { + if (initParam->uwResved & LOS_TASK_ATTR_JOINABLE) { taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN; LOS_ListInit(&taskCB->joinList); } @@ -686,10 +711,6 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *in } else { initParam->processID = OsCurrProcessGet()->processID; } - initParam->uwResved &= ~OS_TASK_FLAG_PTHREAD_JOIN; - if (initParam->uwResved & LOS_TASK_STATUS_DETACHED) { - initParam->uwResved = OS_TASK_FLAG_DETACHED; - } ret = LOS_TaskCreateOnly(taskID, initParam); if (ret != LOS_OK) { @@ -856,31 +877,6 @@ STATIC INLINE VOID OsTaskStatusUnusedSet(LosTaskCB *taskCB) OS_MEM_CLEAR(taskCB->taskID); } -STATIC INLINE VOID OsTaskReleaseHoldLock(LosProcessCB *processCB, LosTaskCB *taskCB) -{ - LosMux *mux = NULL; - UINT32 ret; - - while (!LOS_ListEmpty(&taskCB->lockList)) { - mux = LOS_DL_LIST_ENTRY(LOS_DL_LIST_FIRST(&taskCB->lockList), LosMux, holdList); - ret = OsMuxUnlockUnsafe(taskCB, mux, NULL); - if (ret != LOS_OK) { - LOS_ListDelete(&mux->holdList); - PRINT_ERR("mux ulock failed! : %u\n", ret); - } - } - - if (processCB->processMode == OS_USER_MODE) { - OsTaskJoinPostUnsafe(taskCB); - -#ifdef LOSCFG_KERNEL_VM - OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL); -#endif - } - - OsTaskSyncWake(taskCB); -} - LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB *runTask) { LosProcessCB *processCB = OS_PCB_FROM_PID(runTask->processID); @@ -1628,6 +1624,104 @@ LITE_OS_SEC_TEXT INT32 LOS_SetTaskScheduler(INT32 taskID, UINT16 policy, UINT16 return LOS_OK; } +STATIC UINT32 OsTaskJoinCheck(UINT32 taskID) +{ + if (OS_TID_CHECK_INVALID(taskID)) { + return LOS_EINVAL; + } + + if (OS_INT_ACTIVE) { + return LOS_EINTR; + } + + if (!OsPreemptable()) { + return LOS_EINVAL; + } + + if (taskID == OsCurrTaskGet()->taskID) { + return LOS_EDEADLK; + } + return LOS_OK; +} + +UINT32 LOS_TaskJoin(UINT32 taskID, UINTPTR *retval) +{ + UINT32 intSave; + LosTaskCB *runTask = OsCurrTaskGet(); + LosTaskCB *taskCB = NULL; + UINT32 errRet; + + errRet = OsTaskJoinCheck(taskID); + if (errRet != LOS_OK) { + return errRet; + } + + taskCB = OS_TCB_FROM_TID(taskID); + SCHEDULER_LOCK(intSave); + if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { + SCHEDULER_UNLOCK(intSave); + return LOS_EINVAL; + } + + if (runTask->processID != taskCB->processID) { + SCHEDULER_UNLOCK(intSave); + return LOS_EPERM; + } + + errRet = OsTaskJoinPendUnsafe(taskCB); + SCHEDULER_UNLOCK(intSave); + + if (errRet == LOS_OK) { + LOS_Schedule(); + + if (retval != NULL) { + *retval = (UINTPTR)taskCB->joinRetval; + } + + (VOID)LOS_TaskDelete(taskID); + return LOS_OK; + } + + return errRet; +} + +UINT32 LOS_TaskDetach(UINT32 taskID) +{ + UINT32 intSave; + LosTaskCB *runTask = OsCurrTaskGet(); + LosTaskCB *taskCB = NULL; + UINT32 errRet; + + if (OS_TID_CHECK_INVALID(taskID)) { + return LOS_EINVAL; + } + + if (OS_INT_ACTIVE) { + return LOS_EINTR; + } + + taskCB = OS_TCB_FROM_TID(taskID); + SCHEDULER_LOCK(intSave); + if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { + SCHEDULER_UNLOCK(intSave); + return LOS_EINVAL; + } + + if (runTask->processID != taskCB->processID) { + SCHEDULER_UNLOCK(intSave); + return LOS_EPERM; + } + + if (taskCB->taskStatus & OS_TASK_STATUS_EXIT) { + SCHEDULER_UNLOCK(intSave); + return LOS_TaskJoin(taskID, NULL); + } + + errRet = OsTaskSetDetachUnsafe(taskCB); + SCHEDULER_UNLOCK(intSave); + return errRet; +} + LITE_OS_SEC_TEXT UINT32 LOS_GetSystemTaskMaximum(VOID) { return g_taskMaxNum; diff --git a/kernel/base/include/los_task_pri.h b/kernel/base/include/los_task_pri.h index f35a86c1..f98b047f 100644 --- a/kernel/base/include/los_task_pri.h +++ b/kernel/base/include/los_task_pri.h @@ -184,14 +184,6 @@ extern SPIN_LOCK_S g_taskSpin; */ #define OS_TASK_FLAG_PTHREAD_JOIN 0x0400U -/** - * @ingroup los_task - * Flag that indicates the task or task control block status. - * - * The task is status detached. - */ -#define OS_TASK_FLAG_DETACHED 0x0800U - /** * @ingroup los_task * Flag that indicates the task property. @@ -533,7 +525,6 @@ extern VOID OsTaskProcSignal(VOID); extern UINT32 OsTaskDeleteUnsafe(LosTaskCB *taskCB, UINT32 status, UINT32 intSave); extern VOID OsTaskResourcesToFree(LosTaskCB *taskCB); extern VOID OsRunTaskToDelete(LosTaskCB *taskCB); -extern UINT32 OsTaskSyncWait(const LosTaskCB *taskCB); extern UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam); extern INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName); extern VOID OsTaskCBRecycleToFree(VOID); diff --git a/kernel/include/los_task.h b/kernel/include/los_task.h index 6477c735..cf98a09a 100644 --- a/kernel/include/los_task.h +++ b/kernel/include/los_task.h @@ -59,7 +59,15 @@ extern "C" { * * The task is automatically deleted. */ -#define LOS_TASK_STATUS_DETACHED 0x0800U +#define LOS_TASK_STATUS_DETACHED 0x0U + +/** + * @ingroup los_task + * Flag that indicates the task or task control block status. + * + * The task is joinable. + */ +#define LOS_TASK_ATTR_JOINABLE 0x80000000 /** * @ingroup los_task @@ -1065,6 +1073,49 @@ extern INT32 LOS_SetTaskScheduler(INT32 taskID, UINT16 policy, UINT16 priority); */ extern VOID LOS_Schedule(VOID); +/** + * @ingroup los_task + * @brief Wait for the specified task to finish and reclaim its resources. + * + * @par Description: + * This API is used to wait for the specified task to finish and reclaim its resources. + * + * @attention None. + * + * @param taskID [IN] task ID. + * @param retval [OUT] wait for the return value of the task. + * + * @retval LOS_OK successful + * @retval LOS_EINVAL Invalid parameter or invalid operation + * @retval LOS_EINTR Disallow calls in interrupt handlers + * @retval LOS_EPERM Waiting tasks and calling tasks do not belong to the same process + * @retval LOS_EDEADLK The waiting task is the same as the calling task + * @par Dependency: + * + */ +extern UINT32 LOS_TaskJoin(UINT32 taskID, UINTPTR *retval); + +/** + * @ingroup los_task + * @brief Change the joinable attribute of the task to detach. + * + * @par Description: + * This API is used to change the joinable attribute of the task to detach. + * + * @attention None. + * + * @param taskID [IN] task ID. + * + * @retval LOS_OK successful + * @retval LOS_EINVAL Invalid parameter or invalid operation + * @retval LOS_EINTR Disallow calls in interrupt handlers + * @retval LOS_EPERM Waiting tasks and calling tasks do not belong to the same process + * @retval LOS_ESRCH Cannot modify the Joinable attribute of a task that is waiting for completion. + * @par Dependency: + * + */ +extern UINT32 LOS_TaskDetach(UINT32 taskID); + #ifdef __cplusplus #if __cplusplus } diff --git a/syscall/los_syscall.h b/syscall/los_syscall.h index f50754b7..c9594143 100644 --- a/syscall/los_syscall.h +++ b/syscall/los_syscall.h @@ -106,7 +106,7 @@ extern int SysSetProcessGroupID(unsigned int pid, unsigned int gid); extern unsigned int SysCreateUserThread(const TSK_ENTRY_FUNC func, const UserTaskParam *userParam, bool joinable); extern int SysSetThreadArea(const char *area); extern char *SysGetThreadArea(void); -extern int SysUserThreadSetDeatch(unsigned int taskID); +extern int SysUserThreadSetDetach(unsigned int taskID); extern int SysUserThreadDetach(unsigned int taskID); extern int SysThreadJoin(unsigned int taskID); extern void SysUserExitGroup(int status); diff --git a/syscall/process_syscall.c b/syscall/process_syscall.c index 3a711662..11c4bcf7 100644 --- a/syscall/process_syscall.c +++ b/syscall/process_syscall.c @@ -883,9 +883,9 @@ unsigned int SysCreateUserThread(const TSK_ENTRY_FUNC func, const UserTaskParam param.pfnTaskEntry = func; if (joinable == TRUE) { - param.uwResved = OS_TASK_FLAG_PTHREAD_JOIN; + param.uwResved = LOS_TASK_ATTR_JOINABLE; } else { - param.uwResved = OS_TASK_FLAG_DETACHED; + param.uwResved = LOS_TASK_STATUS_DETACHED; } return OsCreateUserTask(OS_INVALID_VALUE, ¶m); @@ -921,7 +921,7 @@ char *SysGetThreadArea(void) return (char *)(OsCurrTaskGet()->userArea); } -int SysUserThreadSetDeatch(unsigned int taskID) +int SysUserThreadSetDetach(unsigned int taskID) { unsigned int intSave; int ret; diff --git a/syscall/syscall_lookup.h b/syscall/syscall_lookup.h index 559cb0b5..d023e2ef 100644 --- a/syscall/syscall_lookup.h +++ b/syscall/syscall_lookup.h @@ -255,7 +255,7 @@ SYSCALL_HAND_DEF(__NR_shmctl, SysShmCtl, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_statx, SysStatx, int, ARG_NUM_5) /* LiteOS customized syscalls, not compatible with ARM EABI */ -SYSCALL_HAND_DEF(__NR_pthread_set_detach, SysUserThreadSetDeatch, int, ARG_NUM_1) +SYSCALL_HAND_DEF(__NR_pthread_set_detach, SysUserThreadSetDetach, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_pthread_join, SysThreadJoin, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_pthread_deatch, SysUserThreadDetach, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_creat_user_thread, SysCreateUserThread, unsigned int, ARG_NUM_3)