/* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "los_task_pri.h" #include "los_base_pri.h" #include "los_event_pri.h" #include "los_exc.h" #include "los_hw_pri.h" #include "los_init.h" #include "los_memstat_pri.h" #include "los_mp.h" #include "los_mux_pri.h" #include "los_sched_pri.h" #include "los_sem_pri.h" #include "los_spinlock.h" #include "los_strncpy_from_user.h" #include "los_percpu_pri.h" #include "los_process_pri.h" #include "los_vm_map.h" #include "los_vm_syscall.h" #include "los_signal.h" #include "los_hook.h" #ifdef LOSCFG_KERNEL_CPUP #include "los_cpup_pri.h" #endif #ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE #include "los_swtmr_pri.h" #endif #ifdef LOSCFG_KERNEL_LITEIPC #include "hm_liteipc.h" #endif #ifdef LOSCFG_ENABLE_OOM_LOOP_TASK #include "los_oom.h" #endif #if (LOSCFG_BASE_CORE_TSK_LIMIT <= 0) #error "task maxnum cannot be zero" #endif /* LOSCFG_BASE_CORE_TSK_LIMIT <= 0 */ // 全局变量定义 LITE_OS_SEC_BSS LosTaskCB* g_taskCBArray; // 任务控制块数组 LITE_OS_SEC_BSS LOS_DL_LIST g_losFreeTask; // 空闲任务列表 LITE_OS_SEC_BSS LOS_DL_LIST g_taskRecycleList; // 待回收任务列表 LITE_OS_SEC_BSS UINT32 g_taskMaxNum; // 最大任务数量 LITE_OS_SEC_BSS UINT32 g_taskScheduled; // 任务调度标志,每个核心一个位 LITE_OS_SEC_BSS EVENT_CB_S g_resourceEvent; // 资源事件控制块 LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_taskSpin); // 任务模块的自旋锁 // 弱引用函数声明 STATIC VOID OsConsoleIDSetHook(UINT32 param1, UINT32 param2) __attribute__((weakref("OsSetConsoleID"))); // 宏定义 #define OS_CHECK_TASK_BLOCK (OS_TASK_STATUS_DELAY | \ OS_TASK_STATUS_PENDING | \ OS_TASK_STATUS_SUSPENDED) // 临时任务块用于引导过程 LITE_OS_SEC_BSS STATIC LosTaskCB g_mainTask[LOSCFG_KERNEL_CORE_NUM]; // 获取主任务控制块 LosTaskCB* OsGetMainTask() { return (LosTaskCB*)(g_mainTask + ArchCurrCpuid()); } // 设置主任务的初始状态 VOID OsSetMainTask() { UINT32 i; CHAR* name = "osMain"; for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) { g_mainTask[i].taskStatus = OS_TASK_STATUS_UNUSED; g_mainTask[i].taskID = LOSCFG_BASE_CORE_TSK_LIMIT; g_mainTask[i].priority = OS_TASK_PRIORITY_LOWEST; #ifdef LOSCFG_KERNEL_SMP_LOCKDEP g_mainTask[i].lockDep.lockDepth = 0; g_mainTask[i].lockDep.waitLock = NULL; #endif (VOID)strncpy_s(g_mainTask[i].taskName, OS_TCB_NAME_LEN, name, OS_TCB_NAME_LEN - 1); LOS_ListInit(&g_mainTask[i].lockList); } } LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID) { while (1) { WFI; // 等待中断指令,将处理器置于低功耗状态,直到接收到中断信号 } } STATIC INLINE VOID OsInsertTCBToFreeList(LosTaskCB* taskCB) { UINT32 taskID = taskCB->taskID; (VOID)memset_s(taskCB, sizeof(LosTaskCB), 0, sizeof(LosTaskCB)); // 清空任务控制块 taskCB->taskID = taskID; taskCB->taskStatus = OS_TASK_STATUS_UNUSED; // 设置任务状态为未使用 taskCB->processID = OS_INVALID_VALUE; // 设置进程ID为无效值 LOS_ListAdd(&g_losFreeTask, &taskCB->pendList); // 将任务控制块添加到空闲任务列表中 } LITE_OS_SEC_TEXT_INIT VOID OsTaskJoinPostUnsafe(LosTaskCB* taskCB) { LosTaskCB* resumedTask = NULL; if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) { // 如果任务具有pthread_join标志 if (!LOS_ListEmpty(&taskCB->joinList)) { resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(taskCB->joinList))); // 获取第一个等待该任务的任务控制块 OsTaskWakeClearPendMask(resumedTask); // 清除任务的等待标志 OsSchedTaskWake(resumedTask); // 唤醒等待的任务 } taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN; // 清除pthread_join标志 } taskCB->taskStatus |= OS_TASK_STATUS_EXIT; // 设置任务状态为退出 } LITE_OS_SEC_TEXT UINT32 OsTaskJoinPendUnsafe(LosTaskCB* taskCB) { LosProcessCB* processCB = OS_PCB_FROM_PID(taskCB->processID); // 获取任务所属进程的进程控制块 if (!(processCB->processStatus & OS_PROCESS_STATUS_RUNNING)) { // 如果进程状态不是运行状态 return LOS_EPERM; // 返回错误码,表示没有权限 } if (taskCB->taskStatus & OS_TASK_STATUS_INIT) { // 如果任务状态为初始化状态 return LOS_EINVAL; // 返回错误码,表示参数无效 } if ((taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) && LOS_ListEmpty(&taskCB->joinList)) { // 如果任务具有pthread_join标志且等待列表为空 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; // 返回错误码,表示参数无效 } LITE_OS_SEC_TEXT UINT32 OsTaskSetDetachUnsafe(LosTaskCB* taskCB) { LosProcessCB* processCB = OS_PCB_FROM_PID(taskCB->processID); // 获取任务所属进程的进程控制块 if (!(processCB->processStatus & OS_PROCESS_STATUS_RUNNING)) { // 如果进程状态不是运行状态 return LOS_EPERM; // 返回错误码,表示没有权限 } if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) { // 如果任务具有pthread_join标志 if (LOS_ListEmpty(&(taskCB->joinList))) { // 如果等待列表为空 LOS_ListDelete(&(taskCB->joinList)); // 从等待列表中删除任务 taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN; // 清除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 */ return LOS_ESRCH; // 返回错误码,表示没有找到 } return LOS_EINVAL; // 返回错误码,表示参数无效 } LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID) { UINT32 index; UINT32 size; UINT32 ret; g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT; // 获取任务的最大数量 size = (g_taskMaxNum + 1) * sizeof(LosTaskCB); // 计算任务控制块数组的大小 /* * This memory is resident memory and is used to save the system resources * of task control block and will not be freed. */ g_taskCBArray = (LosTaskCB*)LOS_MemAlloc(m_aucSysMem0, size); // 分配任务控制块数组的内存 if (g_taskCBArray == NULL) { ret = LOS_ERRNO_TSK_NO_MEMORY; // 分配内存失败,返回错误码 goto EXIT; } (VOID)memset_s(g_taskCBArray, size, 0, size); // 清空任务控制块数组的内存 LOS_ListInit(&g_losFreeTask); // 初始化空闲任务列表 LOS_ListInit(&g_taskRecycleList); // 初始化任务回收列表 for (index = 0; index < g_taskMaxNum; index++) { g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED; // 设置任务状态为未使用 g_taskCBArray[index].taskID = index; // 设置任务ID LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList); // 将任务控制块添加到空闲任务列表中 } ret = OsSchedInit(); // 调度器初始化 EXIT: if (ret != LOS_OK) { PRINT_ERR("OsTaskInit error\n"); // 打印错误信息 } return ret; // 返回初始化结果 } UINT32 OsGetIdleTaskId(VOID) { Percpu* perCpu = OsPercpuGet(); // 获取当前CPU的私有数据 return perCpu->idleTaskID; // 返回空闲任务的ID } LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID) { UINT32 ret; TSK_INIT_PARAM_S taskInitParam; Percpu* perCpu = OsPercpuGet(); // 获取当前CPU的私有数据 UINT32* idleTaskID = &perCpu->idleTaskID; // 获取空闲任务的ID (VOID)memset_s((VOID*)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); // 清空任务初始化参数结构体 taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask; // 设置任务入口函数为OsIdleTask taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE; // 设置任务堆栈大小 taskInitParam.pcName = "Idle"; // 设置任务名称 taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST; // 设置任务优先级为最低优先级 taskInitParam.processID = OsGetIdleProcessID(); // 获取空闲任务所属进程的ID #ifdef LOSCFG_KERNEL_SMP taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid()); // 设置任务的CPU亲和性掩码 #endif ret = LOS_TaskCreateOnly(idleTaskID, &taskInitParam); // 创建空闲任务 LosTaskCB* idleTask = OS_TCB_FROM_TID(*idleTaskID); // 获取空闲任务的任务控制块 idleTask->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK; // 设置空闲任务的标志为系统任务 OsSchedSetIdleTaskSchedParam(idleTask); // 设置空闲任务的调度参数 return ret; // 返回创建结果 } /* * Description : get id of current running task. * Return : task id */ LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID) { LosTaskCB* runTask = OsCurrTaskGet(); // 获取当前运行的任务控制块 if (runTask == NULL) { return LOS_ERRNO_TSK_ID_INVALID; // 如果获取的任务控制块为空,返回错误码 } return runTask->taskID; // 返回当前任务的ID } LITE_OS_SEC_TEXT VOID OsTaskToExit(LosTaskCB* taskCB, UINT32 status) { UINT32 intSave; LosProcessCB* runProcess = OS_PCB_FROM_PID(taskCB->processID); // 获取任务所属进程的进程控制块 LosTaskCB* mainTask = OS_TCB_FROM_TID(runProcess->threadGroupID); // 获取进程的主线程任务控制块 if (mainTask == taskCB) { OsTaskExitGroup(status); // 如果任务是进程的主线程,则退出整个进程 } SCHEDULER_LOCK(intSave); // 锁定调度器 if (runProcess->threadNumber == 1) { /* 1: The last task of the process exits */ SCHEDULER_UNLOCK(intSave); // 解锁调度器 (VOID)OsProcessExit(taskCB, 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)) { UINT32 ret = OsTaskDeleteUnsafe(taskCB, status, intSave); // 如果任务具有分离属性或被标记为退出杀死状态,则删除任务 LOS_Panic("Task delete failed! ERROR : 0x%x\n", ret); // 任务删除失败,打印错误信息 } OsSchedResched(); // 调度任务重新调度 SCHEDULER_UNLOCK(intSave); // 解锁调度器 return; } /* * Description : All task entry * Input : taskID --- The ID of the task to be run */ LITE_OS_SEC_TEXT_INIT VOID OsTaskEntry(UINT32 taskID) { LosTaskCB* taskCB = NULL; LOS_ASSERT(!OS_TID_CHECK_INVALID(taskID)); // 断言任务ID的有效性 /* * task scheduler needs to be protected throughout the whole process * from interrupt and other cores. release task spinlock and enable * interrupt in sequence at the task entry. */ LOS_SpinUnlock(&g_taskSpin); // 释放任务自旋锁 (VOID)LOS_IntUnLock(); // 解锁中断 taskCB = OS_TCB_FROM_TID(taskID); // 根据任务ID获取任务控制块 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) { taskCB->joinRetval = 0; } OsTaskToExit(taskCB, 0); // 任务执行完毕后退出 } LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCreateParamCheck(const UINT32* taskID, TSK_INIT_PARAM_S* initParam, VOID** pool) { LosProcessCB* process = NULL; UINT32 poolSize = OS_SYS_MEM_SIZE; *pool = (VOID*)m_aucSysMem1; if (taskID == NULL) { return LOS_ERRNO_TSK_ID_INVALID; // 任务ID无效 } if (initParam == NULL) { return LOS_ERRNO_TSK_PTR_NULL; // 初始化参数为空 } process = OS_PCB_FROM_PID(initParam->processID); // 根据进程ID获取进程控制块 if (process->processMode > OS_USER_MODE) { return LOS_ERRNO_TSK_ID_INVALID; // 进程模式无效 } if (!OsProcessIsUserMode(process)) { if (initParam->pcName == NULL) { return LOS_ERRNO_TSK_NAME_EMPTY; // 任务名称为空 } } if (initParam->pfnTaskEntry == NULL) { return LOS_ERRNO_TSK_ENTRY_NULL; // 任务入口函数为空 } if (initParam->usTaskPrio > OS_TASK_PRIORITY_LOWEST) { return LOS_ERRNO_TSK_PRIOR_ERROR; // 任务优先级错误 } if (initParam->uwStackSize > poolSize) { return LOS_ERRNO_TSK_STKSZ_TOO_LARGE; // 任务堆栈大小过大 } if (initParam->uwStackSize == 0) { initParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; // 如果任务堆栈大小为0,则设置为默认大小 } initParam->uwStackSize = (UINT32)ALIGN(initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE); // 对任务堆栈大小进行对齐 if (initParam->uwStackSize < LOS_TASK_MIN_STACK_SIZE) { return LOS_ERRNO_TSK_STKSZ_TOO_SMALL; // 任务堆栈大小过小 } return LOS_OK; // 参数检查通过 } LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskStackAlloc(VOID** topStack, UINT32 stackSize, VOID* pool) { *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; OsTaskSyncDestroy(syncSignal); // 销毁任务同步信号量 (VOID)LOS_MemFree(poolTmp, (VOID*)topOfStack); // 释放任务堆栈内存 } LITE_OS_SEC_TEXT VOID OsTaskCBRecycleToFree() { LosTaskCB* taskCB = NULL; UINT32 intSave; SCHEDULER_LOCK(intSave); while (!LOS_ListEmpty(&g_taskRecycleList)) { taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_taskRecycleList)); // 从任务回收列表中获取任务控制块 LOS_ListDelete(&taskCB->pendList); // 从回收列表中移除任务控制块 SCHEDULER_UNLOCK(intSave); OsTaskResourcesToFree(taskCB); // 释放任务资源 SCHEDULER_LOCK(intSave); } SCHEDULER_UNLOCK(intSave); } LITE_OS_SEC_TEXT VOID OsTaskResourcesToFree(LosTaskCB* taskCB) { UINT32 syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT; UINT32 intSave; UINTPTR topOfStack; #ifdef LOSCFG_KERNEL_VM LosProcessCB* processCB = OS_PCB_FROM_PID(taskCB->processID); if (OsProcessIsUserMode(processCB) && (taskCB->userMapBase != 0)) { SCHEDULER_LOCK(intSave); UINT32 mapBase = (UINTPTR)taskCB->userMapBase; UINT32 mapSize = taskCB->userMapSize; taskCB->userMapBase = 0; taskCB->userArea = 0; SCHEDULER_UNLOCK(intSave); LOS_ASSERT(!(processCB->vmSpace == NULL)); UINT32 ret = OsUnMMap(processCB->vmSpace, (UINTPTR)mapBase, mapSize); // 取消映射用户内存 if ((ret != LOS_OK) && (mapBase != 0) && !(processCB->processStatus & OS_PROCESS_STATUS_INIT)) { PRINT_ERR("process(%u) ummap user task(%u) stack failed! mapbase: 0x%x size :0x%x, error: %d\n", processCB->processID, taskCB->taskID, mapBase, mapSize, ret); } #ifdef LOSCFG_KERNEL_LITEIPC LiteIpcRemoveServiceHandle(taskCB); #endif } #endif if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { topOfStack = taskCB->topOfStack; // 获取任务堆栈的栈顶地址 taskCB->topOfStack = 0; #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC syncSignal = taskCB->syncSignal; // 获取任务同步信号量 taskCB->syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT; #endif OsTaskKernelResourcesToFree(syncSignal, topOfStack); // 释放任务内核资源 SCHEDULER_LOCK(intSave); OsClearSigInfoTmpList(&(taskCB->sig)); // 清除任务信号信息临时列表 OsInsertTCBToFreeList(taskCB); // 将任务控制块插入到空闲列表中 SCHEDULER_UNLOCK(intSave); } return; } LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB* taskCB, const VOID* stackPtr, const VOID* topStack, const TSK_INIT_PARAM_S* initParam) { taskCB->stackPointer = (VOID*)stackPtr; // 设置任务的堆栈指针 taskCB->args[0] = initParam->auwArgs[0]; /* 0~3: just for args array index */ // 设置任务的参数 taskCB->args[1] = initParam->auwArgs[1]; taskCB->args[2] = initParam->auwArgs[2]; taskCB->args[3] = initParam->auwArgs[3]; taskCB->topOfStack = (UINTPTR)topStack; // 设置任务堆栈的栈顶地址 taskCB->stackSize = initParam->uwStackSize; // 设置任务堆栈的大小 taskCB->priority = initParam->usTaskPrio; // 设置任务的优先级 taskCB->taskEntry = initParam->pfnTaskEntry; // 设置任务的入口函数 taskCB->signal = SIGNAL_NONE; // 初始化任务的信号 #ifdef LOSCFG_KERNEL_SMP taskCB->currCpu = OS_TASK_INVALID_CPUID; // 初始化当前运行任务所在的CPU ID taskCB->cpuAffiMask = (initParam->usCpuAffiMask) ? initParam->usCpuAffiMask : LOSCFG_KERNEL_CPU_MASK; // 初始化任务的CPU亲和力掩码 #endif #ifdef LOSCFG_KERNEL_LITEIPC LOS_ListInit(&(taskCB->msgListHead)); // 初始化任务的消息列表 #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 { taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN; // 否则设置任务的pthread join标记,并初始化任务的等待列表 LOS_ListInit(&taskCB->joinList); } taskCB->futex.index = OS_INVALID_VALUE; // 初始化任务的futex索引值 LOS_ListInit(&taskCB->lockList); // 初始化任务的锁列表 SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME); // 初始化任务的排序链表 } STATIC UINT32 OsTaskCBInit(LosTaskCB* taskCB, const TSK_INIT_PARAM_S* initParam, const VOID* stackPtr, const VOID* topStack) { UINT32 intSave; // 保存中断状态的变量 UINT32 ret; // 函数返回值 UINT32 numCount; // 线程计数 UINT16 mode; // 进程运行模式 LosProcessCB* processCB = NULL; // 进程控制块指针 OsTaskCBInitBase(taskCB, stackPtr, topStack, initParam); // 初始化任务控制块的基本信息 SCHEDULER_LOCK(intSave); // 关闭调度器中断 processCB = OS_PCB_FROM_PID(initParam->processID); // 根据进程ID获取进程控制块 taskCB->processID = processCB->processID; // 设置任务所属的进程ID mode = processCB->processMode; // 获取进程的运行模式 LOS_ListTailInsert(&(processCB->threadSiblingList), &(taskCB->threadList)); // 将任务控制块插入进程的线程链表中 if (mode == OS_USER_MODE) { // 如果进程运行在用户模式下 taskCB->userArea = initParam->userParam.userArea; // 设置任务的用户区域 taskCB->userMapBase = initParam->userParam.userMapBase; // 设置任务的用户映射基地址 taskCB->userMapSize = initParam->userParam.userMapSize; // 设置任务的用户映射大小 OsUserTaskStackInit(taskCB->stackPointer, (UINTPTR)taskCB->taskEntry, initParam->userParam.userSP); // 初始化用户任务的栈 } if (!processCB->threadNumber) { // 如果进程的线程数为0 processCB->threadGroupID = taskCB->taskID; // 设置进程的线程组ID为当前任务ID } processCB->threadNumber++; // 线程数加1 numCount = processCB->threadCount; // 获取进程的线程计数 processCB->threadCount++; // 线程计数加1 SCHEDULER_UNLOCK(intSave); // 开启调度器中断 if (initParam->pcName != NULL) { // 如果任务名不为空 ret = (UINT32)OsSetTaskName(taskCB, initParam->pcName, FALSE); // 设置任务名 if (ret == LOS_OK) { return LOS_OK; } } if (snprintf_s(taskCB->taskName, OS_TCB_NAME_LEN, OS_TCB_NAME_LEN - 1, "thread%u", numCount) < 0) { // 设置默认任务名 return LOS_NOK; } return LOS_OK; } LITE_OS_SEC_TEXT LosTaskCB* OsGetFreeTaskCB(VOID) { UINT32 intSave; // 保存中断状态的变量 LosTaskCB* taskCB = NULL; // 空闲任务控制块指针 SCHEDULER_LOCK(intSave); // 关闭调度器中断 if (LOS_ListEmpty(&g_losFreeTask)) { // 如果空闲任务链表为空 SCHEDULER_UNLOCK(intSave); // 开启调度器中断 PRINT_ERR("No idle TCB in the system!\n"); // 打印错误信息 #ifdef LOSCFG_DEBUG_VERSION (VOID)OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, OS_PROCESS_INFO_ALL); // 输出任务信息 #endif return NULL; } taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_losFreeTask)); // 从空闲任务链表中获取一个空闲任务控制块 LOS_ListDelete(LOS_DL_LIST_FIRST(&g_losFreeTask)); // 从空闲任务链表中删除该任务控制块 SCHEDULER_UNLOCK(intSave); // 开启调度器中断 return taskCB; // 返回获取的空闲任务控制块指针 } LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32* taskID, TSK_INIT_PARAM_S* initParam) { UINT32 intSave, errRet; // 保存中断状态的变量,函数返回值 VOID* topStack = NULL; // 栈顶指针 VOID* stackPtr = NULL; // 栈指针 LosTaskCB* taskCB = NULL; // 任务控制块指针 VOID* pool = NULL; // 内存池指针 errRet = OsTaskCreateParamCheck(taskID, initParam, &pool); // 检查任务创建参数的合法性 if (errRet != LOS_OK) { return errRet; } taskCB = OsGetFreeTaskCB(); // 获取一个空闲的任务控制块 if (taskCB == NULL) { errRet = LOS_ERRNO_TSK_TCB_UNAVAILABLE; goto LOS_ERREND; } errRet = OsTaskSyncCreate(taskCB); // 创建任务同步对象 if (errRet != LOS_OK) { goto LOS_ERREND_REWIND_TCB; } OsTaskStackAlloc(&topStack, initParam->uwStackSize, pool); // 分配任务栈内存 if (topStack == NULL) { errRet = LOS_ERRNO_TSK_NO_MEMORY; goto LOS_ERREND_REWIND_SYNC; } stackPtr = OsTaskStackInit(taskCB->taskID, initParam->uwStackSize, topStack, TRUE); // 初始化任务栈 errRet = OsTaskCBInit(taskCB, initParam, stackPtr, topStack); // 初始化任务控制块 if (errRet != LOS_OK) { goto LOS_ERREND_TCB_INIT; } if (OsConsoleIDSetHook != NULL) { OsConsoleIDSetHook(taskCB->taskID, OsCurrTaskGet()->taskID); // 设置控制台ID的钩子函数 } *taskID = taskCB->taskID; // 返回任务ID OsHookCall(LOS_HOOK_TYPE_TASK_CREATE, taskCB); // 调用任务创建的钩子函数 return LOS_OK; LOS_ERREND_TCB_INIT: (VOID)LOS_MemFree(pool, topStack); // 释放任务栈内存 LOS_ERREND_REWIND_SYNC: #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC OsTaskSyncDestroy(taskCB->syncSignal); // 销毁任务同步对象 #endif LOS_ERREND_REWIND_TCB: SCHEDULER_LOCK(intSave); OsInsertTCBToFreeList(taskCB); // 将任务控制块插入空闲任务链表 SCHEDULER_UNLOCK(intSave); LOS_ERREND: return errRet; } LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32* taskID, TSK_INIT_PARAM_S* initParam) { UINT32 ret; // 函数返回值 UINT32 intSave; // 保存中断状态的变量 LosTaskCB* taskCB = NULL; // 任务控制块指针 if (initParam == NULL) { return LOS_ERRNO_TSK_PTR_NULL; } if (OS_INT_ACTIVE) { return LOS_ERRNO_TSK_YIELD_IN_INT; } if (OsProcessIsUserMode(OsCurrProcessGet())) { initParam->processID = OsGetKernelInitProcessID(); // 如果当前进程运行在用户模式下,将进程ID设置为内核初始化进程ID } else { initParam->processID = OsCurrProcessGet()->processID; // 否则将进程ID设置为当前进程ID } 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) { return ret; } taskCB = OS_TCB_FROM_TID(*taskID); // 根据任务ID获取任务控制块指针 SCHEDULER_LOCK(intSave); OsSchedTaskEnQueue(taskCB); // 将任务插入调度队列 SCHEDULER_UNLOCK(intSave); /* in case created task not running on this core, schedule or not depends on other schedulers status. */ LOS_MpSchedule(OS_MP_CPU_ALL); // 多处理器调度 if (OS_SCHEDULER_ACTIVE) { LOS_Schedule(); // 调度任务 } return LOS_OK; } LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID) { UINT32 intSave; // 保存中断状态的变量 UINT32 errRet; // 函数返回值 LosTaskCB* taskCB = NULL; // 任务控制块指针 BOOL needSched = FALSE; // 是否需要进行任务调度的标志 if (OS_TID_CHECK_INVALID(taskID)) { return LOS_ERRNO_TSK_ID_INVALID; } taskCB = OS_TCB_FROM_TID(taskID); // 根据任务ID获取任务控制块指针 SCHEDULER_LOCK(intSave); /* 清除挂起信号 */ taskCB->signal &= ~SIGNAL_SUSPEND; if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { errRet = LOS_ERRNO_TSK_NOT_CREATED; OS_GOTO_ERREND(); } else if (!(taskCB->taskStatus & OS_TASK_STATUS_SUSPENDED)) { errRet = LOS_ERRNO_TSK_NOT_SUSPENDED; OS_GOTO_ERREND(); } taskCB->taskStatus &= ~OS_TASK_STATUS_SUSPENDED; if (!(taskCB->taskStatus & OS_CHECK_TASK_BLOCK)) { OsSchedTaskEnQueue(taskCB); // 将任务插入调度队列 if (OS_SCHEDULER_ACTIVE) { needSched = TRUE; } } SCHEDULER_UNLOCK(intSave); LOS_MpSchedule(OS_MP_CPU_ALL); // 多处理器调度 if (needSched) { LOS_Schedule(); // 调度任务 } return LOS_OK; LOS_ERREND: SCHEDULER_UNLOCK(intSave); return errRet; } /* * Check if needs to do the suspend operation on the running task. * Return TRUE, if needs to do the suspension. * Return FALSE, if meets following circumstances: * 1. Do the suspension across cores, if SMP is enabled * 2. Do the suspension when preemption is disabled * 3. Do the suspension in hard-irq * then LOS_TaskSuspend will directly return with 'ret' value. */ LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB* taskCB, UINT32* ret) { /* 初始化默认的返回值 */ *ret = LOS_OK; #ifdef LOSCFG_KERNEL_SMP /* 异步操作,无需进行任务锁检查 */ if (taskCB->currCpu != ArchCurrCpuid()) { taskCB->signal = SIGNAL_SUSPEND; LOS_MpSchedule(taskCB->currCpu); return FALSE; } #endif if (!OsPreemptableInSched()) { /* 在调度期间禁止抢占,挂起当前核心上正在运行的任务 */ *ret = LOS_ERRNO_TSK_SUSPEND_LOCKED; return FALSE; } if (OS_INT_ACTIVE) { /* 在中断中挂起正在运行的任务 */ taskCB->signal = SIGNAL_SUSPEND; return FALSE; } return TRUE; } LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB* taskCB) { UINT32 errRet; // 函数返回值 UINT16 tempStatus; // 临时存储任务状态 tempStatus = taskCB->taskStatus; if (tempStatus & OS_TASK_STATUS_UNUSED) { return LOS_ERRNO_TSK_NOT_CREATED; } if (tempStatus & OS_TASK_STATUS_SUSPENDED) { return LOS_ERRNO_TSK_ALREADY_SUSPENDED; } if ((tempStatus & OS_TASK_STATUS_RUNNING) && !OsTaskSuspendCheckOnRun(taskCB, &errRet)) { return errRet; } if (tempStatus & OS_TASK_STATUS_READY) { OsSchedTaskDeQueue(taskCB); // 从调度队列中移除任务 } taskCB->taskStatus |= OS_TASK_STATUS_SUSPENDED; OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB); // 调用任务挂起的钩子函数 if (taskCB == OsCurrTaskGet()) { OsSchedResched(); // 调度任务 } return LOS_OK; } LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID) { UINT32 intSave; // 保存中断状态的变量 LosTaskCB* taskCB = NULL; // 任务控制块指针 UINT32 errRet; // 函数返回值 if (OS_TID_CHECK_INVALID(taskID)) { return LOS_ERRNO_TSK_ID_INVALID; } taskCB = OS_TCB_FROM_TID(taskID); // 根据任务ID获取任务控制块指针 if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK; } SCHEDULER_LOCK(intSave); errRet = OsTaskSuspend(taskCB); // 调用挂起任务的函数 SCHEDULER_UNLOCK(intSave); return errRet; } STATIC INLINE VOID OsTaskStatusUnusedSet(LosTaskCB* taskCB) { taskCB->taskStatus |= OS_TASK_STATUS_UNUSED; // 设置任务状态为未使用 taskCB->eventMask = 0; // 清除任务的事件掩码 OS_MEM_CLEAR(taskCB->taskID); // 清除任务ID } 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); // 从Futex哈希表中删除任务的Futex节点 #endif } OsTaskSyncWake(taskCB); // 唤醒等待该任务的任务 return; } LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB* runTask) { LosProcessCB* processCB = OS_PCB_FROM_PID(runTask->processID); // 获取任务所属进程的进程控制块指针 OsTaskReleaseHoldLock(processCB, runTask); // 释放任务持有的锁资源 OsTaskStatusUnusedSet(runTask); // 设置任务状态为未使用 LOS_ListDelete(&runTask->threadList); // 从线程链表中删除任务 processCB->threadNumber--; // 进程的线程数减一 LOS_ListTailInsert(&g_taskRecycleList, &runTask->pendList); // 将任务插入任务回收链表 OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL); // 发送资源事件通知 OsSchedResched(); // 调度任务 return; } /* * Check if needs to do the delete operation on the running task. * Return TRUE, if needs to do the deletion. * Return FALSE, if meets following circumstances: * 1. Do the deletion across cores, if SMP is enabled * 2. Do the deletion when preemption is disabled * 3. Do the deletion in hard-irq * then LOS_TaskDelete will directly return with 'ret' value. */ STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB* taskCB, UINT32* ret) { /* init default out return value */ *ret = LOS_OK; #ifdef LOSCFG_KERNEL_SMP /* ASYNCHRONIZED. No need to do task lock checking */ if (taskCB->currCpu != ArchCurrCpuid()) { /* * 任务正在另一个CPU上运行。 * 使用"kill"信号屏蔽目标任务,并触发多处理器调度, * 这可能不是必需的,但删除可以更及时。 */ taskCB->signal = SIGNAL_KILL; LOS_MpSchedule(taskCB->currCpu); *ret = OsTaskSyncWait(taskCB); return FALSE; } #endif if (!OsPreemptableInSched()) { /* 如果任务正在运行且调度器被锁定,则无法删除任务 */ *ret = LOS_ERRNO_TSK_DELETE_LOCKED; return FALSE; } if (OS_INT_ACTIVE) { /* * 在中断中删除正在运行的任务。 * 屏蔽"kill"信号,稍后进行删除处理。 */ taskCB->signal = SIGNAL_KILL; return FALSE; } return TRUE; } STATIC VOID OsTaskDeleteInactive(LosProcessCB* processCB, LosTaskCB* taskCB) { LosMux* mux = (LosMux*)taskCB->taskMux; // 互斥锁指针 UINT16 taskStatus = taskCB->taskStatus; // 任务状态 LOS_ASSERT(!(taskStatus & OS_TASK_STATUS_RUNNING)); OsTaskReleaseHoldLock(processCB, taskCB); // 释放任务持有的锁资源 OsSchedTaskExit(taskCB); // 调度任务退出 if (taskStatus & OS_TASK_STATUS_PENDING) { if (LOS_MuxIsValid(mux) == TRUE) { OsMuxBitmapRestore(mux, taskCB, (LosTaskCB*)mux->owner); } } OsTaskStatusUnusedSet(taskCB); // 设置任务状态为未使用 LOS_ListDelete(&taskCB->threadList); // 从线程链表中删除任务 processCB->threadNumber--; // 进程的线程数减一 LOS_ListTailInsert(&g_taskRecycleList, &taskCB->pendList); // 将任务插入任务回收链表 return; } LITE_OS_SEC_TEXT UINT32 OsTaskDeleteUnsafe(LosTaskCB* taskCB, UINT32 status, UINT32 intSave) { LosProcessCB* processCB = OS_PCB_FROM_PID(taskCB->processID); // 获取任务所属进程的进程控制块指针 UINT32 mode = processCB->processMode; // 进程的运行模式 UINT32 errRet = LOS_OK; // 函数返回值 if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { errRet = LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK; goto EXIT; } if ((taskCB->taskStatus & OS_TASK_STATUS_RUNNING) && !OsRunTaskToDeleteCheckOnRun(taskCB, &errRet)) { goto EXIT; } if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) { OsTaskDeleteInactive(processCB, taskCB); // 非运行中的任务的删除操作 SCHEDULER_UNLOCK(intSave); OsWriteResourceEvent(OS_RESOURCE_EVENT_FREE); return errRet; } OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, taskCB); // 调用任务删除的钩子函数 if (mode == OS_USER_MODE) { SCHEDULER_UNLOCK(intSave); OsTaskResourcesToFree(taskCB); // 释放任务的资源 SCHEDULER_LOCK(intSave); } #ifdef LOSCFG_KERNEL_SMP LOS_ASSERT(OsPercpuGet()->taskLockCnt == 1); #else LOS_ASSERT(OsPercpuGet()->taskLockCnt == 0); #endif OsRunTaskToDelete(taskCB); // 运行中的任务的删除操作 EXIT: SCHEDULER_UNLOCK(intSave); return errRet; } LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID) { UINT32 intSave; UINT32 ret; LosTaskCB* taskCB = NULL; LosProcessCB* processCB = NULL; if (OS_TID_CHECK_INVALID(taskID)) { return LOS_ERRNO_TSK_ID_INVALID; } if (OS_INT_ACTIVE) { return LOS_ERRNO_TSK_YIELD_IN_INT; } taskCB = OS_TCB_FROM_TID(taskID); // 获取任务控制块指针 SCHEDULER_LOCK(intSave); if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { ret = LOS_ERRNO_TSK_NOT_CREATED; OS_GOTO_ERREND(); } if (taskCB->taskStatus & (OS_TASK_FLAG_SYSTEM_TASK | OS_TASK_FLAG_NO_DELETE)) { SCHEDULER_UNLOCK(intSave); OsBackTrace(); return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK; } processCB = OS_PCB_FROM_PID(taskCB->processID); // 获取任务所属进程的进程控制块指针 if (processCB->threadNumber == 1) { /* 1: The last task of the process exits */ if (processCB == OsCurrProcessGet()) { SCHEDULER_UNLOCK(intSave); OsProcessExit(taskCB, OS_PRO_EXIT_OK); // 进程退出 return LOS_OK; } ret = LOS_ERRNO_TSK_ID_INVALID; OS_GOTO_ERREND(); } return OsTaskDeleteUnsafe(taskCB, OS_PRO_EXIT_OK, intSave); // 调用任务删除函数 LOS_ERREND: SCHEDULER_UNLOCK(intSave); return ret; } LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick) { UINT32 intSave; LosTaskCB* runTask = NULL; if (OS_INT_ACTIVE) { PRINT_ERR("In interrupt not allow delay task!\n"); return LOS_ERRNO_TSK_DELAY_IN_INT; } runTask = OsCurrTaskGet(); // 获取当前任务的任务控制块指针 if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { OsBackTrace(); return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK; } if (!OsPreemptable()) { return LOS_ERRNO_TSK_DELAY_IN_LOCK; } OsHookCall(LOS_HOOK_TYPE_TASK_DELAY, tick); // 调用任务延时的钩子函数 if (tick == 0) { return LOS_TaskYield(); // 任务主动让出CPU } SCHEDULER_LOCK(intSave); OsSchedDelay(runTask, tick); // 将任务加入延时队列 OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, runTask); // 调用任务移动到延时队列的钩子函数 SCHEDULER_UNLOCK(intSave); return LOS_OK; } LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID) { UINT32 intSave; LosTaskCB* taskCB = NULL; UINT16 priority; if (OS_TID_CHECK_INVALID(taskID)) { return (UINT16)OS_INVALID; } taskCB = OS_TCB_FROM_TID(taskID); // 获取任务控制块指针 SCHEDULER_LOCK(intSave); if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { SCHEDULER_UNLOCK(intSave); return (UINT16)OS_INVALID; } priority = taskCB->priority; // 获取任务的优先级 SCHEDULER_UNLOCK(intSave); return priority; } LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio) { UINT32 intSave; LosTaskCB *taskCB = NULL; if (taskPrio > OS_TASK_PRIORITY_LOWEST) { return LOS_ERRNO_TSK_PRIOR_ERROR; } if (OS_TID_CHECK_INVALID(taskID)) { return LOS_ERRNO_TSK_ID_INVALID; } taskCB = OS_TCB_FROM_TID(taskID); if (taskCB->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK; } SCHEDULER_LOCK(intSave); if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { SCHEDULER_UNLOCK(intSave); return LOS_ERRNO_TSK_NOT_CREATED; } BOOL isReady = OsSchedModifyTaskSchedParam(taskCB, taskCB->policy, taskPrio); SCHEDULER_UNLOCK(intSave); LOS_MpSchedule(OS_MP_CPU_ALL); if (isReady && OS_SCHEDULER_ACTIVE) { LOS_Schedule(); } return LOS_OK; } LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CurTaskPriSet(UINT16 taskPrio) { return LOS_TaskPriSet(OsCurrTaskGet()->taskID, taskPrio); } LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskYield(VOID) { UINT32 intSave; if (OS_INT_ACTIVE) { return LOS_ERRNO_TSK_YIELD_IN_INT; } if (!OsPreemptable()) { return LOS_ERRNO_TSK_YIELD_IN_LOCK; } LosTaskCB *runTask = OsCurrTaskGet(); if (OS_TID_CHECK_INVALID(runTask->taskID)) { return LOS_ERRNO_TSK_ID_INVALID; } SCHEDULER_LOCK(intSave); /* reset timeslice of yielded task */ OsSchedYield(); SCHEDULER_UNLOCK(intSave); return LOS_OK; } LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskLock(VOID) { UINT32 intSave; intSave = LOS_IntLock(); OsCpuSchedLock(OsPercpuGet()); LOS_IntRestore(intSave); } LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID) { OsCpuSchedUnlock(OsPercpuGet(), LOS_IntLock()); } LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInfo) { UINT32 intSave; LosTaskCB *taskCB = NULL; if (taskInfo == NULL) { return LOS_ERRNO_TSK_PTR_NULL; } if (OS_TID_CHECK_INVALID(taskID)) { return LOS_ERRNO_TSK_ID_INVALID; } taskCB = OS_TCB_FROM_TID(taskID); SCHEDULER_LOCK(intSave); if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { SCHEDULER_UNLOCK(intSave); return LOS_ERRNO_TSK_NOT_CREATED; } if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING) || OS_INT_ACTIVE) { taskInfo->uwSP = (UINTPTR)taskCB->stackPointer; } else { taskInfo->uwSP = ArchSPGet(); } taskInfo->usTaskStatus = taskCB->taskStatus; taskInfo->usTaskPrio = taskCB->priority; taskInfo->uwStackSize = taskCB->stackSize; taskInfo->uwTopOfStack = taskCB->topOfStack; taskInfo->uwEventMask = taskCB->eventMask; taskInfo->taskEvent = taskCB->taskEvent; taskInfo->pTaskMux = taskCB->taskMux; taskInfo->uwTaskID = taskID; if (strncpy_s(taskInfo->acName, LOS_TASK_NAMELEN, taskCB->taskName, LOS_TASK_NAMELEN - 1) != EOK) { PRINT_ERR("Task name copy failed!\n"); } taskInfo->acName[LOS_TASK_NAMELEN - 1] = '\0'; taskInfo->uwBottomOfStack = TRUNCATE(((UINTPTR)taskCB->topOfStack + taskCB->stackSize), OS_TASK_STACK_ADDR_ALIGN); taskInfo->uwCurrUsed = (UINT32)(taskInfo->uwBottomOfStack - taskInfo->uwSP); taskInfo->bOvf = OsStackWaterLineGet((const UINTPTR *)taskInfo->uwBottomOfStack, (const UINTPTR *)taskInfo->uwTopOfStack, &taskInfo->uwPeakUsed); SCHEDULER_UNLOCK(intSave); return LOS_OK; } LITE_OS_SEC_TEXT BOOL OsTaskCpuAffiSetUnsafe(UINT32 taskID, UINT16 newCpuAffiMask, UINT16 *oldCpuAffiMask) { #ifdef LOSCFG_KERNEL_SMP LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID); taskCB->cpuAffiMask = newCpuAffiMask; *oldCpuAffiMask = CPUID_TO_AFFI_MASK(taskCB->currCpu); if (!((*oldCpuAffiMask) & newCpuAffiMask)) { taskCB->signal = SIGNAL_AFFI; return TRUE; } #else (VOID)taskID; (VOID)newCpuAffiMask; (VOID)oldCpuAffiMask; #endif /* LOSCFG_KERNEL_SMP */ return FALSE; } LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskID, UINT16 cpuAffiMask) { LosTaskCB *taskCB = NULL; BOOL needSched = FALSE; UINT32 intSave; UINT16 currCpuMask; if (OS_TID_CHECK_INVALID(taskID)) { return LOS_ERRNO_TSK_ID_INVALID; } if (!(cpuAffiMask & LOSCFG_KERNEL_CPU_MASK)) { return LOS_ERRNO_TSK_CPU_AFFINITY_MASK_ERR; } taskCB = OS_TCB_FROM_TID(taskID); SCHEDULER_LOCK(intSave); if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { SCHEDULER_UNLOCK(intSave); return LOS_ERRNO_TSK_NOT_CREATED; } needSched = OsTaskCpuAffiSetUnsafe(taskID, cpuAffiMask, &currCpuMask); SCHEDULER_UNLOCK(intSave); if (needSched && OS_SCHEDULER_ACTIVE) { LOS_MpSchedule(currCpuMask); LOS_Schedule(); } return LOS_OK; } LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID) { #ifdef LOSCFG_KERNEL_SMP #define INVALID_CPU_AFFI_MASK 0 LosTaskCB *taskCB = NULL; UINT16 cpuAffiMask; UINT32 intSave; if (OS_TID_CHECK_INVALID(taskID)) { return INVALID_CPU_AFFI_MASK; } taskCB = OS_TCB_FROM_TID(taskID); SCHEDULER_LOCK(intSave); if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { SCHEDULER_UNLOCK(intSave); return INVALID_CPU_AFFI_MASK; } cpuAffiMask = taskCB->cpuAffiMask; SCHEDULER_UNLOCK(intSave); return cpuAffiMask; #else (VOID)taskID; return 1; #endif } /* * Description : Process pending signals tagged by others cores */ LITE_OS_SEC_TEXT_MINOR VOID OsTaskProcSignal(VOID) { UINT32 intSave, ret; /* * private and uninterruptable, no protection needed. * while this task is always running when others cores see it, * so it keeps receiving signals while follow code executing. */ LosTaskCB *runTask = OsCurrTaskGet(); if (runTask->signal == SIGNAL_NONE) { return; } if (runTask->signal & SIGNAL_KILL) { /* * clear the signal, and do the task deletion. if the signaled task has been * scheduled out, then this deletion will wait until next run. */ SCHEDULER_LOCK(intSave); runTask->signal = SIGNAL_NONE; ret = OsTaskDeleteUnsafe(runTask, OS_PRO_EXIT_OK, intSave); if (ret) { PRINT_ERR("Task proc signal delete task(%u) failed err:0x%x\n", runTask->taskID, ret); } } else if (runTask->signal & SIGNAL_SUSPEND) { runTask->signal &= ~SIGNAL_SUSPEND; /* suspend killed task may fail, ignore the result */ (VOID)LOS_TaskSuspend(runTask->taskID); #ifdef LOSCFG_KERNEL_SMP } else if (runTask->signal & SIGNAL_AFFI) { runTask->signal &= ~SIGNAL_AFFI; /* pri-queue has updated, notify the target cpu */ LOS_MpSchedule((UINT32)runTask->cpuAffiMask); #endif } } LITE_OS_SEC_TEXT INT32 OsSetTaskName(LosTaskCB *taskCB, const CHAR *name, BOOL setPName) { UINT32 intSave; errno_t err; LosProcessCB *processCB = NULL; const CHAR *namePtr = NULL; CHAR nameBuff[OS_TCB_NAME_LEN] = { 0 }; if ((taskCB == NULL) || (name == NULL)) { return EINVAL; } if (LOS_IsUserAddress((VADDR_T)(UINTPTR)name)) { err = LOS_StrncpyFromUser(nameBuff, (const CHAR *)name, OS_TCB_NAME_LEN); if (err < 0) { return -err; } namePtr = nameBuff; } else { namePtr = name; } SCHEDULER_LOCK(intSave); err = strncpy_s(taskCB->taskName, OS_TCB_NAME_LEN, (VOID *)namePtr, OS_TCB_NAME_LEN - 1); if (err != EOK) { err = EINVAL; goto EXIT; } err = LOS_OK; processCB = OS_PCB_FROM_PID(taskCB->processID); /* if thread is main thread, then set processName as taskName */ if ((taskCB->taskID == processCB->threadGroupID) && (setPName == TRUE)) { err = (INT32)OsSetProcessName(processCB, (const CHAR *)taskCB->taskName); if (err != LOS_OK) { err = EINVAL; } } EXIT: SCHEDULER_UNLOCK(intSave); return err; } STATIC VOID OsExitGroupActiveTaskKilled(LosProcessCB *processCB, LosTaskCB *taskCB) { INT32 ret; taskCB->taskStatus |= OS_TASK_FLAG_EXIT_KILL; #ifdef LOSCFG_KERNEL_SMP /* The other core that the thread is running on and is currently running in a non-system call */ if (!taskCB->sig.sigIntLock && (taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) { taskCB->signal = SIGNAL_KILL; LOS_MpSchedule(taskCB->currCpu); } else #endif #ifdef LOSCFG_KERNEL_VM { ret = OsTaskKillUnsafe(taskCB->taskID, SIGKILL); if (ret != LOS_OK) { PRINT_ERR("pid %u exit, Exit task group %u kill %u failed! ERROR: %d\n", taskCB->processID, OsCurrTaskGet()->taskID, taskCB->taskID, ret); } } #endif if (!(taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN)) { taskCB->taskStatus |= OS_TASK_FLAG_PTHREAD_JOIN; LOS_ListInit(&taskCB->joinList); } ret = OsTaskJoinPendUnsafe(taskCB); if (ret != LOS_OK) { PRINT_ERR("pid %u exit, Exit task group %u to wait others task %u(0x%x) exit failed! ERROR: %d\n", taskCB->processID, OsCurrTaskGet()->taskID, taskCB->taskID, taskCB->taskStatus, ret); } } LITE_OS_SEC_TEXT VOID OsTaskExitGroup(UINT32 status) { UINT32 intSave; LosProcessCB *processCB = OsCurrProcessGet(); LosTaskCB *currTask = OsCurrTaskGet(); SCHEDULER_LOCK(intSave); if ((processCB->processStatus & OS_PROCESS_FLAG_EXIT) || !OsProcessIsUserMode(processCB)) { SCHEDULER_UNLOCK(intSave); return; } processCB->processStatus |= OS_PROCESS_FLAG_EXIT; processCB->threadGroupID = currTask->taskID; LOS_DL_LIST *list = &processCB->threadSiblingList; LOS_DL_LIST *head = list; do { LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(list->pstNext, LosTaskCB, threadList); if ((taskCB->taskStatus & (OS_TASK_STATUS_INIT | OS_TASK_STATUS_EXIT) || ((taskCB->taskStatus & OS_TASK_STATUS_READY) && !taskCB->sig.sigIntLock)) && !(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) { OsTaskDeleteInactive(processCB, taskCB); } else { if (taskCB != currTask) { OsExitGroupActiveTaskKilled(processCB, taskCB); } else { /* Skip the current task */ list = list->pstNext; } } } while (head != list->pstNext); SCHEDULER_UNLOCK(intSave); LOS_ASSERT(processCB->threadNumber == 1); return; } LITE_OS_SEC_TEXT VOID OsExecDestroyTaskGroup(VOID) { OsTaskExitGroup(OS_PRO_EXIT_OK); OsTaskCBRecycleToFree(); } UINT32 OsUserTaskOperatePermissionsCheck(LosTaskCB *taskCB) { return OsUserProcessOperatePermissionsCheck(taskCB, OsCurrProcessGet()->processID); } UINT32 OsUserProcessOperatePermissionsCheck(LosTaskCB *taskCB, UINT32 processID) { if (taskCB == NULL) { return LOS_EINVAL; } if (processID == OS_INVALID_VALUE) { return OS_INVALID_VALUE; } if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { return LOS_EINVAL; } if (processID != taskCB->processID) { return LOS_EPERM; } return LOS_OK; } LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsCreateUserTaskParamCheck(UINT32 processID, TSK_INIT_PARAM_S *param) { UserTaskParam *userParam = NULL; if (param == NULL) { return OS_INVALID_VALUE; } userParam = ¶m->userParam; if ((processID == OS_INVALID_VALUE) && !LOS_IsUserAddress(userParam->userArea)) { return OS_INVALID_VALUE; } if (!LOS_IsUserAddress((UINTPTR)param->pfnTaskEntry)) { return OS_INVALID_VALUE; } if (userParam->userMapBase && !LOS_IsUserAddressRange(userParam->userMapBase, userParam->userMapSize)) { return OS_INVALID_VALUE; } if (!LOS_IsUserAddress(userParam->userSP)) { return OS_INVALID_VALUE; } return LOS_OK; } LITE_OS_SEC_TEXT_INIT UINT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S *initParam) { LosProcessCB *processCB = NULL; UINT32 taskID; UINT32 ret; UINT32 intSave; ret = OsCreateUserTaskParamCheck(processID, initParam); if (ret != LOS_OK) { return ret; } initParam->uwStackSize = OS_USER_TASK_SYSCALL_STACK_SIZE; initParam->usTaskPrio = OS_TASK_PRIORITY_LOWEST; initParam->policy = LOS_SCHED_RR; if (processID == OS_INVALID_VALUE) { SCHEDULER_LOCK(intSave); processCB = OsCurrProcessGet(); initParam->processID = processCB->processID; initParam->consoleID = processCB->consoleID; SCHEDULER_UNLOCK(intSave); } else { processCB = OS_PCB_FROM_PID(processID); if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) { return OS_INVALID_VALUE; } initParam->processID = processID; initParam->consoleID = 0; } ret = LOS_TaskCreateOnly(&taskID, initParam); if (ret != LOS_OK) { return OS_INVALID_VALUE; } return taskID; } LITE_OS_SEC_TEXT INT32 LOS_GetTaskScheduler(INT32 taskID) { UINT32 intSave; LosTaskCB *taskCB = NULL; INT32 policy; if (OS_TID_CHECK_INVALID(taskID)) { return -LOS_EINVAL; } taskCB = OS_TCB_FROM_TID(taskID); SCHEDULER_LOCK(intSave); if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { policy = -LOS_EINVAL; OS_GOTO_ERREND(); } policy = taskCB->policy; LOS_ERREND: SCHEDULER_UNLOCK(intSave); return policy; } LITE_OS_SEC_TEXT INT32 LOS_SetTaskScheduler(INT32 taskID, UINT16 policy, UINT16 priority) { UINT32 intSave; BOOL needSched = FALSE; if (OS_TID_CHECK_INVALID(taskID)) { return LOS_ESRCH; } if (priority > OS_TASK_PRIORITY_LOWEST) { return LOS_EINVAL; } if ((policy != LOS_SCHED_FIFO) && (policy != LOS_SCHED_RR)) { return LOS_EINVAL; } SCHEDULER_LOCK(intSave); needSched = OsSchedModifyTaskSchedParam(OS_TCB_FROM_TID(taskID), policy, priority); SCHEDULER_UNLOCK(intSave); LOS_MpSchedule(OS_MP_CPU_ALL); if (needSched && OS_SCHEDULER_ACTIVE) { LOS_Schedule(); } return LOS_OK; } LITE_OS_SEC_TEXT UINT32 LOS_GetSystemTaskMaximum(VOID) { return g_taskMaxNum; } LITE_OS_SEC_TEXT VOID OsWriteResourceEvent(UINT32 events) { (VOID)LOS_EventWrite(&g_resourceEvent, events); } LITE_OS_SEC_TEXT VOID OsWriteResourceEventUnsafe(UINT32 events) { (VOID)OsEventWriteUnsafe(&g_resourceEvent, events, FALSE, NULL); } STATIC VOID OsResourceRecoveryTask(VOID) { UINT32 ret; while (1) { ret = LOS_EventRead(&g_resourceEvent, OS_RESOURCE_EVENT_MASK, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); if (ret & (OS_RESOURCE_EVENT_FREE | OS_RESOURCE_EVENT_OOM)) { OsTaskCBRecycleToFree(); OsProcessCBRecycleToFree(); } #ifdef LOSCFG_ENABLE_OOM_LOOP_TASK if (ret & OS_RESOURCE_EVENT_OOM) { (VOID)OomCheckProcess(); } #endif } } LITE_OS_SEC_TEXT UINT32 OsResourceFreeTaskCreate(VOID) { UINT32 ret; UINT32 taskID; TSK_INIT_PARAM_S taskInitParam; ret = LOS_EventInit((PEVENT_CB_S)&g_resourceEvent); if (ret != LOS_OK) { return LOS_NOK; } (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsResourceRecoveryTask; taskInitParam.uwStackSize = OS_TASK_RESOURCE_STATIC_SIZE; taskInitParam.pcName = "ResourcesTask"; taskInitParam.usTaskPrio = OS_TASK_RESOURCE_FREE_PRIORITY; ret = LOS_TaskCreate(&taskID, &taskInitParam); if (ret == LOS_OK) { OS_TCB_FROM_TID(taskID)->taskStatus |= OS_TASK_FLAG_NO_DELETE; } return ret; } LOS_MODULE_INIT(OsResourceFreeTaskCreate, LOS_INIT_LEVEL_KMOD_TASK);