!664 feat: 支持LOS_TaskJoin 和 LOS_TaskDetach

Merge pull request !664 from zhushengle/Join
This commit is contained in:
openharmony_ci 2021-10-28 08:01:08 +00:00 committed by Gitee
commit 2f6cd46372
8 changed files with 250 additions and 116 deletions

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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:
* <ul><li>los_task.h: the header file that contains the API declaration.</li></ul>
*/
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:
* <ul><li>los_task.h: the header file that contains the API declaration.</li></ul>
*/
extern UINT32 LOS_TaskDetach(UINT32 taskID);
#ifdef __cplusplus
#if __cplusplus
}

View File

@ -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);

View File

@ -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, &param);
@ -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;

View File

@ -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)