diff --git a/1500-200用例描述.docx b/1500-200用例描述.docx new file mode 100644 index 0000000..38e3aff Binary files /dev/null and b/1500-200用例描述.docx differ diff --git a/DOCX/weitong用例描述.docx b/DOCX/weitong用例描述.docx new file mode 100644 index 0000000..b4b2365 Binary files /dev/null and b/DOCX/weitong用例描述.docx differ diff --git a/core/los_sys.c b/core/los_sys.c index 8a9d373..4d9b586 100644 --- a/core/los_sys.c +++ b/core/los_sys.c @@ -29,44 +29,76 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + /* + LOS_TickCountGet()ȡǰϵͳͨOsGetCurrSchedTimeCycle()ȡǰʱڣÿĵõ + + LOS_CyclePerTickGet()ȡÿĵͨϵͳʱƵʳÿõÿĵ + + LOS_MS2Tick()תΪĺÿٳÿõ + + LOS_Tick2MS()תΪ롣Ľÿٳÿõ + + OsNS2Tick()תΪȼÿĵȻ󽫸ÿĵ1ٳÿĵõֵΪֵ + */ + #include "los_sys_pri.h" #include "los_sched_pri.h" - + // ֵ #define OS_MAX_VALUE 0xFFFFFFFFUL +// ȡǰϵͳ LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID) { + // ڲȡǰʱڲÿĵõ return OsGetCurrSchedTimeCycle() / OS_CYCLE_PER_TICK; } +// ȡÿĵ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CyclePerTickGet(VOID) { + // ϵͳʱƵʳÿõÿĵ return g_sysClock / LOSCFG_BASE_CORE_TICK_PER_SECOND; } +// תΪ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MS2Tick(UINT32 millisec) { + // ֱֵӷֵ if (millisec == OS_MAX_VALUE) { return OS_MAX_VALUE; } + // ÿٳÿõ return ((UINT64)millisec * LOSCFG_BASE_CORE_TICK_PER_SECOND) / OS_SYS_MS_PER_SECOND; } +// תΪ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_Tick2MS(UINT32 tick) { + // ÿٳÿõ return ((UINT64)tick * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND; } +// תΪ LITE_OS_SEC_TEXT_MINOR UINT32 OsNS2Tick(UINT64 nanoseconds) { + // ÿĵ const UINT32 nsPerTick = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND; + // ÿĵ1ٳÿĵõ UINT64 ticks = (nanoseconds + nsPerTick - 1) / nsPerTick; + + // ֵΪֵ if (ticks > OS_MAX_VALUE) { ticks = OS_MAX_VALUE; } + + // תΪ32λ return (UINT32)ticks; } + + + diff --git a/core/los_task.c b/core/los_task.c index 67b7ab6..e33ccac 100644 --- a/core/los_task.c +++ b/core/los_task.c @@ -66,34 +66,38 @@ #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; /* one bit for each cores */ -LITE_OS_SEC_BSS EVENT_CB_S g_resourceEvent; -/* spinlock for task module, only available on SMP mode */ -LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_taskSpin); - + // ȫֱ +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"))); + UINT32 param2) __attribute__((weakref("OsSetConsoleID"))); +// 궨 #define OS_CHECK_TASK_BLOCK (OS_TASK_STATUS_DELAY | \ OS_TASK_STATUS_PENDING | \ OS_TASK_STATUS_SUSPENDED) -/* temp task blocks for booting procedure */ +// ʱ LITE_OS_SEC_BSS STATIC LosTaskCB g_mainTask[LOSCFG_KERNEL_CORE_NUM]; -LosTaskCB *OsGetMainTask() +// ȡƿ +LosTaskCB* OsGetMainTask() { - return (LosTaskCB *)(g_mainTask + ArchCurrCpuid()); + return (LosTaskCB*)(g_mainTask + ArchCurrCpuid()); } +// ijʼ״̬ VOID OsSetMainTask() { UINT32 i; - CHAR *name = "osMain"; + CHAR* name = "osMain"; for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) { g_mainTask[i].taskStatus = OS_TASK_STATUS_UNUSED; @@ -111,141 +115,143 @@ VOID OsSetMainTask() LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID) { while (1) { - WFI; + WFI; // ȴжָڵ͹״ֱ̬յжź } } -STATIC INLINE VOID OsInsertTCBToFreeList(LosTaskCB *taskCB) +STATIC INLINE VOID OsInsertTCBToFreeList(LosTaskCB* taskCB) { UINT32 taskID = taskCB->taskID; - (VOID)memset_s(taskCB, sizeof(LosTaskCB), 0, sizeof(LosTaskCB)); + (VOID)memset_s(taskCB, sizeof(LosTaskCB), 0, sizeof(LosTaskCB)); // ƿ taskCB->taskID = taskID; - taskCB->taskStatus = OS_TASK_STATUS_UNUSED; - taskCB->processID = OS_INVALID_VALUE; - LOS_ListAdd(&g_losFreeTask, &taskCB->pendList); + 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) +LITE_OS_SEC_TEXT_INIT VOID OsTaskJoinPostUnsafe(LosTaskCB* taskCB) { - LosTaskCB *resumedTask = NULL; + LosTaskCB* resumedTask = NULL; - if (taskCB->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) { + 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); + resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(taskCB->joinList))); // ȡһȴƿ + OsTaskWakeClearPendMask(resumedTask); // ĵȴ־ + OsSchedTaskWake(resumedTask); // ѵȴ } - taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN; + taskCB->taskStatus &= ~OS_TASK_FLAG_PTHREAD_JOIN; // pthread_join־ } - taskCB->taskStatus |= OS_TASK_STATUS_EXIT; + taskCB->taskStatus |= OS_TASK_STATUS_EXIT; // ״̬Ϊ˳ } -LITE_OS_SEC_TEXT UINT32 OsTaskJoinPendUnsafe(LosTaskCB *taskCB) +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; + 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_STATUS_INIT) { // ״̬Ϊʼ״̬ + return LOS_EINVAL; // ش룬ʾЧ } - 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; + 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; + return LOS_EINVAL; // ش룬ʾЧ } -LITE_OS_SEC_TEXT UINT32 OsTaskSetDetachUnsafe(LosTaskCB *taskCB) +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; + 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) { - 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; + 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_ESRCH; // ش룬ʾûҵ } - return LOS_EINVAL; + 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); + 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); + g_taskCBArray = (LosTaskCB*)LOS_MemAlloc(m_aucSysMem0, size); // ƿڴ if (g_taskCBArray == NULL) { - ret = LOS_ERRNO_TSK_NO_MEMORY; + ret = LOS_ERRNO_TSK_NO_MEMORY; // ڴʧܣش goto EXIT; } - (VOID)memset_s(g_taskCBArray, size, 0, size); + (VOID)memset_s(g_taskCBArray, size, 0, size); // ƿڴ - LOS_ListInit(&g_losFreeTask); - LOS_ListInit(&g_taskRecycleList); + 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; - LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList); + g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED; // ״̬Ϊδʹ + g_taskCBArray[index].taskID = index; // ID + LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList); // ƿӵб } - ret = OsSchedInit(); + ret = OsSchedInit(); // ʼ EXIT: if (ret != LOS_OK) { - PRINT_ERR("OsTaskInit error\n"); + PRINT_ERR("OsTaskInit error\n"); // ӡϢ } - return ret; + return ret; // سʼ } UINT32 OsGetIdleTaskId(VOID) { - Percpu *perCpu = OsPercpuGet(); - return perCpu->idleTaskID; + 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(); - UINT32 *idleTaskID = &perCpu->idleTaskID; - - (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); - taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask; - taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE; - taskInitParam.pcName = "Idle"; - taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST; - taskInitParam.processID = OsGetIdleProcessID(); + 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()); + 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); + ret = LOS_TaskCreateOnly(idleTaskID, &taskInitParam); // + LosTaskCB* idleTask = OS_TCB_FROM_TID(*idleTaskID); // ȡƿ + idleTask->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK; // ÿı־Ϊϵͳ + OsSchedSetIdleTaskSchedParam(idleTask); // ÿĵȲ - return ret; + return ret; // ش } /* @@ -254,167 +260,169 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID) */ LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID) { - LosTaskCB *runTask = OsCurrTaskGet(); + LosTaskCB* runTask = OsCurrTaskGet(); // ȡǰеƿ if (runTask == NULL) { - return LOS_ERRNO_TSK_ID_INVALID; + return LOS_ERRNO_TSK_ID_INVALID; // ȡƿΪգش } - return runTask->taskID; + return runTask->taskID; // صǰID } -LITE_OS_SEC_TEXT VOID OsTaskToExit(LosTaskCB *taskCB, UINT32 status) +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); + LosProcessCB* runProcess = OS_PCB_FROM_PID(taskCB->processID); // ȡ̵Ľ̿ƿ + LosTaskCB* mainTask = OS_TCB_FROM_TID(runProcess->threadGroupID); // ȡ̵߳ƿ if (mainTask == taskCB) { - OsTaskExitGroup(status); + OsTaskExitGroup(status); // ǽ̵̣߳˳ } - SCHEDULER_LOCK(intSave); + SCHEDULER_LOCK(intSave); // if (runProcess->threadNumber == 1) { /* 1: The last task of the process exits */ - SCHEDULER_UNLOCK(intSave); - (VOID)OsProcessExit(taskCB, status); + 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); + 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); + UINT32 ret = OsTaskDeleteUnsafe(taskCB, status, intSave); // зԻ򱻱Ϊ˳ɱ״̬ɾ + LOS_Panic("Task delete failed! ERROR : 0x%x\n", ret); // ɾʧܣӡϢ } - OsSchedResched(); - SCHEDULER_UNLOCK(intSave); + 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; + LosTaskCB* taskCB = NULL; - LOS_ASSERT(!OS_TID_CHECK_INVALID(taskID)); + 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(); + LOS_SpinUnlock(&g_taskSpin); // ͷ + (VOID)LOS_IntUnLock(); // ж - taskCB = OS_TCB_FROM_TID(taskID); + 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 */ + 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); + OsTaskToExit(taskCB, 0); // ִϺ˳ } -LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCreateParamCheck(const UINT32 *taskID, - TSK_INIT_PARAM_S *initParam, VOID **pool) +LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCreateParamCheck(const UINT32* taskID, + TSK_INIT_PARAM_S* initParam, VOID** pool) { - LosProcessCB *process = NULL; + LosProcessCB* process = NULL; UINT32 poolSize = OS_SYS_MEM_SIZE; - *pool = (VOID *)m_aucSysMem1; + *pool = (VOID*)m_aucSysMem1; if (taskID == NULL) { - return LOS_ERRNO_TSK_ID_INVALID; + return LOS_ERRNO_TSK_ID_INVALID; // IDЧ } if (initParam == NULL) { - return LOS_ERRNO_TSK_PTR_NULL; + return LOS_ERRNO_TSK_PTR_NULL; // ʼΪ } - process = OS_PCB_FROM_PID(initParam->processID); + process = OS_PCB_FROM_PID(initParam->processID); // ݽIDȡ̿ƿ if (process->processMode > OS_USER_MODE) { - return LOS_ERRNO_TSK_ID_INVALID; + return LOS_ERRNO_TSK_ID_INVALID; // ģʽЧ } if (!OsProcessIsUserMode(process)) { if (initParam->pcName == NULL) { - return LOS_ERRNO_TSK_NAME_EMPTY; + return LOS_ERRNO_TSK_NAME_EMPTY; // Ϊ } } if (initParam->pfnTaskEntry == NULL) { - return LOS_ERRNO_TSK_ENTRY_NULL; + return LOS_ERRNO_TSK_ENTRY_NULL; // ںΪ } if (initParam->usTaskPrio > OS_TASK_PRIORITY_LOWEST) { - return LOS_ERRNO_TSK_PRIOR_ERROR; + return LOS_ERRNO_TSK_PRIOR_ERROR; // ȼ } if (initParam->uwStackSize > poolSize) { - return LOS_ERRNO_TSK_STKSZ_TOO_LARGE; + return LOS_ERRNO_TSK_STKSZ_TOO_LARGE; // ջС } if (initParam->uwStackSize == 0) { - initParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + initParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; // ջСΪ0ΪĬϴС } - initParam->uwStackSize = (UINT32)ALIGN(initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE); + 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_ERRNO_TSK_STKSZ_TOO_SMALL; // ջСС } - return LOS_OK; + return LOS_OK; // ͨ } -LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskStackAlloc(VOID **topStack, UINT32 stackSize, VOID *pool) +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); + *topStack = (VOID*)LOS_MemAllocAlign(pool, stackSize, LOSCFG_STACK_POINT_ALIGN_SIZE); // ջڴ } -STATIC INLINE UINT32 OsTaskSyncCreate(LosTaskCB *taskCB) +STATIC INLINE UINT32 OsTaskSyncCreate(LosTaskCB* taskCB) { #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - UINT32 ret = LOS_SemCreate(0, &taskCB->syncSignal); + UINT32 ret = LOS_SemCreate(0, &taskCB->syncSignal); // ͬź if (ret != LOS_OK) { - return LOS_ERRNO_TSK_MP_SYNC_RESOURCE; + return LOS_ERRNO_TSK_MP_SYNC_RESOURCE; // ͬԴʧ } #else (VOID)taskCB; #endif - return LOS_OK; + return LOS_OK; // ͬɹ } STATIC INLINE VOID OsTaskSyncDestroy(UINT32 syncSignal) { #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - (VOID)LOS_SemDelete(syncSignal); + (VOID)LOS_SemDelete(syncSignal); // ɾͬź #else (VOID)syncSignal; #endif } -LITE_OS_SEC_TEXT UINT32 OsTaskSyncWait(const LosTaskCB *taskCB) + +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); + 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; + ret = LOS_ERRNO_TSK_MP_SYNC_FAILED; // ͬȴʧ } - LOS_SpinLock(&g_taskSpin); + LOS_SpinLock(&g_taskSpin); // ȡ return ret; #else @@ -423,10 +431,10 @@ LITE_OS_SEC_TEXT UINT32 OsTaskSyncWait(const LosTaskCB *taskCB) #endif } -STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB) +STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB* taskCB) { #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - (VOID)OsSemPostUnsafe(taskCB->syncSignal, NULL); + (VOID)OsSemPostUnsafe(taskCB->syncSignal, NULL); // ͬź #else (VOID)taskCB; #endif @@ -434,39 +442,39 @@ STATIC INLINE VOID OsTaskSyncWake(const LosTaskCB *taskCB) STATIC VOID OsTaskKernelResourcesToFree(UINT32 syncSignal, UINTPTR topOfStack) { - VOID *poolTmp = (VOID *)m_aucSysMem1; + VOID* poolTmp = (VOID*)m_aucSysMem1; - OsTaskSyncDestroy(syncSignal); + OsTaskSyncDestroy(syncSignal); // ͬź - (VOID)LOS_MemFree(poolTmp, (VOID *)topOfStack); + (VOID)LOS_MemFree(poolTmp, (VOID*)topOfStack); // ͷջڴ } LITE_OS_SEC_TEXT VOID OsTaskCBRecycleToFree() { - LosTaskCB *taskCB = NULL; + 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); + taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_taskRecycleList)); // блȡƿ + LOS_ListDelete(&taskCB->pendList); // ӻбƳƿ SCHEDULER_UNLOCK(intSave); - OsTaskResourcesToFree(taskCB); + OsTaskResourcesToFree(taskCB); // ͷԴ SCHEDULER_LOCK(intSave); } SCHEDULER_UNLOCK(intSave); } -LITE_OS_SEC_TEXT VOID OsTaskResourcesToFree(LosTaskCB *taskCB) +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); + LosProcessCB* processCB = OS_PCB_FROM_PID(taskCB->processID); if (OsProcessIsUserMode(processCB) && (taskCB->userMapBase != 0)) { SCHEDULER_LOCK(intSave); UINT32 mapBase = (UINTPTR)taskCB->userMapBase; @@ -476,10 +484,10 @@ LITE_OS_SEC_TEXT VOID OsTaskResourcesToFree(LosTaskCB *taskCB) SCHEDULER_UNLOCK(intSave); LOS_ASSERT(!(processCB->vmSpace == NULL)); - UINT32 ret = OsUnMMap(processCB->vmSpace, (UINTPTR)mapBase, mapSize); + 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); + processCB->processID, taskCB->taskID, mapBase, mapSize, ret); } #ifdef LOSCFG_KERNEL_LITEIPC @@ -489,189 +497,197 @@ LITE_OS_SEC_TEXT VOID OsTaskResourcesToFree(LosTaskCB *taskCB) #endif if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { - topOfStack = taskCB->topOfStack; + topOfStack = taskCB->topOfStack; // ȡջջַ taskCB->topOfStack = 0; #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - syncSignal = taskCB->syncSignal; + syncSignal = taskCB->syncSignal; // ȡͬź taskCB->syncSignal = LOSCFG_BASE_IPC_SEM_LIMIT; #endif - OsTaskKernelResourcesToFree(syncSignal, topOfStack); + OsTaskKernelResourcesToFree(syncSignal, topOfStack); // ͷںԴ SCHEDULER_LOCK(intSave); - OsClearSigInfoTmpList(&(taskCB->sig)); - OsInsertTCBToFreeList(taskCB); + 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) + +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; + taskCB->stackPointer = (VOID*)stackPtr; // Ķջָ + taskCB->args[0] = initParam->auwArgs[0]; /* 0~3: just for args array index */ // IJ + 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; - taskCB->cpuAffiMask = (initParam->usCpuAffiMask) ? - initParam->usCpuAffiMask : LOSCFG_KERNEL_CPU_MASK; + 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)); + LOS_ListInit(&(taskCB->msgListHead)); // ʼϢб #endif - taskCB->policy = (initParam->policy == LOS_SCHED_FIFO) ? LOS_SCHED_FIFO : LOS_SCHED_RR; - taskCB->taskStatus = OS_TASK_STATUS_INIT; + 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; + 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; - LOS_ListInit(&taskCB->lockList); - SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME); + 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) +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; + UINT32 intSave; // ж״̬ı + UINT32 ret; // ֵ + UINT32 numCount; // ̼߳ + UINT16 mode; // ģʽ + LosProcessCB* processCB = NULL; // ̿ƿָ - OsTaskCBInitBase(taskCB, stackPtr, topStack, initParam); + OsTaskCBInitBase(taskCB, stackPtr, topStack, initParam); // ʼƿĻϢ - SCHEDULER_LOCK(intSave); - processCB = OS_PCB_FROM_PID(initParam->processID); - taskCB->processID = processCB->processID; - 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); + 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) { - processCB->threadGroupID = taskCB->taskID; + if (!processCB->threadNumber) { // ̵߳Ϊ0 + processCB->threadGroupID = taskCB->taskID; // ý̵߳IDΪǰID } - processCB->threadNumber++; + processCB->threadNumber++; // ߳1 - numCount = processCB->threadCount; - processCB->threadCount++; - SCHEDULER_UNLOCK(intSave); + numCount = processCB->threadCount; // ȡ̵̼߳ + processCB->threadCount++; // ̼߳1 - if (initParam->pcName != NULL) { - ret = (UINT32)OsSetTaskName(taskCB, initParam->pcName, FALSE); + 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) { + 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) +LITE_OS_SEC_TEXT LosTaskCB* OsGetFreeTaskCB(VOID) { - UINT32 intSave; - LosTaskCB *taskCB = NULL; + 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"); + 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); + (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); + taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_losFreeTask)); // ӿлȡһƿ + LOS_ListDelete(LOS_DL_LIST_FIRST(&g_losFreeTask)); // ӿɾƿ + SCHEDULER_UNLOCK(intSave); // ж - return taskCB; + return taskCB; // ػȡĿƿָ } -LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S *initParam) + +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; + UINT32 intSave, errRet; // ж״̬ıֵ + VOID* topStack = NULL; // ջָ + VOID* stackPtr = NULL; // ջָ + LosTaskCB* taskCB = NULL; // ƿָ + VOID* pool = NULL; // ڴָ - errRet = OsTaskCreateParamCheck(taskID, initParam, &pool); + errRet = OsTaskCreateParamCheck(taskID, initParam, &pool); // 񴴽ĺϷ if (errRet != LOS_OK) { return errRet; } - taskCB = OsGetFreeTaskCB(); + taskCB = OsGetFreeTaskCB(); // ȡһеƿ if (taskCB == NULL) { errRet = LOS_ERRNO_TSK_TCB_UNAVAILABLE; goto LOS_ERREND; } - errRet = OsTaskSyncCreate(taskCB); + errRet = OsTaskSyncCreate(taskCB); // ͬ if (errRet != LOS_OK) { goto LOS_ERREND_REWIND_TCB; } - OsTaskStackAlloc(&topStack, initParam->uwStackSize, pool); + 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); + 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); + OsConsoleIDSetHook(taskCB->taskID, OsCurrTaskGet()->taskID); // ÿ̨IDĹӺ } - *taskID = taskCB->taskID; - OsHookCall(LOS_HOOK_TYPE_TASK_CREATE, taskCB); + *taskID = taskCB->taskID; // ID + OsHookCall(LOS_HOOK_TYPE_TASK_CREATE, taskCB); // 񴴽ĹӺ return LOS_OK; LOS_ERREND_TCB_INIT: - (VOID)LOS_MemFree(pool, topStack); + (VOID)LOS_MemFree(pool, topStack); // ͷջڴ LOS_ERREND_REWIND_SYNC: #ifdef LOSCFG_KERNEL_SMP_TASK_SYNC - OsTaskSyncDestroy(taskCB->syncSignal); + OsTaskSyncDestroy(taskCB->syncSignal); // ͬ #endif LOS_ERREND_REWIND_TCB: SCHEDULER_LOCK(intSave); - OsInsertTCBToFreeList(taskCB); + OsInsertTCBToFreeList(taskCB); // ƿ SCHEDULER_UNLOCK(intSave); LOS_ERREND: return errRet; } -LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam) +LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32* taskID, TSK_INIT_PARAM_S* initParam) { - UINT32 ret; - UINT32 intSave; - LosTaskCB *taskCB = NULL; + UINT32 ret; // ֵ + UINT32 intSave; // ж״̬ı + LosTaskCB* taskCB = NULL; // ƿָ if (initParam == NULL) { return LOS_ERRNO_TSK_PTR_NULL; @@ -682,72 +698,75 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *in } if (OsProcessIsUserMode(OsCurrProcessGet())) { - initParam->processID = OsGetKernelInitProcessID(); - } else { - initParam->processID = OsCurrProcessGet()->processID; + 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); + ret = LOS_TaskCreateOnly(taskID, initParam); // 񴴽 if (ret != LOS_OK) { return ret; } - taskCB = OS_TCB_FROM_TID(*taskID); + taskCB = OS_TCB_FROM_TID(*taskID); // IDȡƿָ SCHEDULER_LOCK(intSave); - OsSchedTaskEnQueue(taskCB); + 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); + LOS_MpSchedule(OS_MP_CPU_ALL); // ദ if (OS_SCHEDULER_ACTIVE) { - LOS_Schedule(); + 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; + 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); + taskCB = OS_TCB_FROM_TID(taskID); // IDȡƿָ SCHEDULER_LOCK(intSave); - /* clear pending signal */ + /* ź */ 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)) { + } + 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); + OsSchedTaskEnQueue(taskCB); // ȶ if (OS_SCHEDULER_ACTIVE) { needSched = TRUE; } } SCHEDULER_UNLOCK(intSave); - LOS_MpSchedule(OS_MP_CPU_ALL); + LOS_MpSchedule(OS_MP_CPU_ALL); // ദ if (needSched) { - LOS_Schedule(); + LOS_Schedule(); // } return LOS_OK; @@ -766,13 +785,13 @@ LOS_ERREND: * 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) +LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(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()) { taskCB->signal = SIGNAL_SUSPEND; LOS_MpSchedule(taskCB->currCpu); @@ -781,13 +800,13 @@ LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB *taskCB, UIN #endif if (!OsPreemptableInSched()) { - /* Suspending the current core's running task */ + /* ڵڼֹռǰе */ *ret = LOS_ERRNO_TSK_SUSPEND_LOCKED; return FALSE; } if (OS_INT_ACTIVE) { - /* suspend running task in interrupt */ + /* жйе */ taskCB->signal = SIGNAL_SUSPEND; return FALSE; } @@ -795,10 +814,10 @@ LITE_OS_SEC_TEXT_INIT STATIC BOOL OsTaskSuspendCheckOnRun(LosTaskCB *taskCB, UIN return TRUE; } -LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB *taskCB) +LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB* taskCB) { - UINT32 errRet; - UINT16 tempStatus; + UINT32 errRet; // ֵ + UINT16 tempStatus; // ʱ洢״̬ tempStatus = taskCB->taskStatus; if (tempStatus & OS_TASK_STATUS_UNUSED) { @@ -815,55 +834,56 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsTaskSuspend(LosTaskCB *taskCB) } if (tempStatus & OS_TASK_STATUS_READY) { - OsSchedTaskDeQueue(taskCB); + OsSchedTaskDeQueue(taskCB); // ӵȶƳ } taskCB->taskStatus |= OS_TASK_STATUS_SUSPENDED; - OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB); + OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB); // ĹӺ if (taskCB == OsCurrTaskGet()) { - OsSchedResched(); + OsSchedResched(); // } return LOS_OK; } + LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID) { - UINT32 intSave; - LosTaskCB *taskCB = NULL; - UINT32 errRet; + 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); + 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); + errRet = OsTaskSuspend(taskCB); // ùĺ SCHEDULER_UNLOCK(intSave); return errRet; } -STATIC INLINE VOID OsTaskStatusUnusedSet(LosTaskCB *taskCB) +STATIC INLINE VOID OsTaskStatusUnusedSet(LosTaskCB* taskCB) { - taskCB->taskStatus |= OS_TASK_STATUS_UNUSED; - taskCB->eventMask = 0; + taskCB->taskStatus |= OS_TASK_STATUS_UNUSED; // ״̬Ϊδʹ + taskCB->eventMask = 0; // ¼ - OS_MEM_CLEAR(taskCB->taskID); + OS_MEM_CLEAR(taskCB->taskID); // ID } -STATIC INLINE VOID OsTaskReleaseHoldLock(LosProcessCB *processCB, LosTaskCB *taskCB) +STATIC INLINE VOID OsTaskReleaseHoldLock(LosProcessCB* processCB, LosTaskCB* taskCB) { - LosMux *mux = NULL; - UINT32 ret; + 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); + ret = OsMuxUnlockUnsafe(taskCB, mux, NULL); // еĻ if (ret != LOS_OK) { LOS_ListDelete(&mux->holdList); PRINT_ERR("mux ulock failed! : %u\n", ret); @@ -871,29 +891,31 @@ STATIC INLINE VOID OsTaskReleaseHoldLock(LosProcessCB *processCB, LosTaskCB *tas } if (processCB->processMode == OS_USER_MODE) { - OsTaskJoinPostUnsafe(taskCB); + OsTaskJoinPostUnsafe(taskCB); // û̬˳ʱ #ifdef LOSCFG_KERNEL_VM - OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL); + OsFutexNodeDeleteFromFutexHash(&taskCB->futex, TRUE, NULL, NULL); // FutexϣɾFutexڵ #endif } - OsTaskSyncWake(taskCB); + OsTaskSyncWake(taskCB); // ѵȴ + + return; } -LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB *runTask) +LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB* runTask) { - LosProcessCB *processCB = OS_PCB_FROM_PID(runTask->processID); + LosProcessCB* processCB = OS_PCB_FROM_PID(runTask->processID); // ȡ̵Ľ̿ƿָ - OsTaskReleaseHoldLock(processCB, runTask); - OsTaskStatusUnusedSet(runTask); + 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); + LOS_ListDelete(&runTask->threadList); // ߳ɾ + processCB->threadNumber--; // ̵߳һ + LOS_ListTailInsert(&g_taskRecycleList, &runTask->pendList); // + OsEventWriteUnsafe(&g_resourceEvent, OS_RESOURCE_EVENT_FREE, FALSE, NULL); // Դ¼֪ͨ - OsSchedResched(); + OsSchedResched(); // return; } @@ -906,7 +928,8 @@ LITE_OS_SEC_TEXT VOID OsRunTaskToDelete(LosTaskCB *runTask) * 3. Do the deletion in hard-irq * then LOS_TaskDelete will directly return with 'ret' value. */ -STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB *taskCB, UINT32 *ret) + +STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB* taskCB, UINT32* ret) { /* init default out return value */ *ret = LOS_OK; @@ -915,9 +938,9 @@ STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB *taskCB, UINT32 *ret) /* ASYNCHRONIZED. No need to do task lock checking */ if (taskCB->currCpu != ArchCurrCpuid()) { /* - * the task is running on another cpu. - * mask the target task with "kill" signal, and trigger mp schedule - * which might not be essential but the deletion could more in time. + * һCPUС + * ʹ"kill"źĿ񣬲ദȣ + * ܲDZģɾԸʱ */ taskCB->signal = SIGNAL_KILL; LOS_MpSchedule(taskCB->currCpu); @@ -927,15 +950,15 @@ STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB *taskCB, UINT32 *ret) #endif if (!OsPreemptableInSched()) { - /* If the task is running and scheduler is locked then you can not delete it */ + /* ҵ޷ɾ */ *ret = LOS_ERRNO_TSK_DELETE_LOCKED; return FALSE; } if (OS_INT_ACTIVE) { /* - * delete running task in interrupt. - * mask "kill" signal and later deletion will be handled. + * жɾе + * "kill"źţԺɾ */ taskCB->signal = SIGNAL_KILL; return FALSE; @@ -944,35 +967,35 @@ STATIC BOOL OsRunTaskToDeleteCheckOnRun(LosTaskCB *taskCB, UINT32 *ret) return TRUE; } -STATIC VOID OsTaskDeleteInactive(LosProcessCB *processCB, LosTaskCB *taskCB) +STATIC VOID OsTaskDeleteInactive(LosProcessCB* processCB, LosTaskCB* taskCB) { - LosMux *mux = (LosMux *)taskCB->taskMux; - UINT16 taskStatus = taskCB->taskStatus; + LosMux* mux = (LosMux*)taskCB->taskMux; // ָ + UINT16 taskStatus = taskCB->taskStatus; // ״̬ LOS_ASSERT(!(taskStatus & OS_TASK_STATUS_RUNNING)); - OsTaskReleaseHoldLock(processCB, taskCB); + OsTaskReleaseHoldLock(processCB, taskCB); // ͷеԴ - OsSchedTaskExit(taskCB); + OsSchedTaskExit(taskCB); // ˳ if (taskStatus & OS_TASK_STATUS_PENDING) { if (LOS_MuxIsValid(mux) == TRUE) { - OsMuxBitmapRestore(mux, taskCB, (LosTaskCB *)mux->owner); + OsMuxBitmapRestore(mux, taskCB, (LosTaskCB*)mux->owner); } } - OsTaskStatusUnusedSet(taskCB); + OsTaskStatusUnusedSet(taskCB); // ״̬Ϊδʹ - LOS_ListDelete(&taskCB->threadList); - processCB->threadNumber--; - LOS_ListTailInsert(&g_taskRecycleList, &taskCB->pendList); + 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) +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; + 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; @@ -984,15 +1007,15 @@ LITE_OS_SEC_TEXT UINT32 OsTaskDeleteUnsafe(LosTaskCB *taskCB, UINT32 status, UIN } if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) { - OsTaskDeleteInactive(processCB, taskCB); + OsTaskDeleteInactive(processCB, taskCB); // еɾ SCHEDULER_UNLOCK(intSave); OsWriteResourceEvent(OS_RESOURCE_EVENT_FREE); return errRet; } - OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, taskCB); + OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, taskCB); // ɾĹӺ if (mode == OS_USER_MODE) { SCHEDULER_UNLOCK(intSave); - OsTaskResourcesToFree(taskCB); + OsTaskResourcesToFree(taskCB); // ͷԴ SCHEDULER_LOCK(intSave); } @@ -1001,7 +1024,7 @@ LITE_OS_SEC_TEXT UINT32 OsTaskDeleteUnsafe(LosTaskCB *taskCB, UINT32 status, UIN #else LOS_ASSERT(OsPercpuGet()->taskLockCnt == 0); #endif - OsRunTaskToDelete(taskCB); + OsRunTaskToDelete(taskCB); // еɾ EXIT: SCHEDULER_UNLOCK(intSave); @@ -1012,8 +1035,8 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID) { UINT32 intSave; UINT32 ret; - LosTaskCB *taskCB = NULL; - LosProcessCB *processCB = NULL; + LosTaskCB* taskCB = NULL; + LosProcessCB* processCB = NULL; if (OS_TID_CHECK_INVALID(taskID)) { return LOS_ERRNO_TSK_ID_INVALID; @@ -1023,7 +1046,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID) return LOS_ERRNO_TSK_YIELD_IN_INT; } - taskCB = OS_TCB_FROM_TID(taskID); + taskCB = OS_TCB_FROM_TID(taskID); // ȡƿָ SCHEDULER_LOCK(intSave); if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { ret = LOS_ERRNO_TSK_NOT_CREATED; @@ -1036,11 +1059,11 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID) return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK; } - processCB = OS_PCB_FROM_PID(taskCB->processID); + 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); + OsProcessExit(taskCB, OS_PRO_EXIT_OK); // ˳ return LOS_OK; } @@ -1048,7 +1071,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID) OS_GOTO_ERREND(); } - return OsTaskDeleteUnsafe(taskCB, OS_PRO_EXIT_OK, intSave); + return OsTaskDeleteUnsafe(taskCB, OS_PRO_EXIT_OK, intSave); // ɾ LOS_ERREND: SCHEDULER_UNLOCK(intSave); @@ -1058,14 +1081,14 @@ LOS_ERREND: LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick) { UINT32 intSave; - LosTaskCB *runTask = NULL; + 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(); + runTask = OsCurrTaskGet(); // ȡǰƿָ if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { OsBackTrace(); return LOS_ERRNO_TSK_OPERATE_SYSTEM_TASK; @@ -1074,14 +1097,14 @@ LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick) if (!OsPreemptable()) { return LOS_ERRNO_TSK_DELAY_IN_LOCK; } - OsHookCall(LOS_HOOK_TYPE_TASK_DELAY, tick); + OsHookCall(LOS_HOOK_TYPE_TASK_DELAY, tick); // ʱĹӺ if (tick == 0) { - return LOS_TaskYield(); + return LOS_TaskYield(); // óCPU } SCHEDULER_LOCK(intSave); - OsSchedDelay(runTask, tick); - OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, runTask); + OsSchedDelay(runTask, tick); // ʱ + OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, runTask); // ƶʱеĹӺ SCHEDULER_UNLOCK(intSave); return LOS_OK; @@ -1090,25 +1113,26 @@ LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick) LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID) { UINT32 intSave; - LosTaskCB *taskCB = NULL; + LosTaskCB* taskCB = NULL; UINT16 priority; if (OS_TID_CHECK_INVALID(taskID)) { return (UINT16)OS_INVALID; } - taskCB = OS_TCB_FROM_TID(taskID); + 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; + priority = taskCB->priority; // ȡȼ SCHEDULER_UNLOCK(intSave); return priority; } + LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio) { UINT32 intSave; diff --git a/core/los_tick.c b/core/los_tick.c index b5c2794..7544c0b 100644 --- a/core/los_tick.c +++ b/core/los_tick.c @@ -29,6 +29,22 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + /* + + g_sysClockϵͳʱƵʣڼ¼ϵͳʱƵʡ + + g_tickPerSecondÿڼ¼ÿӷĽ + + g_cycle2NsScaleѭڵűڽתΪ롣 + + g_tickSpinģڱģķʡ + + OsTickHandler()жϴصIJںڲܻһЩضƽ̨IJԼ¼ݡ⶯̬VDSOʱֵȡȻOsSchedTick()ĽIJ + */ + + #include "los_tick_pri.h" #include "los_swtmr_pri.h" #include "los_sched_pri.h" @@ -36,17 +52,22 @@ #include "los_vdso.h" #endif - + // ϵͳʱƵ LITE_OS_SEC_DATA_INIT UINT32 g_sysClock; + +// ÿ LITE_OS_SEC_DATA_INIT UINT32 g_tickPerSecond; + +// ѭڵű LITE_OS_SEC_BSS DOUBLE g_cycle2NsScale; -/* spinlock for task module */ +// ģ LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_tickSpin); /* * Description : Tick interruption handler */ + // жϴ LITE_OS_SEC_TEXT VOID OsTickHandler(VOID) { #ifdef LOSCFG_SCHED_TICK_DEBUG @@ -61,6 +82,10 @@ LITE_OS_SEC_TEXT VOID OsTickHandler(VOID) HalClockIrqClear(); /* diff from every platform */ #endif + // ĽĴ OsSchedTick(); } + + + diff --git a/process1520-2000.c b/process1520-2000.c new file mode 100644 index 0000000..ebd7a64 --- /dev/null +++ b/process1520-2000.c @@ -0,0 +1,460 @@ +STATIC UINT32 OsLoadUserInit(LosProcessCB *processCB) +{ + /* userInitTextStart ----- + * | user text |//定义起始位置的指针变量// + * + * | user data | initSize + * userInitBssStart ---//定义结束位置的指针变量// + * | user bss | initBssSize + * userInitEnd --- ----- + */ + errno_t errRet; + INT32 ret; + CHAR *userInitTextStart = (CHAR *)&__user_init_entry; + CHAR *userInitBssStart = (CHAR *)&__user_init_bss; + CHAR *userInitEnd = (CHAR *)&__user_init_end; + UINT32 initBssSize = userInitEnd - userInitBssStart;//计算 BSS 段(未初始化数据段)的大小 initBssSize// + UINT32 initSize = userInitEnd - userInitTextStart;//计算和整个初始化段(包括 text、data 和 bss)的大小 // + VOID *userBss = NULL; + VOID *userText = NULL; + + if ((LOS_Align((UINTPTR)userInitTextStart, PAGE_SIZE) != (UINTPTR)userInitTextStart) || + (LOS_Align((UINTPTR)userInitEnd, PAGE_SIZE) != (UINTPTR)userInitEnd)) { + return LOS_EINVAL;//检查 userInitTextStart 和 userInitEnd 是否都按页对齐// + } + + if ((initSize == 0) || (initSize <= initBssSize)) { + return LOS_EINVAL;//检查 initSize 是否为零或者小于等于 initBssSize,如果是,则返回错误码 LOS_EINVAL// + } + + userText = LOS_PhysPagesAllocContiguous(initSize >> PAGE_SHIFT); + if (userText == NULL) { + return LOS_NOK;//使用 LOS_PhysPagesAllocContiguous 函数为用户空间初始化段分配连续的物理页面,并将地址赋值给 userText// + } + + errRet = memcpy_s(userText, initSize, (VOID *)&__user_init_load_addr, initSize - initBssSize); + if (errRet != EOK) { + PRINT_ERR("Load user init text, data and bss failed! err : %d\n", errRet); + goto ERROR;//使用 memcpy_s 将初始化段的 text 和 data 部分从 __user_init_load_addr 复制到新分配的 userText 指向的内存区域// + } + ret = LOS_VaddrToPaddrMmap(processCB->vmSpace, (VADDR_T)(UINTPTR)userInitTextStart, LOS_PaddrQuery(userText), + initSize, VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE | + VM_MAP_REGION_FLAG_FIXED | VM_MAP_REGION_FLAG_PERM_EXECUTE | + VM_MAP_REGION_FLAG_PERM_USER); + if (ret < 0) { + PRINT_ERR("Mmap user init text, data and bss failed! err : %d\n", ret); + goto ERROR;//使用 LOS_VaddrToPaddrMmap 函数将新分配的物理页面映射到进程的虚拟地址空间// + } + + /* The User init boot segment may not actually exist */ + if (initBssSize != 0) { + userBss = (VOID *)((UINTPTR)userText + userInitBssStart - userInitTextStart); + errRet = memset_s(userBss, initBssSize, 0, initBssSize); + if (errRet != EOK) { + PRINT_ERR("memset user init bss failed! err : %d\n", errRet); + goto ERROR;//如果存在 BSS 段(initBssSize 不为 0),则使用 memset_s 函数将 BSS 段的内存清零// + } + } + + return LOS_OK; + +ERROR: + (VOID)LOS_PhysPagesFreeContiguous(userText, initSize >> PAGE_SHIFT); + return LOS_NOK; +} + +LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID) +{ + UINT32 ret; + UINT32 size; + TSK_INIT_PARAM_S param = { 0 }; + VOID *stack = NULL; + + LosProcessCB *processCB = OS_PCB_FROM_PID(g_userInitProcess); + ret = OsProcessCreateInit(processCB, OS_USER_MODE, "Init", OS_PROCESS_USERINIT_PRIORITY); + if (ret != LOS_OK) { + return ret; + } + + ret = OsLoadUserInit(processCB); + if (ret != LOS_OK) { + goto ERROR; + } + + stack = OsUserInitStackAlloc(processCB, &size); + if (stack == NULL) { + PRINT_ERR("Alloc user init process user stack failed!\n"); + goto ERROR;//如果在复制或内存映射过程中发生错误,会跳转到 ERROR 标签处理错误情况,释放已分配资源并返回错误码// + } + + param.pfnTaskEntry = (TSK_ENTRY_FUNC)(CHAR *)&__user_init_entry; + param.userParam.userSP = (UINTPTR)stack + size; + param.userParam.userMapBase = (UINTPTR)stack; + param.userParam.userMapSize = size; + param.uwResved = OS_TASK_FLAG_PTHREAD_JOIN; + ret = OsUserInitProcessStart(g_userInitProcess, ¶m); + if (ret != LOS_OK) { + (VOID)OsUnMMap(processCB->vmSpace, param.userParam.userMapBase, param.userParam.userMapSize); + goto ERROR; + } + + return LOS_OK;//如果一切顺利,函数最后返回 LOS_OK,表示用户空间初始化程序加载成功// + +ERROR: + OsDeInitPCB(processCB);//在发生错误时,调用此函数来清理进程控制块// + return ret;//返回错误码// +} + +STATIC UINT32 OsCopyUser(LosProcessCB *childCB, LosProcessCB *parentCB) +{ +#ifdef LOSCFG_SECURITY_CAPABILITY//执行用户信息的复制// + UINT32 size = sizeof(User) + sizeof(UINT32) * (parentCB->user->groupNumber - 1);//算需要复制的用户信息所需的内存大小// + childCB->user = LOS_MemAlloc(m_aucSysMem1, size);//为子进程分配内存来存储用户信息// + if (childCB->user == NULL) { + return LOS_ENOMEM;//如果分配失败,返回 LOS_ENOMEM 表示内存不足// + } + + (VOID)memcpy_s(childCB->user, size, parentCB->user, size);//使用 memcpy_s 将父进程的用户信息复制到子进程// +#endif + return LOS_OK;//返回 LOS_OK 表示成功// +} + +STATIC VOID OsInitCopyTaskParam(LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size, + TSK_INIT_PARAM_S *childPara) +{ + LosTaskCB *mainThread = NULL; + UINT32 intSave;//初始化子进程的任务参数// + + SCHEDULER_LOCK(intSave); + mainThread = OsCurrTaskGet();//锁定调度器以保证线程安全// + + if (OsProcessIsUserMode(childProcessCB)) { + childPara->pfnTaskEntry = mainThread->taskEntry; + childPara->uwStackSize = mainThread->stackSize; + childPara->userParam.userArea = mainThread->userArea; + childPara->userParam.userMapBase = mainThread->userMapBase; + childPara->userParam.userMapSize = mainThread->userMapSize;//根据子进程是否为用户模式,设置任务入口点、堆栈大小以及其他用户特定的参数// + } else { + childPara->pfnTaskEntry = (TSK_ENTRY_FUNC)entry; + childPara->uwStackSize = size; + } + childPara->pcName = (CHAR *)name; + childPara->policy = mainThread->policy; + 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;//如果当前任务支持线程的 join 操作或者是 detached 状态,则相应地设置标志位// + } + + SCHEDULER_UNLOCK(intSave);//解锁调度器// +} + +STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size) +{//创建一个新的任务,作为子进程的主线程// + LosTaskCB *runTask = OsCurrTaskGet(); + TSK_INIT_PARAM_S childPara = { 0 }; + UINT32 ret; + UINT32 intSave; + UINT32 taskID; + + OsInitCopyTaskParam(childProcessCB, name, entry, size, &childPara); + + ret = LOS_TaskCreateOnly(&taskID, &childPara);//调用 LOS_TaskCreateOnly 来创建任务,仅创建任务而不立即运行// + if (ret != LOS_OK) { + if (ret == LOS_ERRNO_TSK_TCB_UNAVAILABLE) { + return LOS_EAGAIN; + } + return LOS_ENOMEM;//如果任务创建失败,根据错误类型返回相应的错误码(如 LOS_EAGAIN 表示资源暂时不可用,LOS_ENOMEM 表示内存不足)// + } + + LosTaskCB *childTaskCB = OS_TCB_FROM_TID(taskID);//获取新创建任务的任务控制块指针// + childTaskCB->taskStatus = runTask->taskStatus; + if (childTaskCB->taskStatus & OS_TASK_STATUS_RUNNING) { + childTaskCB->taskStatus &= ~OS_TASK_STATUS_RUNNING; + } else { + if (OS_SCHEDULER_ACTIVE) { + LOS_Panic("Clone thread status not running error status: 0x%x\n", childTaskCB->taskStatus); + }//如果子任务的状态为运行状态,则清除运行状态位// + childTaskCB->taskStatus &= ~OS_TASK_STATUS_UNUSED; + childProcessCB->priority = OS_PROCESS_PRIORITY_LOWEST;//如果调度器处于激活状态并且子任务不在运行状态,触发内核恐慌// + } + + if (OsProcessIsUserMode(childProcessCB)) { + SCHEDULER_LOCK(intSave); + OsUserCloneParentStack(childTaskCB->stackPointer, runTask->topOfStack, runTask->stackSize); + SCHEDULER_UNLOCK(intSave); + } + return LOS_OK; +} + +STATIC UINT32 OsCopyParent(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB) +{ + UINT32 ret; + UINT32 intSave; + LosProcessCB *parentProcessCB = NULL; + + SCHEDULER_LOCK(intSave);//锁定调度器以保证线程安全// + childProcessCB->priority = runProcessCB->priority; + + if (flags & CLONE_PARENT) { + parentProcessCB = OS_PCB_FROM_PID(runProcessCB->parentProcessID); + } else { + parentProcessCB = runProcessCB; + }//根据 flags 中的 CLONE_PARENT 位决定子进程的父进程是当前进程的父进程还是当前进程本身// + childProcessCB->parentProcessID = parentProcessCB->processID; + LOS_ListTailInsert(&parentProcessCB->childrenList, &childProcessCB->siblingList); + childProcessCB->group = parentProcessCB->group; + LOS_ListTailInsert(&parentProcessCB->group->processList, &childProcessCB->subordinateGroupList); + ret = OsCopyUser(childProcessCB, parentProcessCB);//调用 OsCopyUser 函数复制用户信息// + + SCHEDULER_UNLOCK(intSave);//解锁调度器// + return ret; +} + +STATIC UINT32 OsCopyMM(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB) +{ + status_t status; + UINT32 intSave; + + if (!OsProcessIsUserMode(childProcessCB)) { + return LOS_OK;//如果子进程不是用户模式,直接返回 LOS_OK// + } + + if (flags & CLONE_VM) { + SCHEDULER_LOCK(intSave); + childProcessCB->vmSpace->archMmu.virtTtb = runProcessCB->vmSpace->archMmu.virtTtb; + childProcessCB->vmSpace->archMmu.physTtb = runProcessCB->vmSpace->archMmu.physTtb; + SCHEDULER_UNLOCK(intSave); + return LOS_OK;//如果 flags 中的 CLONE_VM 位被设置,表示需要共享虚拟内存空间,那么将父进程的虚拟内存表指针复制给子进程,并返回 LOS_OK// + } + + status = LOS_VmSpaceClone(runProcessCB->vmSpace, childProcessCB->vmSpace); + if (status != LOS_OK) { + return LOS_ENOMEM; + } + return LOS_OK;//如果没有设置 CLONE_VM 位,则调用 LOS_VmSpaceClone 函数来克隆父进程的虚拟内存空间给子进程// +} + +STATIC UINT32 OsCopyFile(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB) +{ +#ifdef LOSCFG_FS_VFS + if (flags & CLONE_FILES) { + childProcessCB->files = runProcessCB->files; + } else { + childProcessCB->files = dup_fd(runProcessCB->files); + } + if (childProcessCB->files == NULL) { + return LOS_ENOMEM;//如果虚拟内存空间克隆失败,返回 LOS_ENOMEM 表示内存不足// + } +#endif + + childProcessCB->consoleID = runProcessCB->consoleID; + childProcessCB->umask = runProcessCB->umask; + return LOS_OK; +} + +STATIC UINT32 OsForkInitPCB(UINT32 flags, LosProcessCB *child, const CHAR *name, UINTPTR sp, UINT32 size) +{//初始化子进程的进程控制块(PCB)// + UINT32 ret; + LosProcessCB *run = OsCurrProcessGet(); + + ret = OsInitPCB(child, run->processMode, OS_PROCESS_PRIORITY_LOWEST, name); + if (ret != LOS_OK) { + return ret; + }//调用 OsInitPCB 来初始化 PCB 的基本信息// + + ret = OsCopyParent(flags, child, run); + if (ret != LOS_OK) { + return ret; + } + + return OsCopyTask(flags, child, name, sp, size);//继续调用 OsCopyParent 复制父进程的某些资源给子进程,最后调用 OsCopyTask 来复制任务相关的资源// +} + +STATIC UINT32 OsChildSetProcessGroupAndSched(LosProcessCB *child, LosProcessCB *run) +{//用于将子进程设置到正确的进程组,并将其加入到调度队列中// + UINT32 intSave; + UINT32 ret; + ProcessGroup *group = NULL; + + SCHEDULER_LOCK(intSave); + if (run->group->groupID == OS_USER_PRIVILEGE_PROCESS_GROUP) { + ret = OsSetProcessGroupIDUnsafe(child->processID, child->processID, &group); + if (ret != LOS_OK) { + SCHEDULER_UNLOCK(intSave); + return LOS_ENOMEM; + } + }//如果父进程属于用户特权进程组,则会为子进程创建一个新的进程组// + + OsSchedTaskEnQueue(OS_TCB_FROM_TID(child->threadGroupID)); + SCHEDULER_UNLOCK(intSave); + + (VOID)LOS_MemFree(m_aucSysMem1, group); + return LOS_OK;//将子进程的主线程加入调度队列,并释放之前可能分配的进程组内存// +} + +STATIC UINT32 OsCopyProcessResources(UINT32 flags, LosProcessCB *child, LosProcessCB *run) +{//负责复制父进程的资源给子进程,包括内存管理单元、文件描述符等// + UINT32 ret; + + ret = OsCopyMM(flags, child, run); + if (ret != LOS_OK) { + return ret; + } + + ret = OsCopyFile(flags, child, run); + if (ret != LOS_OK) { + return ret; + }//如果系统配置了 LOSCFG_KERNEL_LITEIPC,则还需要重新初始化 IPC 资源// + +#ifdef LOSCFG_KERNEL_LITEIPC + if (OsProcessIsUserMode(child)) { + ret = LiteIpcPoolReInit(&child->ipcInfo, (const ProcIpcInfo *)(&run->ipcInfo)); + if (ret != LOS_OK) { + return LOS_ENOMEM; + } + } +#endif + +#ifdef LOSCFG_SECURITY_CAPABILITY + OsCopyCapability(run, child); +#endif + + return LOS_OK;//如果配置了 LOSCFG_SECURITY_CAPABILITY,还需要复制安全能力// +} + +STATIC INT32 OsCopyProcess(UINT32 flags, const CHAR *name, UINTPTR sp, UINT32 size) +{ + UINT32 intSave, ret, processID; + LosProcessCB *run = OsCurrProcessGet(); + + LosProcessCB *child = OsGetFreePCB(); + if (child == NULL) { + return -LOS_EAGAIN; + } + processID = child->processID;//获取一个空闲的 PCB,然后通过调用 OsForkInitPCB 初始化 PCB// + + ret = OsForkInitPCB(flags, child, name, sp, size); + if (ret != LOS_OK) { + goto ERROR_INIT; + } + + ret = OsCopyProcessResources(flags, child, run); + if (ret != LOS_OK) { + goto ERROR_TASK; + }//通过 OsCopyProcessResources 复制资源// + + ret = OsChildSetProcessGroupAndSched(child, run); + if (ret != LOS_OK) { + goto ERROR_TASK; + } + + LOS_MpSchedule(OS_MP_CPU_ALL); + if (OS_SCHEDULER_ACTIVE) { + LOS_Schedule(); + } + + return processID;//通过 OsChildSetProcessGroupAndSched 设置进程组和调度。如果任何步骤失败,它会跳转到错误处理部分并释放已分配的资源// + +ERROR_TASK: + SCHEDULER_LOCK(intSave); + (VOID)OsTaskDeleteUnsafe(OS_TCB_FROM_TID(child->threadGroupID), OS_PRO_EXIT_OK, intSave);//调用来删除已经创建但未能成功完成初始化的子进程的主线程// +ERROR_INIT: + OsDeInitPCB(child); + return -ret;//调用来释放和反初始化进程控制块(PCB)// +} + +LITE_OS_SEC_TEXT INT32 OsClone(UINT32 flags, UINTPTR sp, UINT32 size) +{ + UINT32 cloneFlag = CLONE_PARENT | CLONE_THREAD | CLONE_VFORK | CLONE_VM; + + if (flags & (~cloneFlag)) { + PRINT_WARN("Clone dont support some flags!\n");//检查传入的 flags 参数,并确保没有不支持的标志被设置。如果有不支持的标志,它会打印警告// + } + + return OsCopyProcess(cloneFlag & flags, NULL, sp, size);//调用 OsCopyProcess 来实际创建一个新的进程或线程// +} + +LITE_OS_SEC_TEXT INT32 LOS_Fork(UINT32 flags, const CHAR *name, const TSK_ENTRY_FUNC entry, UINT32 stackSize) +{//供了一个创建新进程的接口,类似于 UNIX 系统中的 fork 系统调用// + UINT32 cloneFlag = CLONE_PARENT | CLONE_THREAD | CLONE_VFORK | CLONE_FILES; + + if (flags & (~cloneFlag)) { + PRINT_WARN("Clone dont support some flags!\n"); + }//检查 flags 参数,确保没有不支持的标志被设置,并添加 CLONE_FILES 标志,以便子进程可以共享文件描述符表// + + flags |= CLONE_FILES; + return OsCopyProcess(cloneFlag & flags, name, (UINTPTR)entry, stackSize); +} +#else +LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID) +{ + return 0; +} +#endif//OsCopyProcess 函数来创建一个新的进程// + +LITE_OS_SEC_TEXT VOID LOS_Exit(INT32 status) +{//允许一个进程退出并释放资源// + UINT32 intSave; + + /* The exit of a kernel - state process must be kernel - state and all threads must actively exit */ + LosProcessCB *processCB = OsCurrProcessGet(); + SCHEDULER_LOCK(intSave);//如果当前进程是内核态进程且拥有多个线程,则不允许直接退出// + if (!OsProcessIsUserMode(processCB) && (processCB->threadNumber != 1)) { + SCHEDULER_UNLOCK(intSave); + PRINT_ERR("Kernel-state processes with multiple threads are not allowed to exit directly\n"); + return; + } + SCHEDULER_UNLOCK(intSave); + + OsTaskExitGroup((UINT32)status); + OsProcessExit(OsCurrTaskGet(), (UINT32)status);//如果条件允许,它会调用 OsTaskExitGroup 和 OsProcessExit 来完成退出流程// +} + +LITE_OS_SEC_TEXT INT32 LOS_GetUsedPIDList(UINT32 *pidList, INT32 pidMaxNum) +{//这个函数用于获取当前正在使用的所有进程的 PID 列表// + LosProcessCB *pcb = NULL; + INT32 num = 0; + UINT32 intSave; + UINT32 pid = 1; + + if (pidList == NULL) { + return 0; + }//它通过遍历所有可能的 PID 并检查对应的 PCB 是否正在使用来实现// + SCHEDULER_LOCK(intSave); + while (OsProcessIDUserCheckInvalid(pid) == false) { + pcb = OS_PCB_FROM_PID(pid); + pid++; + if (OsProcessIsUnused(pcb)) { + continue; + } + pidList[num] = pcb->processID; + num++; + if (num >= pidMaxNum) { + break; + } + } + SCHEDULER_UNLOCK(intSave); + return num;//如果 PCB 正在使用,它将该 PCB 的 PID 添加到 pidList 数组中,并返回找到的 PID 数量// +} + +#ifdef LOSCFG_FS_VFS +LITE_OS_SEC_TEXT struct fd_table_s *LOS_GetFdTable(UINT32 pid) +{//返回指定 PID 的进程的文件描述符表// + LosProcessCB *pcb = NULL; + struct files_struct *files = NULL;//它首先检查 PID 是否有效,然后获取对应的 PCB 和文件结构体 files// + + if (OS_PID_CHECK_INVALID(pid)) { + return NULL; + } + pcb = OS_PCB_FROM_PID(pid); + files = pcb->files; + if (files == NULL) { + return NULL; + } + + return files->fdt;//如果这些结构体有效,它返回文件描述符表 fdt// +} + diff --git a/process(800-1200).cpp b/process(800-1200).cpp new file mode 100644 index 0000000..32abce8 --- /dev/null +++ b/process(800-1200).cpp @@ -0,0 +1,426 @@ +```c +// 去掉初始化标签 +kerInitProcess->processStatus &= ~OS_PROCESS_STATUS_INIT; +g_processGroup = kerInitProcess->group; +LOS_ListInit(&g_processGroup->groupList); +OsCurrProcessSet(kerInitProcess); + +// 创建内核态0号进程 +LosProcessCB *idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess); +ret = OsInitPCB(idleProcess, OS_KERNEL_MODE, OS_TASK_PRIORITY_LOWEST, "KIdle"); +if (ret != LOS_OK) { + return ret; +} +idleProcess->parentProcessID = kerInitProcess->processID; +LOS_ListTailInsert(&kerInitProcess->childrenList, &idleProcess->siblingList); +idleProcess->group = kerInitProcess->group; +LOS_ListTailInsert(&kerInitProcess->group->processList, &idleProcess->subordinateGroupList); + +#ifdef LOSCFG_SECURITY_CAPABILITY +idleProcess->user = kerInitProcess->user; +#endif + +#ifdef LOSCFG_FS_VFS +idleProcess->files = kerInitProcess->files; +#endif + +// 创建空闲任务并将其指定给内核态0号进程 +ret = OsIdleTaskCreate(); +if (ret != LOS_OK) { + return ret; +} +idleProcess->threadGroupID = OsPercpuGet()->idleTaskID; + +return LOS_OK; +``` + +```c +// 进程调度参数检查 +STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 prio, UINT16 policy) +{ + if (OS_PID_CHECK_INVALID(pid)) { + return LOS_EINVAL; + } + + if (which != LOS_PRIO_PROCESS) { + return LOS_EINVAL; + } + + if (prio > OS_PROCESS_PRIORITY_LOWEST) { + return LOS_EINVAL; + } + + if (policy != LOS_SCHED_RR) { + return LOS_EINVAL; + } + + return LOS_OK; +} + +#ifdef LOSCFG_SECURITY_CAPABILITY +STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, UINT16 prio) +{ + LosProcessCB *runProcess = OsCurrProcessGet(); + + // 对于内核态进程直接通过检查 + if (!OsProcessIsUserMode(runProcess)) { + return TRUE; + } + + // 用户态进程可以降低自己的优先级 + if ((runProcess->processID == processCB->processID) && (prio > processCB->priority)) { + return TRUE; + } + + // 如果具有 CAP_SCHED_SETPRIORITY 权限,可以修改进程的优先级 + if (IsCapPermit(CAP_SCHED_SETPRIORITY)) { + return TRUE; + } + return FALSE; +} +#endif + +LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy) +{ + LosProcessCB *processCB = NULL; + BOOL needSched = FALSE; + UINT32 intSave; + INT32 ret; + + ret = OsProcessSchedlerParamCheck(which, pid, prio, policy); + if (ret != LOS_OK) { + return -ret; + } + + SCHEDULER_LOCK(intSave); + processCB = OS_PCB_FROM_PID(pid); + + // 如果进程未激活,则返回错误 + if (OsProcessIsInactive(processCB)) { + ret = LOS_ESRCH; + goto EXIT; + } + +#ifdef LOSCFG_SECURITY_CAPABILITY + // 如果权限不足,则返回错误 + if (!OsProcessCapPermitCheck(processCB, prio)) { + ret = LOS_EPERM; + goto EXIT; + } +#endif + + // 修改进程调度参数,判断是否需要进行调度 + needSched = OsSchedModifyProcessSchedParam(processCB, policy, prio); + SCHEDULER_UNLOCK(intSave); + + // 调度其他核上的进程 + LOS_MpSchedule(OS_MP_CPU_ALL); + + // 如果需要调度且调度器已经激活,则进行调度 + if (needSched && OS_SCHEDULER_ACTIVE) { + LOS_Schedule(); + } + return LOS_OK; + +EXIT: + SCHEDULER_UNLOCK(intSave); + return -ret; +} + +LITE_OS_SEC_TEXT INT32 LOS_SetProcessScheduler(INT32 pid, UINT16 policy, UINT16 prio) +{ + return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, prio, policy); +} + +LITE_OS_SEC_TEXT INT32 LOS_GetProcessScheduler(INT32 pid) +{ + UINT32 intSave; + + if (OS_PID_CHECK_INVALID(pid)) { + return -LOS_EINVAL; + } + + SCHEDULER_LOCK(intSave); + LosProcessCB *processCB = OS_PCB_FROM_PID(pid); + + // 如果进程未使用,则返回错误 + if (OsProcessIsUnused(processCB)) { + SCHEDULER_UNLOCK(intSave); + return -LOS_ESRCH; + } + + SCHEDULER_UNLOCK(intSave); + + return LOS_SCHED_RR; +} + +LITE_OS_SEC_TEXT INT32 LOS_SetProcessPriority(INT32 pid, UINT16 prio) +{ + return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, prio, LOS_GetProcessScheduler(pid)); +} + +LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid) +{ + LosProcessCB *processCB = NULL; + INT32 prio; + UINT32 intSave; + (VOID)which; + + if (OS_PID_CHECK_INVALID(pid)) { + return -LOS_EINVAL; + } + + if (which != LOS_PRIO_PROCESS) { + return -LOS_EINVAL; + } + + SCHEDULER_LOCK(intSave); + processCB = OS_PCB_FROM_PID(pid); + + // 如果进程未使用,则返回错误 + if (OsProcessIsUnused(processCB)) { + prio = -LOS_ESRCH; + goto OUT; + } + + prio = (INT32)processCB->priority; + +OUT: + SCHEDULER_UNLOCK(intSave); + return prio; +} + +LITE_OS_SEC_TEXT INT32 LOS_GetProcessPriority(INT32 pid) +{ + return OsGetProcessPriority(LOS_PRIO_PROCESS, pid); +} + +// 将运行任务插入等待列表 +STATIC VOID OsWaitInsertWaitListInOrder(LosTaskCB *runTask, LosProcessCB *processCB) +{ + LOS_DL_LIST *head = &processCB->waitList; + LOS_DL_LIST *list = head; + LosTaskCB *taskCB = NULL; + + if (runTask->waitFlag == OS_PROCESS_WAIT_GID) { + while (list->pstNext != head) { + taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list)); + + // 如果等待标记为 OS_PROCESS_WAIT_PRO,则继续查找下一个等待队列 + if (taskCB->waitFlag == OS_PROCESS_WAIT_PRO) { + list = list->pstNext; + continue; + } + break; + } + } else if (runTask->waitFlag == OS_PROCESS_WAIT_ANY) { + while (list->pstNext != head) { + taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list)); + + // 如果等待标记不为 OS_PROCESS_WAIT_ANY,则继续查找下一个等待队列 + if (taskCB->waitFlag != OS_PROCESS_WAIT_ANY) { + list = list->pstNext; + continue; + } + break; + } + } +} + +``` +// 等待指定的子进程退出 +STATIC UINT32 OsWaitSetFlag(const LosProcessCB *processCB, INT32 pid, LosProcessCB **child) +{ + LosProcessCB *childCB = NULL; + ProcessGroup *group = NULL; + LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务控制块 + UINT32 ret; + + if (pid > 0) { + // 等待具有指定进程号的子进程退出 + childCB = OsFindExitChildProcess(processCB, pid); // 查找具有指定进程号的已退出的子进程 + if (childCB != NULL) { + goto WAIT_BACK; // 子进程已退出,则跳转到WAIT_BACK标签处 + } + + ret = OsFindChildProcess(processCB, pid); // 查找具有指定进程号的子进程是否存在 + if (ret != LOS_OK) { + return LOS_ECHILD; // 没有找到指定进程号的子进程,返回错误码LOS_ECHILD + } + runTask->waitFlag = OS_PROCESS_WAIT_PRO; // 设置当前任务的等待标志为进程号 + runTask->waitID = pid; // 设置当前任务等待的进程号为指定进程号 + } else if (pid == 0) { + // 等待同一进程组中的任何子进程退出 + childCB = OsFindGroupExitProcess(processCB->group, OS_INVALID_VALUE); // 查找同一进程组中的已退出的子进程 + if (childCB != NULL) { + goto WAIT_BACK; // 子进程已退出,则跳转到WAIT_BACK标签处 + } + runTask->waitID = processCB->group->groupID; // 设置当前任务等待的进程号为进程组号 + runTask->waitFlag = OS_PROCESS_WAIT_GID; // 设置当前任务的等待标志为进程组号 + } else if (pid == -1) { + // 等待任何子进程退出 + childCB = OsFindExitChildProcess(processCB, OS_INVALID_VALUE); // 查找任何已退出的子进程 + if (childCB != NULL) { + goto WAIT_BACK; // 子进程已退出,则跳转到WAIT_BACK标签处 + } + runTask->waitID = pid; // 设置当前任务等待的进程号为-1 + runTask->waitFlag = OS_PROCESS_WAIT_ANY; // 设置当前任务的等待标志为任何子进程 + } else { // pid < -1 + // 等待进程组号为pid绝对值的任何子进程退出 + group = OsFindProcessGroup(-pid); // 查找具有指定进程组号的进程组 + if (group == NULL) { + return LOS_ECHILD; // 没有找到指定进程组号的进程组,返回错误码LOS_ECHILD + } + + childCB = OsFindGroupExitProcess(group, OS_INVALID_VALUE); // 查找指定进程组中已退出的子进程 + if (childCB != NULL) { + goto WAIT_BACK; // 子进程已退出,则跳转到WAIT_BACK标签处 + } + + runTask->waitID = -pid; // 设置当前任务等待的进程号为进程组号的绝对值 + runTask->waitFlag = OS_PROCESS_WAIT_GID; // 设置当前任务的等待标志为进程组号 + } + +WAIT_BACK: + *child = childCB; // 返回已退出的子进程 + return LOS_OK; +} + +// 回收已退出的子进程资源,并返回进程号 +STATIC UINT32 OsWaitRecycleChildProcess(const LosProcessCB *childCB, UINT32 intSave, INT32 *status, siginfo_t *info) +{ + ProcessGroup *group = NULL; + UINT32 pid = childCB->processID; // 子进程的进程号 + UINT16 mode = childCB->processMode; // 子进程的运行模式 + INT32 exitCode = childCB->exitCode; // 子进程的退出码 + UINT32 uid = 0; + +#ifdef LOSCFG_SECURITY_CAPABILITY + if (childCB->user != NULL) { + uid = childCB->user->userID; // 子进程的用户ID + } +#endif + + OsRecycleZombiesProcess((LosProcessCB *)childCB, &group); // 回收已退出的子进程资源,并获取进程组 + + SCHEDULER_UNLOCK(intSave); // 解锁调度器 + + if (status != NULL) { + if (mode == OS_USER_MODE) { + (VOID)LOS_ArchCopyToUser((VOID *)status, (const VOID *)(&(exitCode)), sizeof(INT32)); // 拷贝退出码到用户空间 + } else { + *status = exitCode; // 将退出码保存到status中 + } + } + /* get signal info */ + if (info != NULL) { + siginfo_t tempinfo = { 0 }; + + tempinfo.si_signo = SIGCHLD; + tempinfo.si_errno = 0; + tempinfo.si_pid = pid; + tempinfo.si_uid = uid; + /* + * Process exit code + * 31 15 8 7 0 + * | | exit code | core dump | signal | + */ + if ((exitCode & 0x7f) == 0) { + tempinfo.si_code = CLD_EXITED; + tempinfo.si_status = (exitCode >> 8U); + } else { + tempinfo.si_code = (exitCode & 0x80) ? CLD_DUMPED : CLD_KILLED; + tempinfo.si_status = (exitCode & 0x7f); + } + + if (mode == OS_USER_MODE) { + (VOID)LOS_ArchCopyToUser((VOID *)(info), (const VOID *)(&(tempinfo)), sizeof(siginfo_t)); // 拷贝信号信息到用户空间 + } else { + (VOID)memcpy_s((VOID *)(info), sizeof(siginfo_t), (const VOID *)(&(tempinfo)), sizeof(siginfo_t)); + } + } + (VOID)LOS_MemFree(m_aucSysMem1, group); // 释放进程组资源 + return pid; // 返回子进程的进程号 +} + +// 检查等待子进程的具体信息 +STATIC UINT32 OsWaitChildProcessCheck(LosProcessCB *processCB, INT32 pid, LosProcessCB **childCB) +{ + if (LOS_ListEmpty(&(processCB->childrenList)) && LOS_ListEmpty(&(processCB->exitChildList))) { + return LOS_ECHILD; // 没有子进程,则返回错误码LOS_ECHILD + } + + return OsWaitSetFlag(processCB, pid, childCB); // 设置等待标志等信息 +} + +// 检查等待选项是否正确 +STATIC UINT32 OsWaitOptionsCheck(UINT32 options) +{ + UINT32 flag = LOS_WAIT_WNOHANG | LOS_WAIT_WUNTRACED | LOS_WAIT_WCONTINUED; + + flag = ~flag & options; + if (flag != 0) { + return LOS_EINVAL; // 选项不正确,返回错误码LOS_EINVAL + } + + if ((options & (LOS_WAIT_WCONTINUED | LOS_WAIT_WUNTRACED)) != 0) { + return LOS_EOPNOTSUPP; // 不支持的选项,返回错误码LOS_EOPNOTSUPP + } + + if (OS_INT_ACTIVE) { + return LOS_EINTR; // 当前处于中断上下文中,返回错误码LOS_EINTR + } + + return LOS_OK; // 选项正确,返回LOS_OK +} + +// 等待子进程退出 +STATIC INT32 OsWait(INT32 pid, USER INT32 *status, USER siginfo_t *info, UINT32 options, VOID *rusage) +{ + (VOID)rusage; + UINT32 ret; + UINT32 intSave; + LosProcessCB *childCB = NULL; + LosProcessCB *processCB = NULL; + LosTaskCB *runTask = NULL; + + SCHEDULER_LOCK(intSave); // 加锁调度器 + processCB = OsCurrProcessGet(); // 获取当前进程控制块 + runTask = OsCurrTaskGet(); // 获取当前任务控制块 + + ret = OsWaitChildProcessCheck(processCB, pid, &childCB); // 检查等待子进程的具体信息 + if (ret != LOS_OK) { + pid = -ret; // 若等待子进程的标志不正确,将错误码赋值给pid + goto ERROR; + } + + if (childCB != NULL) { + return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status, info); // 回收已退出的子进程资源并返回进程号 + } + + if ((options & LOS_WAIT_WNOHANG) != 0) { + runTask->waitFlag = 0; // 不阻塞任务 + pid = 0; + goto ERROR; + } + + OsWaitInsertWaitListInOrder(runTask, processCB); // 将当前任务插入等待列表中 + + runTask->waitFlag = 0; + if (runTask->waitID == OS_INVALID_VALUE) { + pid = -LOS_ECHILD; // 没有子进程需要等待,返回错误码LOS_ECHILD + goto ERROR; + } + + childCB = OS_PCB_FROM_PID(runTask->waitID); // 根据等待的进程号获取子进程控制块 + if (!(childCB->processStatus & OS_PROCESS_STATUS_ZOMBIES)) { + pid = -LOS_ESRCH; // 子进程没有退出,返回错误码LOS_ESRCH + goto ERROR; + } + + return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status, info); // 回收已退出的子进程资源并返回进程号 + +ERROR: + SCHEDULER_UNLOCK(intSave); // 解锁调度器 + return pid; +} \ No newline at end of file diff --git a/process(800-1200).docx b/process(800-1200).docx new file mode 100644 index 0000000..e358788 Binary files /dev/null and b/process(800-1200).docx differ diff --git a/sched/sched_sq/los_sched.c b/sched/sched_sq/los_sched.c index dab0291..1fab649 100644 --- a/sched/sched_sq/los_sched.c +++ b/sched/sched_sq/los_sched.c @@ -48,43 +48,46 @@ #include "los_stat_pri.h" #endif -#define OS_32BIT_MAX 0xFFFFFFFFUL -#define OS_SCHED_FIFO_TIMEOUT 0x7FFFFFFF -#define OS_PRIORITY_QUEUE_NUM 32 -#define PRIQUEUE_PRIOR0_BIT 0x80000000U -#define OS_SCHED_TIME_SLICES_MIN ((5000 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 5ms */ -#define OS_SCHED_TIME_SLICES_MAX ((LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) -#define OS_SCHED_TIME_SLICES_DIFF (OS_SCHED_TIME_SLICES_MAX - OS_SCHED_TIME_SLICES_MIN) -#define OS_SCHED_READY_MAX 30 -#define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */ - +#define OS_32BIT_MAX 0xFFFFFFFFUL //定义32位操作系统的最大值 +#define OS_SCHED_FIFO_TIMEOUT 0x7FFFFFFF //定义FIFO调度器的超时值 +#define OS_PRIORITY_QUEUE_NUM 32 //定义优先级队列的数量 +#define PRIQUEUE_PRIOR0_BIT 0x80000000U //定义优先级队列中优先级0的最高位 +#define OS_SCHED_TIME_SLICES_MIN ((5000 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 定义调度器的最小时间片(以纳秒为单位)5ms */ +#define OS_SCHED_TIME_SLICES_MAX ((LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) //定义调度器的最大时间片(以纳秒为单位) +#define OS_SCHED_TIME_SLICES_DIFF (OS_SCHED_TIME_SLICES_MAX - OS_SCHED_TIME_SLICES_MIN) //定义调度器最大时间片和最小时间片之间的差值 +#define OS_SCHED_READY_MAX 30 //定义调度器的最大就绪任务数 +#define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /*定义最小时间片(以INT32类型表示,单位为50微秒) 50us */ + +//定义调度器队列结构体SchedQueue typedef struct { - LOS_DL_LIST priQueueList[OS_PRIORITY_QUEUE_NUM]; - UINT32 readyTasks[OS_PRIORITY_QUEUE_NUM]; - UINT32 queueBitmap; + LOS_DL_LIST priQueueList[OS_PRIORITY_QUEUE_NUM]; // 优先级队列列表 + UINT32 readyTasks[OS_PRIORITY_QUEUE_NUM]; // 就绪任务数 + UINT32 queueBitmap; // 队列位图 } SchedQueue; - +//定义调度器结构体Sched typedef struct { - SchedQueue queueList[OS_PRIORITY_QUEUE_NUM]; - UINT32 queueBitmap; - SchedScan taskScan; - SchedScan swtmrScan; + SchedQueue queueList[OS_PRIORITY_QUEUE_NUM]; // 优先级队列列表 + UINT32 queueBitmap; // 队列位图 + SchedScan taskScan; // 任务扫描 + SchedScan swtmrScan; // 软件定时器扫描 } Sched; -STATIC Sched *g_sched = NULL; -STATIC UINT64 g_schedTickMaxResponseTime; -UINT64 g_sysSchedStartTime = OS_64BIT_MAX; +STATIC Sched *g_sched = NULL; //定义全局调度器变量g_sched +STATIC UINT64 g_schedTickMaxResponseTime; //定义调度器tick的最大响应时间 +UINT64 g_sysSchedStartTime = OS_64BIT_MAX; //定义系统调度器的起始时间 #ifdef LOSCFG_SCHED_TICK_DEBUG -#define OS_SCHED_DEBUG_DATA_NUM 1000 +#define OS_SCHED_DEBUG_DATA_NUM 1000 //定义调度器tick调试数据数量的常量 +//定义调度器tick调试数据结构体SchedTickDebug typedef struct { - UINT32 tickResporeTime[OS_SCHED_DEBUG_DATA_NUM]; - UINT32 index; - UINT32 setTickCount; - UINT64 oldResporeTime; + UINT32 tickResporeTime[OS_SCHED_DEBUG_DATA_NUM]; // tick响应时间数组 + UINT32 index; // 当前数据索引 + UINT32 setTickCount; // 设置的tick计数 + UINT64 oldResporeTime; // 上一次的响应时间 } SchedTickDebug; -STATIC SchedTickDebug *g_schedTickDebug = NULL; +STATIC SchedTickDebug *g_schedTickDebug = NULL; //定义全局调度器tick调试数据变量g_schedTickDebug +//初始化调度器tick调试数据 STATIC UINT32 OsSchedDebugInit(VOID) { UINT32 size = sizeof(SchedTickDebug) * LOSCFG_KERNEL_CORE_NUM; @@ -96,7 +99,7 @@ STATIC UINT32 OsSchedDebugInit(VOID) (VOID)memset_s(g_schedTickDebug, size, 0, size); return LOS_OK; } - +//记录调度器tick调试数据 VOID OsSchedDebugRecordData(VOID) { SchedTickDebug *schedDebug = &g_schedTickDebug[ArchCurrCpuid()]; @@ -107,265 +110,308 @@ VOID OsSchedDebugRecordData(VOID) schedDebug->index++; } } - +//获取调度器tick调试数据 SchedTickDebug *OsSchedDebugGet(VOID) { return g_schedTickDebug; } - +// 显示调度器 tick 响应时间的 Shell 命令函数 UINT32 OsShellShowTickRespo(VOID) { - UINT32 intSave; - UINT16 cpu; - UINT64 allTime; + UINT32 intSave; // 保存中断状态的变量 + UINT16 cpu; // CPU 编号 + UINT64 allTime; // 所有时间的总和 + // 计算存储调度器调试信息的内存大小 UINT32 tickSize = sizeof(SchedTickDebug) * LOSCFG_KERNEL_CORE_NUM; + + // 在系统内存池中分配存储调度器调试信息的内存 SchedTickDebug *schedDebug = (SchedTickDebug *)LOS_MemAlloc(m_aucSysMem1, tickSize); if (schedDebug == NULL) { return LOS_NOK; } + // 创建一个数组来保存每个 CPU 上的任务和软件定时器的排序链表节点数 UINT32 sortLinkNum[LOSCFG_KERNEL_CORE_NUM]; + + // 禁止调度器调度 SCHEDULER_LOCK(intSave); + + // 将调度器调试信息拷贝到 schedDebug 中 (VOID)memcpy_s((CHAR *)schedDebug, tickSize, (CHAR *)OsSchedDebugGet(), tickSize); + + // 将调度器调试信息清零 (VOID)memset_s((CHAR *)OsSchedDebugGet(), tickSize, 0, tickSize); + + // 计算每个 CPU 上的任务和软件定时器的排序链表节点数 for (cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) { sortLinkNum[cpu] = OsPercpuGetByID(cpu)->taskSortLink.nodeNum + OsPercpuGetByID(cpu)->swtmrSortLink.nodeNum; } + + // 允许调度器调度 SCHEDULER_UNLOCK(intSave); + // 遍历每个 CPU 上的调度器调试信息 for (cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) { - SchedTickDebug *schedData = &schedDebug[cpu]; + SchedTickDebug *schedData = &schedDebug[cpu]; // 获取当前 CPU 的调度器调试信息 + + // 打印当前 CPU 的调度器调试信息 PRINTK("cpu : %u sched data num : %u set time count : %u SortMax : %u\n", cpu, schedData->index, schedData->setTickCount, sortLinkNum[cpu]); - UINT32 *data = schedData->tickResporeTime; - allTime = 0; + + UINT32 *data = schedData->tickResporeTime; // 获取当前 CPU 的 tick 响应时间数据 + + allTime = 0; // 重置总时间 + + // 遍历 tick 响应时间数据 for (UINT32 i = 1; i < schedData->index; i++) { - allTime += data[i]; - UINT32 timeUs = (data[i] * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; - PRINTK(" %u(%u)", timeUs, timeUs / OS_US_PER_TICK); - if ((i != 0) && ((i % 5) == 0)) { /* A row of 5 data */ - PRINTK("\n"); + allTime += data[i]; // 计算总时间 + UINT32 timeUs = (data[i] * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; // 将时间转换为微秒 + PRINTK(" %u(%u)", timeUs, timeUs / OS_US_PER_TICK); // 打印时间 + if ((i != 0) && ((i % 5) == 0)) { /* A row of 5 data每行显示5个数据 */ + PRINTK("\n"); // 换行 } } - allTime = (allTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; - PRINTK("\nTick Indicates the average response period: %llu(us)\n", allTime / (schedData->index - 1)); + allTime = (allTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; // 将总时间转换为微秒 + PRINTK("\nTick Indicates the average response period: %llu(us)\n", allTime / (schedData->index - 1)); //平均响应周期 } + // 释放内存 (VOID)LOS_MemFree(m_aucSysMem1, schedDebug); + return LOS_OK; } #else - +//显示调度器tick响应时间的Shell命令函数 UINT32 OsShellShowTickRespo(VOID) { return LOS_NOK; } #endif - +//定义调度器调试开关 #ifdef LOSCFG_SCHED_DEBUG +// 显示调度器调度参数的 Shell 命令函数 UINT32 OsShellShowSchedParam(VOID) { - UINT64 averRunTime; - UINT64 averTimeSlice; - UINT64 averSchedWait; - UINT64 averPendTime; - UINT32 intSave; - UINT32 size = g_taskMaxNum * sizeof(LosTaskCB); - LosTaskCB *taskCBArray = LOS_MemAlloc(m_aucSysMem1, size); + UINT64 averRunTime; // 平均运行时间 + UINT64 averTimeSlice; // 平均时间片 + UINT64 averSchedWait; // 平均等待调度时间 + UINT64 averPendTime; // 平均挂起时间 + UINT32 intSave; // 保存中断状态的变量 + UINT32 size = g_taskMaxNum * sizeof(LosTaskCB); // 计算任务控制块数组的大小 + LosTaskCB *taskCBArray = LOS_MemAlloc(m_aucSysMem1, size); // 在系统内存池中分配任务控制块数组的内存 if (taskCBArray == NULL) { return LOS_NOK; } - SCHEDULER_LOCK(intSave); + SCHEDULER_LOCK(intSave); // 禁止调度器调度 + + // 将全局的任务控制块数组拷贝到局部数组中 (VOID)memcpy_s(taskCBArray, size, g_taskCBArray, size); - SCHEDULER_UNLOCK(intSave); + + SCHEDULER_UNLOCK(intSave); // 允许调度器调度 + + // 打印表头 PRINTK(" Tid AverRunTime(us) SwitchCount AverTimeSlice(us) TimeSliceCount AverReadyWait(us) " "AverPendTime(us) TaskName \n"); + + // 遍历任务控制块数组 for (UINT32 tid = 0; tid < g_taskMaxNum; tid++) { - LosTaskCB *taskCB = taskCBArray + tid; + LosTaskCB *taskCB = taskCBArray + tid; // 获取当前任务控制块 + + // 如果任务控制块未使用,则跳过 if (OsTaskIsUnused(taskCB)) { continue; } - averRunTime = 0; - averTimeSlice = 0; - averPendTime = 0; - averSchedWait = 0; + averRunTime = 0; // 平均运行时间初始化为0 + averTimeSlice = 0; // 平均时间片初始化为0 + averPendTime = 0; // 平均挂起时间初始化为0 + averSchedWait = 0; // 平均等待调度时间初始化为0 + // 计算平均运行时间 if (taskCB->schedStat.switchCount >= 1) { - averRunTime = taskCB->schedStat.runTime / taskCB->schedStat.switchCount; - averRunTime = (averRunTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; + averRunTime = taskCB->schedStat.runTime / taskCB->schedStat.switchCount; // 平均运行时间 = 运行时间 / 切换次数 + averRunTime = (averRunTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; // 将平均运行时间转换为微秒 } + // 计算平均时间片 if (taskCB->schedStat.timeSliceCount > 1) { - averTimeSlice = taskCB->schedStat.timeSliceTime / (taskCB->schedStat.timeSliceCount - 1); - averTimeSlice = (averTimeSlice * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; + averTimeSlice = taskCB->schedStat.timeSliceTime / (taskCB->schedStat.timeSliceCount - 1); // 平均时间片 = 时间片总数 / (时间片个数 - 1) + averTimeSlice = (averTimeSlice * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; // 将平均时间片转换为微秒 } + // 计算平均挂起时间 if (taskCB->schedStat.pendCount > 1) { - averPendTime = taskCB->schedStat.pendTime / taskCB->schedStat.pendCount; - averPendTime = (averPendTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; + averPendTime = taskCB->schedStat.pendTime / taskCB->schedStat.pendCount; // 平均挂起时间 = 挂起时间 / 挂起次数 + averPendTime = (averPendTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; // 将平均挂起时间转换为微秒 } + // 计算平均等待调度时间 if (taskCB->schedStat.waitSchedCount > 0) { - averSchedWait = taskCB->schedStat.waitSchedTime / taskCB->schedStat.waitSchedCount; - averSchedWait = (averSchedWait * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; + averSchedWait = taskCB->schedStat.waitSchedTime / taskCB->schedStat.waitSchedCount; // 平均等待调度时间 = 等待调度时间 / 等待调度次数 + averSchedWait = (averSchedWait * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US; // 将平均等待调度时间转换为微秒 } + // 打印任务的调度参数信息 PRINTK("%5u%19llu%15llu%19llu%18llu%19llu%18llu %-32s\n", taskCB->taskID, averRunTime, taskCB->schedStat.switchCount, averTimeSlice, taskCB->schedStat.timeSliceCount - 1, averSchedWait, averPendTime, taskCB->taskName); } - (VOID)LOS_MemFree(m_aucSysMem1, taskCBArray); + (VOID)LOS_MemFree(m_aucSysMem1, taskCBArray); // 释放内存 return LOS_OK; } #else + UINT32 OsShellShowSchedParam(VOID) { - return LOS_NOK; + return LOS_NOK; // 返回错误码,表示未实现该函数 } #endif +// 设置调度器的 tick 定时器类型 UINT32 OsSchedSetTickTimerType(UINT32 timerType) { switch (timerType) { - case 32: /* 32 bit timer */ - g_schedTickMaxResponseTime = OS_32BIT_MAX; + case 32: /* 32 位定时器 */ + g_schedTickMaxResponseTime = OS_32BIT_MAX; // 设置最大的 tick 响应时间为 32 位定时器的最大值 break; - case 64: /* 64 bit timer */ - g_schedTickMaxResponseTime = OS_64BIT_MAX; + case 64: /* 64 位定时器 */ + g_schedTickMaxResponseTime = OS_64BIT_MAX; // 设置最大的 tick 响应时间为 64 位定时器的最大值 break; default: PRINT_ERR("Unsupported Tick Timer type, The system only supports 32 and 64 bit tick timers\n"); - return LOS_NOK; + return LOS_NOK; // 返回错误码,表示不支持该类型的定时器 } - return LOS_OK; + return LOS_OK; // 返回成功码 } +// 设置调度器的启动时间 STATIC VOID OsSchedSetStartTime(UINT64 currCycle) { if (g_sysSchedStartTime == OS_64BIT_MAX) { - g_sysSchedStartTime = currCycle; + g_sysSchedStartTime = currCycle; // 如果系统的调度启动时间未设置,则设置为当前的时钟周期数 } } +// 更新时间片 STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime) { - LOS_ASSERT(currTime >= taskCB->startTime); + LOS_ASSERT(currTime >= taskCB->startTime); // 断言当前时间大于等于任务的启动时间 - INT32 incTime = (currTime - taskCB->startTime - taskCB->irqUsedTime); + INT32 incTime = (currTime - taskCB->startTime - taskCB->irqUsedTime); // 计算增加的时间 - LOS_ASSERT(incTime >= 0); + LOS_ASSERT(incTime >= 0); // 断言增加的时间大于等于0 if (taskCB->policy == LOS_SCHED_RR) { - taskCB->timeSlice -= incTime; + taskCB->timeSlice -= incTime; // 更新时间片剩余时间 #ifdef LOSCFG_SCHED_DEBUG - taskCB->schedStat.timeSliceRealTime += incTime; + taskCB->schedStat.timeSliceRealTime += incTime; // 更新调度统计信息中的实际时间片使用时间 #endif } - taskCB->irqUsedTime = 0; - taskCB->startTime = currTime; + taskCB->irqUsedTime = 0; // 清零中断使用的时间 + taskCB->startTime = currTime; // 更新任务的启动时间 #ifdef LOSCFG_SCHED_DEBUG - taskCB->schedStat.allRuntime += incTime; + taskCB->schedStat.allRuntime += incTime; // 更新调度统计信息中的总运行时间 #endif } +// 重新加载 tick 定时器 STATIC INLINE VOID OsSchedTickReload(Percpu *currCpu, UINT64 nextResponseTime, UINT32 responseID, BOOL isTimeSlice) { UINT64 currTime, nextExpireTime; UINT32 usedTime; - currTime = OsGetCurrSchedTimeCycle(); + currTime = OsGetCurrSchedTimeCycle(); // 获取当前的调度时间 if (currCpu->tickStartTime != 0) { - usedTime = currTime - currCpu->tickStartTime; - currCpu->tickStartTime = 0; + usedTime = currTime - currCpu->tickStartTime; // 计算 tick 定时器已经使用的时间 + currCpu->tickStartTime = 0; // 清零 tick 定时器的启动时间 } else { usedTime = 0; } if ((nextResponseTime > usedTime) && ((nextResponseTime - usedTime) > OS_TICK_RESPONSE_PRECISION)) { - nextResponseTime -= usedTime; + nextResponseTime -= usedTime; // 减去已经使用的时间,得到下一次 tick 定时器的响应时间 } else { - nextResponseTime = OS_TICK_RESPONSE_PRECISION; + nextResponseTime = OS_TICK_RESPONSE_PRECISION; // 如果计算出的响应时间小于精度要求,设置为精度要求 } - nextExpireTime = currTime + nextResponseTime; + nextExpireTime = currTime + nextResponseTime; // 计算下一次 tick 定时器的到期时间 if (nextExpireTime >= currCpu->responseTime) { - return; + return; // 如果下一次到期时间大于等于当前的响应时间,直接返回 } if (isTimeSlice) { - /* The expiration time of the current system is the thread's slice expiration time */ - currCpu->responseID = responseID; + /* 当前系统的到期时间是线程的时间片到期时间 */ + currCpu->responseID = responseID; // 设置当前 CPU 的响应 ID } else { - currCpu->responseID = OS_INVALID_VALUE; + currCpu->responseID = OS_INVALID_VALUE; // 设置当前 CPU 的响应 ID 为无效值 } - currCpu->responseTime = nextExpireTime; - HalClockTickTimerReload(nextResponseTime); + currCpu->responseTime = nextExpireTime; // 更新当前 CPU 的响应时间 + HalClockTickTimerReload(nextResponseTime); // 重新加载 tick 定时器 #ifdef LOSCFG_SCHED_TICK_DEBUG SchedTickDebug *schedDebug = &g_schedTickDebug[ArchCurrCpuid()]; if (schedDebug->index < OS_SCHED_DEBUG_DATA_NUM) { - schedDebug->setTickCount++; + schedDebug->setTickCount++; // 更新调度 tick 调试信息中的设置 tick 数量 } #endif } + STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, UINT32 oldResponseID) { - UINT64 nextExpireTime = OsGetNextExpireTime(startTime); - Percpu *currCpu = OsPercpuGet(); + UINT64 nextExpireTime = OsGetNextExpireTime(startTime); // 获取下一次到期时间 + Percpu *currCpu = OsPercpuGet(); // 获取当前 CPU 的数据结构指针 UINT64 nextResponseTime; BOOL isTimeSlice = FALSE; - currCpu->schedFlag &= ~INT_PEND_TICK; + currCpu->schedFlag &= ~INT_PEND_TICK; // 清除调度标志位中的中断挂起标志 + if (currCpu->responseID == oldResponseID) { - /* This time has expired, and the next time the theory has expired is infinite */ + /* 此次已经到期,下一次理论上到期的时间为无穷大 */ currCpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME; } - /* The current thread's time slice has been consumed, but the current system lock task cannot - * trigger the schedule to release the CPU - */ + /* 当前线程的时间片已经消耗完,但当前系统锁定任务无法触发调度以释放 CPU */ if ((nextExpireTime > taskEndTime) && ((nextExpireTime - taskEndTime) > OS_SCHED_MINI_PERIOD)) { nextExpireTime = taskEndTime; - isTimeSlice = TRUE; + isTimeSlice = TRUE; // 设置时间片到期标志 } if ((currCpu->responseTime > nextExpireTime) && ((currCpu->responseTime - nextExpireTime) >= OS_TICK_RESPONSE_PRECISION)) { - nextResponseTime = nextExpireTime - startTime; + nextResponseTime = nextExpireTime - startTime; // 计算下一次响应时间 if (nextResponseTime > g_schedTickMaxResponseTime) { - nextResponseTime = g_schedTickMaxResponseTime; + nextResponseTime = g_schedTickMaxResponseTime; // 如果下一次响应时间超过最大响应时间,设置为最大响应时间 } } else { - /* There is no point earlier than the current expiration date */ - currCpu->tickStartTime = 0; + /* 没有比当前到期时间更早的点 */ + currCpu->tickStartTime = 0; // 清零 tick 定时器的启动时间 return; } - OsSchedTickReload(currCpu, nextResponseTime, responseID, isTimeSlice); + OsSchedTickReload(currCpu, nextResponseTime, responseID, isTimeSlice); // 重新加载 tick 定时器 } VOID OsSchedUpdateExpireTime(UINT64 startTime) { UINT64 endTime; - Percpu *cpu = OsPercpuGet(); - LosTaskCB *runTask = OsCurrTaskGet(); + Percpu *cpu = OsPercpuGet(); // 获取当前 CPU 的数据结构指针 + LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务的控制块指针 if (!OS_SCHEDULER_ACTIVE || OS_INT_ACTIVE) { - cpu->schedFlag |= INT_PEND_TICK; + cpu->schedFlag |= INT_PEND_TICK; // 如果调度器不活跃或者中断活跃,设置调度标志位中的中断挂起标志 return; } @@ -373,335 +419,330 @@ VOID OsSchedUpdateExpireTime(UINT64 startTime) LOS_SpinLock(&g_taskSpin); INT32 timeSlice = (runTask->timeSlice <= OS_TIME_SLICE_MIN) ? runTask->initTimeSlice : runTask->timeSlice; LOS_SpinUnlock(&g_taskSpin); - endTime = startTime + timeSlice; + endTime = startTime + timeSlice; // 计算任务的结束时间 } else { - endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; + endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; // 如果不是轮转调度策略,设置结束时间为最大响应时间减去精度要求 } - OsSchedSetNextExpireTime(startTime, runTask->taskID, endTime, runTask->taskID); + OsSchedSetNextExpireTime(startTime, runTask->taskID, endTime, runTask->taskID); // 设置下一次到期时间 } STATIC INLINE UINT32 OsSchedCalculateTimeSlice(UINT16 proPriority, UINT16 priority) { UINT32 ratTime, readTasks; - SchedQueue *queueList = &g_sched->queueList[proPriority]; - readTasks = queueList->readyTasks[priority]; + SchedQueue *queueList = &g_sched->queueList[proPriority]; // 获取指定优先级的调度队列 + readTasks = queueList->readyTasks[priority]; // 获取指定优先级的就绪任务数量 if (readTasks > OS_SCHED_READY_MAX) { - return OS_SCHED_TIME_SLICES_MIN; + return OS_SCHED_TIME_SLICES_MIN; // 如果就绪任务数量超过最大限制,返回最小时间片 } - ratTime = ((OS_SCHED_READY_MAX - readTasks) * OS_SCHED_TIME_SLICES_DIFF) / OS_SCHED_READY_MAX; - return (ratTime + OS_SCHED_TIME_SLICES_MIN); + ratTime = ((OS_SCHED_READY_MAX - readTasks) * OS_SCHED_TIME_SLICES_DIFF) / OS_SCHED_READY_MAX; // 计算时间片 + return (ratTime + OS_SCHED_TIME_SLICES_MIN); // 返回计算出的时间片 } - STATIC INLINE VOID OsSchedPriQueueEnHead(UINT32 proPriority, LOS_DL_LIST *priqueueItem, UINT32 priority) { - SchedQueue *queueList = &g_sched->queueList[proPriority]; - LOS_DL_LIST *priQueueList = &queueList->priQueueList[0]; - UINT32 *bitMap = &queueList->queueBitmap; + SchedQueue *queueList = &g_sched->queueList[proPriority]; // 获取指定优先级的调度队列 + LOS_DL_LIST *priQueueList = &queueList->priQueueList[0]; // 获取指定优先级的优先级队列 + UINT32 *bitMap = &queueList->queueBitmap; // 获取位图 /* - * Task control blocks are inited as zero. And when task is deleted, - * and at the same time would be deleted from priority queue or - * other lists, task pend node will restored as zero. + * 任务控制块被初始化为零。当任务被删除时, + * 同时从优先级队列或其他列表中删除,任务挂起节点将被恢复为零。 */ - LOS_ASSERT(priqueueItem->pstNext == NULL); + LOS_ASSERT(priqueueItem->pstNext == NULL); // 断言优先级队列项的下一个节点为空 if (*bitMap == 0) { - g_sched->queueBitmap |= PRIQUEUE_PRIOR0_BIT >> proPriority; + g_sched->queueBitmap |= PRIQUEUE_PRIOR0_BIT >> proPriority; // 如果位图为零,设置全局位图中对应的位 } if (LOS_ListEmpty(&priQueueList[priority])) { - *bitMap |= PRIQUEUE_PRIOR0_BIT >> priority; + *bitMap |= PRIQUEUE_PRIOR0_BIT >> priority; // 如果指定优先级的优先级队列为空,设置位图中对应的位 } - LOS_ListHeadInsert(&priQueueList[priority], priqueueItem); - queueList->readyTasks[priority]++; + LOS_ListHeadInsert(&priQueueList[priority], priqueueItem); // 将优先级队列项插入到指定优先级的队列头部 + queueList->readyTasks[priority]++; // 增加指定优先级的就绪任务数量 } STATIC INLINE VOID OsSchedPriQueueEnTail(UINT32 proPriority, LOS_DL_LIST *priqueueItem, UINT32 priority) { - SchedQueue *queueList = &g_sched->queueList[proPriority]; - LOS_DL_LIST *priQueueList = &queueList->priQueueList[0]; - UINT32 *bitMap = &queueList->queueBitmap; + SchedQueue *queueList = &g_sched->queueList[proPriority]; // 获取指定优先级的调度队列 + LOS_DL_LIST *priQueueList = &queueList->priQueueList[0]; // 获取指定优先级的优先级队列 + UINT32 *bitMap = &queueList->queueBitmap; // 获取位图 /* - * Task control blocks are inited as zero. And when task is deleted, - * and at the same time would be deleted from priority queue or - * other lists, task pend node will restored as zero. + * 任务控制块被初始化为零。当任务被删除时, + * 同时从优先级队列或其他列表中删除,任务挂起节点将被恢复为零。 */ - LOS_ASSERT(priqueueItem->pstNext == NULL); + LOS_ASSERT(priqueueItem->pstNext == NULL); // 断言优先级队列项的下一个节点为空 if (*bitMap == 0) { - g_sched->queueBitmap |= PRIQUEUE_PRIOR0_BIT >> proPriority; + g_sched->queueBitmap |= PRIQUEUE_PRIOR0_BIT >> proPriority; // 如果位图为零,设置全局位图中对应的位 } if (LOS_ListEmpty(&priQueueList[priority])) { - *bitMap |= PRIQUEUE_PRIOR0_BIT >> priority; + *bitMap |= PRIQUEUE_PRIOR0_BIT >> priority; // 如果指定优先级的优先级队列为空,设置位图中对应的位 } - LOS_ListTailInsert(&priQueueList[priority], priqueueItem); - queueList->readyTasks[priority]++; + LOS_ListTailInsert(&priQueueList[priority], priqueueItem); // 将优先级队列项插入到指定优先级的队列尾部 + queueList->readyTasks[priority]++; // 增加指定优先级的就绪任务数量 } STATIC INLINE VOID OsSchedPriQueueDelete(UINT32 proPriority, LOS_DL_LIST *priqueueItem, UINT32 priority) { - SchedQueue *queueList = &g_sched->queueList[proPriority]; - LOS_DL_LIST *priQueueList = &queueList->priQueueList[0]; - UINT32 *bitMap = &queueList->queueBitmap; + SchedQueue *queueList = &g_sched->queueList[proPriority]; // 获取指定优先级的调度队列 + LOS_DL_LIST *priQueueList = &queueList->priQueueList[0]; // 获取指定优先级的优先级队列 + UINT32 *bitMap = &queueList->queueBitmap; // 获取位图 - LOS_ListDelete(priqueueItem); - queueList->readyTasks[priority]--; + LOS_ListDelete(priqueueItem); // 从优先级队列中删除优先级队列项 + queueList->readyTasks[priority]--; // 减少指定优先级的就绪任务数量 if (LOS_ListEmpty(&priQueueList[priority])) { - *bitMap &= ~(PRIQUEUE_PRIOR0_BIT >> priority); + *bitMap &= ~(PRIQUEUE_PRIOR0_BIT >> priority); // 如果指定优先级的优先级队列为空,清除位图中对应的位 } if (*bitMap == 0) { - g_sched->queueBitmap &= ~(PRIQUEUE_PRIOR0_BIT >> proPriority); + g_sched->queueBitmap &= ~(PRIQUEUE_PRIOR0_BIT >> proPriority); // 如果位图为零,清除全局位图中对应的位 } } - STATIC INLINE VOID OsSchedWakePendTimeTask(UINT64 currTime, LosTaskCB *taskCB, BOOL *needSchedule) { #ifndef LOSCFG_SCHED_DEBUG (VOID)currTime; #endif - LOS_SpinLock(&g_taskSpin); - UINT16 tempStatus = taskCB->taskStatus; + LOS_SpinLock(&g_taskSpin); // 获取全局任务自旋锁 + UINT16 tempStatus = taskCB->taskStatus; // 获取任务的状态 if (tempStatus & (OS_TASK_STATUS_PENDING | OS_TASK_STATUS_DELAY)) { - taskCB->taskStatus &= ~(OS_TASK_STATUS_PENDING | OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY); + taskCB->taskStatus &= ~(OS_TASK_STATUS_PENDING | OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY); // 清除任务的挂起状态和延时状态 if (tempStatus & OS_TASK_STATUS_PENDING) { #ifdef LOSCFG_KERNEL_LITEIPC - taskCB->ipcStatus &= ~IPC_THREAD_STATUS_PEND; + taskCB->ipcStatus &= ~IPC_THREAD_STATUS_PEND; // 清除任务的轻量级 IPC 挂起状态 #endif - taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT; - LOS_ListDelete(&taskCB->pendList); - taskCB->taskMux = NULL; - OsTaskWakeClearPendMask(taskCB); + taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT; // 设置任务的超时状态 + LOS_ListDelete(&taskCB->pendList); // 从挂起任务列表中删除任务 + taskCB->taskMux = NULL; // 清除任务的互斥信号量 + OsTaskWakeClearPendMask(taskCB); // 清除任务的挂起掩码 } if (!(tempStatus & OS_TASK_STATUS_SUSPENDED)) { #ifdef LOSCFG_SCHED_DEBUG - taskCB->schedStat.pendTime += currTime - taskCB->startTime; - taskCB->schedStat.pendCount++; + taskCB->schedStat.pendTime += currTime - taskCB->startTime; // 更新任务的挂起时间统计 + taskCB->schedStat.pendCount++; // 增加任务的挂起次数统计 #endif - OsSchedTaskEnQueue(taskCB); - *needSchedule = TRUE; + OsSchedTaskEnQueue(taskCB); // 将任务加入调度队列 + *needSchedule = TRUE; // 设置需要进行调度 } } - LOS_SpinUnlock(&g_taskSpin); + LOS_SpinUnlock(&g_taskSpin); // 释放全局任务自旋锁 } STATIC INLINE BOOL OsSchedScanTimerList(VOID) { - Percpu *cpu = OsPercpuGet(); - BOOL needSchedule = FALSE; - SortLinkAttribute *taskSortLink = &OsPercpuGet()->taskSortLink; - LOS_DL_LIST *listObject = &taskSortLink->sortLink; + Percpu *cpu = OsPercpuGet(); // 获取当前 CPU 的 Per-CPU 变量 + BOOL needSchedule = FALSE; // 标记是否需要进行调度 + SortLinkAttribute *taskSortLink = &OsPercpuGet()->taskSortLink; // 获取当前 CPU 的任务排序链表属性 + LOS_DL_LIST *listObject = &taskSortLink->sortLink; // 获取当前 CPU 的任务排序链表 /* - * When task is pended with timeout, the task block is on the timeout sortlink - * (per cpu) and ipc(mutex,sem and etc.)'s block at the same time, it can be waken - * up by either timeout or corresponding ipc it's waiting. + * 当任务被挂起并设置了超时时,任务块会同时存在于超时排序链表 + * (每个 CPU 都有一个) 和相应的 IPC(互斥信号量、信号量等)的链表中, + * 它可以通过超时或等待的 IPC 被唤醒。 * - * Now synchronize sortlink preocedure is used, therefore the whole task scan needs - * to be protected, preventing another core from doing sortlink deletion at same time. + * 现在使用同步的排序链表过程,因此整个任务扫描需要保护, + * 防止另一个核心同时进行排序链表的删除操作。 */ - LOS_SpinLock(&cpu->taskSortLinkSpin); + LOS_SpinLock(&cpu->taskSortLinkSpin); // 获取当前 CPU 的任务排序链表自旋锁 if (LOS_ListEmpty(listObject)) { LOS_SpinUnlock(&cpu->taskSortLinkSpin); return needSchedule; } - SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode); - UINT64 currTime = OsGetCurrSchedTimeCycle(); + SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode); // 获取排序链表的第一个任务节点 + UINT64 currTime = OsGetCurrSchedTimeCycle(); // 获取当前调度时间 while (sortList->responseTime <= currTime) { - LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList); - OsDeleteNodeSortLink(taskSortLink, &taskCB->sortList); - LOS_SpinUnlock(&cpu->taskSortLinkSpin); + LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList); // 获取任务控制块 + OsDeleteNodeSortLink(taskSortLink, &taskCB->sortList); // 从排序链表中删除任务节点 + LOS_SpinUnlock(&cpu->taskSortLinkSpin); // 释放当前 CPU 的任务排序链表自旋锁 - OsSchedWakePendTimeTask(currTime, taskCB, &needSchedule); + OsSchedWakePendTimeTask(currTime, taskCB, &needSchedule); // 唤醒被挂起的超时任务 - LOS_SpinLock(&cpu->taskSortLinkSpin); + LOS_SpinLock(&cpu->taskSortLinkSpin); // 获取当前 CPU 的任务排序链表自旋锁 if (LOS_ListEmpty(listObject)) { break; } - sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode); + sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode); // 获取排序链表的下一个任务节点 } - LOS_SpinUnlock(&cpu->taskSortLinkSpin); + LOS_SpinUnlock(&cpu->taskSortLinkSpin); // 释放当前 CPU 的任务排序链表自旋锁 - return needSchedule; + return needSchedule; // 返回是否需要进行调度 } - STATIC INLINE VOID OsSchedEnTaskQueue(LosTaskCB *taskCB, LosProcessCB *processCB) { - LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY)); + LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY)); // 断言任务不处于就绪状态 switch (taskCB->policy) { case LOS_SCHED_RR: { - if (taskCB->timeSlice > OS_TIME_SLICE_MIN) { - OsSchedPriQueueEnHead(processCB->priority, &taskCB->pendList, taskCB->priority); + if (taskCB->timeSlice > OS_TIME_SLICE_MIN) { // 如果时间片大于最小时间片 + OsSchedPriQueueEnHead(processCB->priority, &taskCB->pendList, taskCB->priority); // 将任务加入就绪队列的头部 } else { - taskCB->initTimeSlice = OsSchedCalculateTimeSlice(processCB->priority, taskCB->priority); - taskCB->timeSlice = taskCB->initTimeSlice; - OsSchedPriQueueEnTail(processCB->priority, &taskCB->pendList, taskCB->priority); + taskCB->initTimeSlice = OsSchedCalculateTimeSlice(processCB->priority, taskCB->priority); // 计算任务的初始时间片 + taskCB->timeSlice = taskCB->initTimeSlice; // 设置任务的时间片 + OsSchedPriQueueEnTail(processCB->priority, &taskCB->pendList, taskCB->priority); // 将任务加入就绪队列的尾部 #ifdef LOSCFG_SCHED_DEBUG - taskCB->schedStat.timeSliceTime = taskCB->schedStat.timeSliceRealTime; - taskCB->schedStat.timeSliceCount++; + taskCB->schedStat.timeSliceTime = taskCB->schedStat.timeSliceRealTime; // 更新任务的时间片统计 + taskCB->schedStat.timeSliceCount++; // 增加任务的时间片计数 #endif } break; } case LOS_SCHED_FIFO: { - /* The time slice of FIFO is always greater than 0 unless the yield is called */ - if ((taskCB->timeSlice > OS_TIME_SLICE_MIN) && (taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) { - OsSchedPriQueueEnHead(processCB->priority, &taskCB->pendList, taskCB->priority); + /* FIFO 调度策略的时间片总是大于 0,除非调用了 yield */ + if ((taskCB->timeSlice > OS_TIME_SLICE_MIN) && (taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) { // 如果时间片大于最小时间片且任务正在运行 + OsSchedPriQueueEnHead(processCB->priority, &taskCB->pendList, taskCB->priority); // 将任务加入就绪队列的头部 } else { - taskCB->initTimeSlice = OS_SCHED_FIFO_TIMEOUT; - taskCB->timeSlice = taskCB->initTimeSlice; - OsSchedPriQueueEnTail(processCB->priority, &taskCB->pendList, taskCB->priority); + taskCB->initTimeSlice = OS_SCHED_FIFO_TIMEOUT; // 设置任务的初始时间片为 FIFO 超时时间 + taskCB->timeSlice = taskCB->initTimeSlice; // 设置任务的时间片 + OsSchedPriQueueEnTail(processCB->priority, &taskCB->pendList, taskCB->priority); // 将任务加入就绪队列的尾部 } break; } case LOS_SCHED_IDLE: #ifdef LOSCFG_SCHED_DEBUG - taskCB->schedStat.timeSliceCount = 1; + taskCB->schedStat.timeSliceCount = 1; // 设置任务的时间片计数为 1 #endif break; default: - LOS_ASSERT(0); + LOS_ASSERT(0); // 断言不会执行到这里 break; } - taskCB->taskStatus &= ~OS_TASK_STATUS_BLOCKED; - taskCB->taskStatus |= OS_TASK_STATUS_READY; + taskCB->taskStatus &= ~OS_TASK_STATUS_BLOCKED; // 清除任务的阻塞状态 + taskCB->taskStatus |= OS_TASK_STATUS_READY; // 设置任务的就绪状态 - processCB->processStatus &= ~(OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_PENDING); - processCB->processStatus |= OS_PROCESS_STATUS_READY; - processCB->readyTaskNum++; + processCB->processStatus &= ~(OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_PENDING); // 清除进程的初始化和挂起状态 + processCB->processStatus |= OS_PROCESS_STATUS_READY; // 设置进程的就绪状态 + processCB->readyTaskNum++; // 增加进程的就绪任务数 } STATIC INLINE VOID OsSchedDeTaskQueue(LosTaskCB *taskCB, LosProcessCB *processCB) { - if (taskCB->policy != LOS_SCHED_IDLE) { - OsSchedPriQueueDelete(processCB->priority, &taskCB->pendList, taskCB->priority); + if (taskCB->policy != LOS_SCHED_IDLE) { // 如果任务的调度策略不是 IDLE + OsSchedPriQueueDelete(processCB->priority, &taskCB->pendList, taskCB->priority); // 从就绪队列中删除任务 } - taskCB->taskStatus &= ~OS_TASK_STATUS_READY; + taskCB->taskStatus &= ~OS_TASK_STATUS_READY; // 清除任务的就绪状态 - processCB->readyTaskNum--; + processCB->readyTaskNum--; // 减少进程的就绪任务数 if (processCB->readyTaskNum == 0) { - processCB->processStatus &= ~OS_PROCESS_STATUS_READY; + processCB->processStatus &= ~OS_PROCESS_STATUS_READY; // 如果进程的就绪任务数为 0,则清除进程的就绪状态 } } VOID OsSchedTaskDeQueue(LosTaskCB *taskCB) { - LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID); + LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID); // 获取任务所属进程的控制块 - if (taskCB->taskStatus & OS_TASK_STATUS_READY) { - OsSchedDeTaskQueue(taskCB, processCB); + if (taskCB->taskStatus & OS_TASK_STATUS_READY) { // 如果任务处于就绪状态 + OsSchedDeTaskQueue(taskCB, processCB); // 从就绪队列中删除任务 } - if (processCB->processStatus & OS_PROCESS_STATUS_READY) { + if (processCB->processStatus & OS_PROCESS_STATUS_READY) { // 如果进程处于就绪状态 return; } - /* If the current process has only the current thread running, - * the process becomes blocked after the thread leaves the scheduling queue + /* 如果当前进程只有当前线程在运行, + * 那么线程离开调度队列后进程将变为阻塞状态 */ if (OS_PROCESS_GET_RUNTASK_COUNT(processCB->processStatus) == 1) { - processCB->processStatus |= OS_PROCESS_STATUS_PENDING; + processCB->processStatus |= OS_PROCESS_STATUS_PENDING; // 设置进程的挂起状态 } } VOID OsSchedTaskEnQueue(LosTaskCB *taskCB) { - LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID); + LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID); // 获取任务所属进程的控制块 #ifdef LOSCFG_SCHED_DEBUG - if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) { - taskCB->startTime = OsGetCurrSchedTimeCycle(); + if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) { // 如果任务不是正在运行状态 + taskCB->startTime = OsGetCurrSchedTimeCycle(); // 记录任务的启动时间 } #endif - OsSchedEnTaskQueue(taskCB, processCB); + OsSchedEnTaskQueue(taskCB, processCB); // 将任务加入就绪队列 } VOID OsSchedTaskExit(LosTaskCB *taskCB) { - LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID); + LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID); // 获取任务所属进程的控制块 - if (taskCB->taskStatus & OS_TASK_STATUS_READY) { - OsSchedTaskDeQueue(taskCB); - processCB->processStatus &= ~OS_PROCESS_STATUS_PENDING; - } else if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) { - LOS_ListDelete(&taskCB->pendList); - taskCB->taskStatus &= ~OS_TASK_STATUS_PENDING; + if (taskCB->taskStatus & OS_TASK_STATUS_READY) { // 如果任务处于就绪状态 + OsSchedTaskDeQueue(taskCB); // 从就绪队列中删除任务 + processCB->processStatus &= ~OS_PROCESS_STATUS_PENDING; // 清除进程的挂起状态 + } else if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) { // 如果任务处于挂起状态 + LOS_ListDelete(&taskCB->pendList); // 从挂起队列中删除任务 + taskCB->taskStatus &= ~OS_TASK_STATUS_PENDING; // 清除任务的挂起状态 } - if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) { - OsDeleteSortLink(&taskCB->sortList, OS_SORT_LINK_TASK); - taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME); + if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) { // 如果任务处于延时或等待定时状态 + OsDeleteSortLink(&taskCB->sortList, OS_SORT_LINK_TASK); // 从排序链表中删除任务 + taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME); // 清除任务的延时和等待定时状态 } } VOID OsSchedYield(VOID) { - LosTaskCB *runTask = OsCurrTaskGet(); + LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务 - runTask->timeSlice = 0; + runTask->timeSlice = 0; // 将任务的时间片设置为 0 - runTask->startTime = OsGetCurrSchedTimeCycle(); - OsSchedTaskEnQueue(runTask); - OsSchedResched(); + runTask->startTime = OsGetCurrSchedTimeCycle(); // 记录任务的启动时间 + OsSchedTaskEnQueue(runTask); // 将任务加入就绪队列 + OsSchedResched(); // 进行调度 } VOID OsSchedDelay(LosTaskCB *runTask, UINT32 tick) { - OsSchedTaskDeQueue(runTask); - runTask->taskStatus |= OS_TASK_STATUS_DELAY; - runTask->waitTimes = tick; + OsSchedTaskDeQueue(runTask); // 从就绪队列中删除任务 + runTask->taskStatus |= OS_TASK_STATUS_DELAY; // 设置任务的延时状态 + runTask->waitTimes = tick; // 设置任务的等待时间 - OsSchedResched(); + OsSchedResched(); // 进行调度 } UINT32 OsSchedTaskWait(LOS_DL_LIST *list, UINT32 ticks, BOOL needSched) { - LosTaskCB *runTask = OsCurrTaskGet(); - OsSchedTaskDeQueue(runTask); + LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务 + OsSchedTaskDeQueue(runTask); // 从就绪队列中删除任务 - runTask->taskStatus |= OS_TASK_STATUS_PENDING; - LOS_ListTailInsert(list, &runTask->pendList); + runTask->taskStatus |= OS_TASK_STATUS_PENDING; // 设置任务的挂起状态 + LOS_ListTailInsert(list, &runTask->pendList); // 将任务插入挂起队列的尾部 - if (ticks != LOS_WAIT_FOREVER) { - runTask->taskStatus |= OS_TASK_STATUS_PEND_TIME; - runTask->waitTimes = ticks; + if (ticks != LOS_WAIT_FOREVER) { // 如果等待时间不是永远 + runTask->taskStatus |= OS_TASK_STATUS_PEND_TIME; // 设置任务的等待定时状态 + runTask->waitTimes = ticks; // 设置任务的等待时间 } - if (needSched == TRUE) { - OsSchedResched(); - if (runTask->taskStatus & OS_TASK_STATUS_TIMEOUT) { - runTask->taskStatus &= ~OS_TASK_STATUS_TIMEOUT; - return LOS_ERRNO_TSK_TIMEOUT; + if (needSched == TRUE) { // 如果需要进行调度 + OsSchedResched(); // 进行调度 + if (runTask->taskStatus & OS_TASK_STATUS_TIMEOUT) { // 如果任务超时 + runTask->taskStatus &= ~OS_TASK_STATUS_TIMEOUT; // 清除任务的超时状态 + return LOS_ERRNO_TSK_TIMEOUT; // 返回超时错误 } } - return LOS_OK; + return LOS_OK; // 返回成功 } VOID OsSchedTaskWake(LosTaskCB *resumedTask) { - LOS_ListDelete(&resumedTask->pendList); - resumedTask->taskStatus &= ~OS_TASK_STATUS_PENDING; + LOS_ListDelete(&resumedTask->pendList); // 从挂起队列中删除任务 + resumedTask->taskStatus &= ~OS_TASK_STATUS_PENDING; // 清除任务的挂起状态 - if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) { - OsDeleteSortLink(&resumedTask->sortList, OS_SORT_LINK_TASK); - resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME; + if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) { // 如果任务处于等待定时状态 + OsDeleteSortLink(&resumedTask->sortList, OS_SORT_LINK_TASK); // 从排序链表中删除任务 + resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME; // 清除任务的等待定时状态 } - if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPENDED)) { + if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPENDED)) { // 如果任务没有被挂起 #ifdef LOSCFG_SCHED_DEBUG resumedTask->schedStat.pendTime += OsGetCurrSchedTimeCycle() - resumedTask->startTime; resumedTask->schedStat.pendCount++; @@ -712,96 +753,96 @@ VOID OsSchedTaskWake(LosTaskCB *resumedTask) BOOL OsSchedModifyTaskSchedParam(LosTaskCB *taskCB, UINT16 policy, UINT16 priority) { - if (taskCB->policy != policy) { - taskCB->policy = policy; - taskCB->timeSlice = 0; + if (taskCB->policy != policy) { // 如果任务的调度策略与传入的策略不同 + taskCB->policy = policy; // 更新任务的调度策略 + taskCB->timeSlice = 0; // 将任务的时间片设置为 0 } - if (taskCB->taskStatus & OS_TASK_STATUS_READY) { - OsSchedTaskDeQueue(taskCB); - taskCB->priority = priority; - OsSchedTaskEnQueue(taskCB); - return TRUE; + if (taskCB->taskStatus & OS_TASK_STATUS_READY) { // 如果任务处于就绪状态 + OsSchedTaskDeQueue(taskCB); // 从就绪队列中删除任务 + taskCB->priority = priority; // 更新任务的优先级 + OsSchedTaskEnQueue(taskCB); // 将任务加入就绪队列 + return TRUE; // 返回需要进行调度 } - taskCB->priority = priority; - OsHookCall(LOS_HOOK_TYPE_TASK_PRIMODIFY, taskCB, taskCB->priority); - if (taskCB->taskStatus & OS_TASK_STATUS_INIT) { - OsSchedTaskEnQueue(taskCB); - return TRUE; + taskCB->priority = priority; // 更新任务的优先级 + OsHookCall(LOS_HOOK_TYPE_TASK_PRIMODIFY, taskCB, taskCB->priority); // 调用任务优先级修改的钩子函数 + if (taskCB->taskStatus & OS_TASK_STATUS_INIT) { // 如果任务处于初始化状态 + OsSchedTaskEnQueue(taskCB); // 将任务加入就绪队列 + return TRUE; // 返回需要进行调度 } - if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) { - return TRUE; + if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) { // 如果任务处于运行状态 + return TRUE; // 返回需要进行调度 } - return FALSE; + return FALSE; // 返回不需要进行调度 } + BOOL OsSchedModifyProcessSchedParam(LosProcessCB *processCB, UINT16 policy, UINT16 priority) { LosTaskCB *taskCB = NULL; BOOL needSched = FALSE; - (VOID)policy; + (VOID)policy; // 忽略传入的调度策略 - if (processCB->processStatus & OS_PROCESS_STATUS_READY) { + if (processCB->processStatus & OS_PROCESS_STATUS_READY) { // 如果进程处于就绪状态 LOS_DL_LIST_FOR_EACH_ENTRY(taskCB, &processCB->threadSiblingList, LosTaskCB, threadList) { - if (taskCB->taskStatus & OS_TASK_STATUS_READY) { - OsSchedPriQueueDelete(processCB->priority, &taskCB->pendList, taskCB->priority); - OsSchedPriQueueEnTail(priority, &taskCB->pendList, taskCB->priority); - needSched = TRUE; + if (taskCB->taskStatus & OS_TASK_STATUS_READY) { // 如果任务处于就绪状态 + OsSchedPriQueueDelete(processCB->priority, &taskCB->pendList, taskCB->priority); // 从优先级队列中删除任务 + OsSchedPriQueueEnTail(priority, &taskCB->pendList, taskCB->priority); // 将任务按照新的优先级插入到优先级队列中 + needSched = TRUE; // 需要进行调度 } } } - processCB->priority = priority; - if (processCB->processStatus & OS_PROCESS_STATUS_RUNNING) { - needSched = TRUE; + processCB->priority = priority; // 更新进程的优先级 + if (processCB->processStatus & OS_PROCESS_STATUS_RUNNING) { // 如果进程处于运行状态 + needSched = TRUE; // 需要进行调度 } - return needSched; + return needSched; // 返回是否需要进行调度 } VOID OsSchedTick(VOID) { - Sched *sched = g_sched; - Percpu *currCpu = OsPercpuGet(); - BOOL needSched = FALSE; - LosTaskCB *runTask = OsCurrTaskGet(); - - currCpu->tickStartTime = runTask->irqStartTime; - if (currCpu->responseID == OS_INVALID_VALUE) { - if (sched->swtmrScan != NULL) { - (VOID)sched->swtmrScan(); + Sched *sched = g_sched; // 获取全局调度器结构体指针 + Percpu *currCpu = OsPercpuGet(); // 获取当前 CPU 的私有数据结构指针 + BOOL needSched = FALSE; // 是否需要进行调度 + LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务 + + currCpu->tickStartTime = runTask->irqStartTime; // 记录当前时钟中断的开始时间 + if (currCpu->responseID == OS_INVALID_VALUE) { // 如果当前 CPU 的响应 ID 无效 + if (sched->swtmrScan != NULL) { // 如果软件定时器扫描函数不为空 + (VOID)sched->swtmrScan(); // 执行软件定时器扫描函数 } - needSched = sched->taskScan(); + needSched = sched->taskScan(); // 执行任务扫描函数,判断是否需要进行调度 - if (needSched) { - LOS_MpSchedule(OS_MP_CPU_ALL); - currCpu->schedFlag |= INT_PEND_RESCH; + if (needSched) { // 如果需要进行调度 + LOS_MpSchedule(OS_MP_CPU_ALL); // 进行多核调度 + currCpu->schedFlag |= INT_PEND_RESCH; // 设置调度标志位 } } - currCpu->schedFlag |= INT_PEND_TICK; - currCpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME; + currCpu->schedFlag |= INT_PEND_TICK; // 设置时钟中断调度标志位 + currCpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME; // 设置响应时间的上限 } VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask) { - idleTask->policy = LOS_SCHED_IDLE; - idleTask->initTimeSlice = OS_SCHED_FIFO_TIMEOUT; - idleTask->timeSlice = idleTask->initTimeSlice; - OsSchedTaskEnQueue(idleTask); + idleTask->policy = LOS_SCHED_IDLE; // 设置空闲任务的调度策略为 LOS_SCHED_IDLE + idleTask->initTimeSlice = OS_SCHED_FIFO_TIMEOUT; // 设置空闲任务的初始时间片 + idleTask->timeSlice = idleTask->initTimeSlice; // 设置空闲任务的时间片 + OsSchedTaskEnQueue(idleTask); // 将空闲任务加入就绪队列 } - UINT32 OsSchedSwtmrScanRegister(SchedScan func) { - if (func == NULL) { - return LOS_NOK; + if (func == NULL) { // 如果传入的函数指针为空 + return LOS_NOK; // 返回失败 } - g_sched->swtmrScan = func; - return LOS_OK; + g_sched->swtmrScan = func; // 注册软件定时器扫描函数 + return LOS_OK; // 返回成功 } UINT32 OsSchedInit(VOID) @@ -809,143 +850,140 @@ UINT32 OsSchedInit(VOID) UINT16 index, pri; UINT32 ret; - g_sched = (Sched *)LOS_MemAlloc(m_aucSysMem0, sizeof(Sched)); - if (g_sched == NULL) { - return LOS_ERRNO_TSK_NO_MEMORY; + g_sched = (Sched *)LOS_MemAlloc(m_aucSysMem0, sizeof(Sched)); // 分配内存给全局调度器结构体指针 + if (g_sched == NULL) { // 如果内存分配失败 + return LOS_ERRNO_TSK_NO_MEMORY; // 返回内存不足错误 } - (VOID)memset_s(g_sched, sizeof(Sched), 0, sizeof(Sched)); + (VOID)memset_s(g_sched, sizeof(Sched), 0, sizeof(Sched)); // 将全局调度器结构体清零 - for (index = 0; index < OS_PRIORITY_QUEUE_NUM; index++) { + for (index = 0; index < OS_PRIORITY_QUEUE_NUM; index++) { // 遍历优先级队列 SchedQueue *queueList = &g_sched->queueList[index]; LOS_DL_LIST *priList = &queueList->priQueueList[0]; - for (pri = 0; pri < OS_PRIORITY_QUEUE_NUM; pri++) { - LOS_ListInit(&priList[pri]); + for (pri = 0; pri < OS_PRIORITY_QUEUE_NUM; pri++) { // 遍历每个优先级队列的优先级 + LOS_ListInit(&priList[pri]); // 初始化优先级队列 } } - for (index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) { - Percpu *cpu = OsPercpuGetByID(index); - ret = OsSortLinkInit(&cpu->taskSortLink); - if (ret != LOS_OK) { - return LOS_ERRNO_TSK_NO_MEMORY; + for (index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) { // 遍历每个 CPU 的私有数据结构 + Percpu *cpu = OsPercpuGetByID(index); // 获取当前 CPU 的私有数据结构指针 + ret = OsSortLinkInit(&cpu->taskSortLink); // 初始化任务排序链表 + if (ret != LOS_OK) { // 如果初始化失败 + return LOS_ERRNO_TSK_NO_MEMORY; // 返回内存不足错误 } - cpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME; - LOS_SpinInit(&cpu->taskSortLinkSpin); - LOS_SpinInit(&cpu->swtmrSortLinkSpin); + cpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME; // 设置响应时间的上限 + LOS_SpinInit(&cpu->taskSortLinkSpin); // 初始化任务排序链表的自旋锁 + LOS_SpinInit(&cpu->swtmrSortLinkSpin); // 初始化软件定时器排序链表的自旋锁 } - g_sched->taskScan = OsSchedScanTimerList; + g_sched->taskScan = OsSchedScanTimerList; // 设置任务扫描函数为默认的定时器扫描函数 #ifdef LOSCFG_SCHED_TICK_DEBUG - ret = OsSchedDebugInit(); - if (ret != LOS_OK) { - return ret; + ret = OsSchedDebugInit(); // 初始化调度器的调试功能 + if (ret != LOS_OK) { // 如果初始化失败 + return ret; // 返回错误码 } #endif - return LOS_OK; + return LOS_OK; // 返回成功 } - STATIC LosTaskCB *OsGetTopTask(VOID) { UINT32 priority, processPriority; UINT32 bitmap; LosTaskCB *newTask = NULL; - UINT32 processBitmap = g_sched->queueBitmap; + UINT32 processBitmap = g_sched->queueBitmap; // 获取全局调度器的进程位图 #ifdef LOSCFG_KERNEL_SMP - UINT32 cpuid = ArchCurrCpuid(); + UINT32 cpuid = ArchCurrCpuid(); // 获取当前 CPU 的 ID #endif - while (processBitmap) { - processPriority = CLZ(processBitmap); - SchedQueue *queueList = &g_sched->queueList[processPriority]; - bitmap = queueList->queueBitmap; - while (bitmap) { - priority = CLZ(bitmap); - LOS_DL_LIST_FOR_EACH_ENTRY(newTask, &queueList->priQueueList[priority], LosTaskCB, pendList) { + while (processBitmap) { // 遍历进程位图 + processPriority = CLZ(processBitmap); // 获取最高优先级的进程 + SchedQueue *queueList = &g_sched->queueList[processPriority]; // 获取对应优先级的队列 + bitmap = queueList->queueBitmap; // 获取优先级队列的位图 + while (bitmap) { // 遍历优先级队列的位图 + priority = CLZ(bitmap); // 获取最高优先级的任务 + LOS_DL_LIST_FOR_EACH_ENTRY(newTask, &queueList->priQueueList[priority], LosTaskCB, pendList) { #ifdef LOSCFG_KERNEL_SMP - if (newTask->cpuAffiMask & (1U << cpuid)) { + if (newTask->cpuAffiMask & (1U << cpuid)) { // 如果任务可以在当前 CPU 上运行 #endif - goto FIND_TASK; + goto FIND_TASK; // 跳转到找到任务的位置 #ifdef LOSCFG_KERNEL_SMP - } -#endif } - bitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - priority - 1)); +#endif + } + bitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - priority - 1)); // 清除已经遍历过的位 } - processBitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - processPriority - 1)); + processBitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - processPriority - 1)); // 清除已经遍历过的位 } - newTask = OS_TCB_FROM_TID(OsPercpuGet()->idleTaskID); + newTask = OS_TCB_FROM_TID(OsPercpuGet()->idleTaskID); // 如果没有找到任务,则返回空闲任务 FIND_TASK: - OsSchedDeTaskQueue(newTask, OS_PCB_FROM_PID(newTask->processID)); - return newTask; + OsSchedDeTaskQueue(newTask, OS_PCB_FROM_PID(newTask->processID)); // 从任务队列中删除任务 + return newTask; // 返回找到的任务 } - VOID OsSchedStart(VOID) { - UINT32 cpuid = ArchCurrCpuid(); + UINT32 cpuid = ArchCurrCpuid(); // 获取当前 CPU 的 ID UINT32 intSave; - SCHEDULER_LOCK(intSave); + SCHEDULER_LOCK(intSave); // 锁住调度器 - if (cpuid == 0) { - OsTickStart(); + if (cpuid == 0) { // 如果是第一个 CPU + OsTickStart(); // 启动系统时钟中断 } - LosTaskCB *newTask = OsGetTopTask(); - LosProcessCB *newProcess = OS_PCB_FROM_PID(newTask->processID); + LosTaskCB *newTask = OsGetTopTask(); // 获取要运行的任务 + LosProcessCB *newProcess = OS_PCB_FROM_PID(newTask->processID); // 获取任务所属的进程 - newTask->taskStatus |= OS_TASK_STATUS_RUNNING; - newProcess->processStatus |= OS_PROCESS_STATUS_RUNNING; - newProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(newProcess->processStatus); + newTask->taskStatus |= OS_TASK_STATUS_RUNNING; // 设置任务状态为运行中 + newProcess->processStatus |= OS_PROCESS_STATUS_RUNNING; // 设置进程状态为运行中 + newProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(newProcess->processStatus); // 增加进程的运行任务计数 - OsSchedSetStartTime(HalClockGetCycles()); - newTask->startTime = OsGetCurrSchedTimeCycle(); + OsSchedSetStartTime(HalClockGetCycles()); // 设置调度器的起始时间 + newTask->startTime = OsGetCurrSchedTimeCycle(); // 设置任务的起始时间 #ifdef LOSCFG_KERNEL_SMP /* * attention: current cpu needs to be set, in case first task deletion * may fail because this flag mismatch with the real current cpu. */ - newTask->currCpu = cpuid; + newTask->currCpu = cpuid; // 设置任务所在的 CPU #endif - OsCurrTaskSet((VOID *)newTask); + OsCurrTaskSet((VOID *)newTask); // 设置当前任务 /* System start schedule */ - OS_SCHEDULER_SET(cpuid); + OS_SCHEDULER_SET(cpuid); // 设置调度器标志,表示系统已经开始调度 - OsPercpuGet()->responseID = OS_INVALID; - OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, newTask->startTime + newTask->timeSlice, OS_INVALID); + OsPercpuGet()->responseID = OS_INVALID; // 初始化响应 ID + OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, newTask->startTime + newTask->timeSlice, OS_INVALID); // 设置下一个任务的到期时间 - PRINTK("cpu %d entering scheduler\n", cpuid); - OsTaskContextLoad(newTask); + PRINTK("cpu %d entering scheduler\n", cpuid); // 打印进入调度器的消息 + OsTaskContextLoad(newTask); // 加载任务上下文并开始执行任务 } #ifdef LOSCFG_KERNEL_SMP VOID OsSchedToUserReleaseLock(VOID) { /* The scheduling lock needs to be released before returning to user mode */ - LOCKDEP_CHECK_OUT(&g_taskSpin); - ArchSpinUnlock(&g_taskSpin.rawLock); + LOCKDEP_CHECK_OUT(&g_taskSpin); // 检查任务自旋锁是否正确释放 + ArchSpinUnlock(&g_taskSpin.rawLock); // 解锁任务自旋锁 - OsPercpuGet()->taskLockCnt--; + OsPercpuGet()->taskLockCnt--; // 减少任务锁计数 } #endif - #ifdef LOSCFG_BASE_CORE_TSK_MONITOR STATIC VOID OsTaskStackCheck(LosTaskCB *runTask, LosTaskCB *newTask) { - if (!OS_STACK_MAGIC_CHECK(runTask->topOfStack)) { - LOS_Panic("CURRENT task ID: %s:%d stack overflow!\n", runTask->taskName, runTask->taskID); + if (!OS_STACK_MAGIC_CHECK(runTask->topOfStack)) { // 检查当前运行任务的栈是否溢出 + LOS_Panic("CURRENT task ID: %s:%d stack overflow!\n", runTask->taskName, runTask->taskID); // 如果溢出,触发异常并打印错误信息 } if (((UINTPTR)(newTask->stackPointer) <= newTask->topOfStack) || - ((UINTPTR)(newTask->stackPointer) > (newTask->topOfStack + newTask->stackSize))) { + ((UINTPTR)(newTask->stackPointer) > (newTask->topOfStack + newTask->stackSize))) { // 检查新任务的栈指针是否合法 LOS_Panic("HIGHEST task ID: %s:%u SP error! StackPointer: %p TopOfStack: %p\n", - newTask->taskName, newTask->taskID, newTask->stackPointer, newTask->topOfStack); + newTask->taskName, newTask->taskID, newTask->stackPointer, newTask->topOfStack); // 如果不合法,触发异常并打印错误信息 } } #endif @@ -953,178 +991,192 @@ STATIC VOID OsTaskStackCheck(LosTaskCB *runTask, LosTaskCB *newTask) STATIC INLINE VOID OsSchedSwitchCheck(LosTaskCB *runTask, LosTaskCB *newTask) { #ifdef LOSCFG_BASE_CORE_TSK_MONITOR - OsTaskStackCheck(runTask, newTask); + OsTaskStackCheck(runTask, newTask); // 检查任务栈的合法性 #endif /* LOSCFG_BASE_CORE_TSK_MONITOR */ - OsHookCall(LOS_HOOK_TYPE_TASK_SWITCHEDIN, newTask, runTask); + OsHookCall(LOS_HOOK_TYPE_TASK_SWITCHEDIN, newTask, runTask); // 调用任务切换回调函数 } STATIC INLINE VOID OsSchedSwitchProcess(LosProcessCB *runProcess, LosProcessCB *newProcess) { - runProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_DEC(runProcess->processStatus); - newProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(newProcess->processStatus); + runProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_DEC(runProcess->processStatus); // 减少当前进程的运行任务计数 + newProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(newProcess->processStatus); // 增加新进程的运行任务计数 - LOS_ASSERT(!(OS_PROCESS_GET_RUNTASK_COUNT(newProcess->processStatus) > LOSCFG_KERNEL_CORE_NUM)); - if (OS_PROCESS_GET_RUNTASK_COUNT(runProcess->processStatus) == 0) { - runProcess->processStatus &= ~OS_PROCESS_STATUS_RUNNING; + LOS_ASSERT(!(OS_PROCESS_GET_RUNTASK_COUNT(newProcess->processStatus) > LOSCFG_KERNEL_CORE_NUM)); // 断言新进程的运行任务计数不超过 CPU 核心数 + if (OS_PROCESS_GET_RUNTASK_COUNT(runProcess->processStatus) == 0) { // 如果当前进程的运行任务计数为 0 + runProcess->processStatus &= ~OS_PROCESS_STATUS_RUNNING; // 清除当前进程的运行状态标志 } - LOS_ASSERT(!(newProcess->processStatus & OS_PROCESS_STATUS_PENDING)); - newProcess->processStatus |= OS_PROCESS_STATUS_RUNNING; + LOS_ASSERT(!(newProcess->processStatus & OS_PROCESS_STATUS_PENDING)); // 断言新进程的状态不是挂起状态 + newProcess->processStatus |= OS_PROCESS_STATUS_RUNNING; // 设置新进程的运行状态标志 #ifdef LOSCFG_KERNEL_VM - if (OsProcessIsUserMode(newProcess)) { - LOS_ArchMmuContextSwitch(&newProcess->vmSpace->archMmu); + if (OsProcessIsUserMode(newProcess)) { // 如果新进程是用户态进程 + LOS_ArchMmuContextSwitch(&newProcess->vmSpace->archMmu); // 切换内存管理单元上下文 } #endif - OsCurrProcessSet(newProcess); + OsCurrProcessSet(newProcess); // 设置当前进程为新进程 } - STATIC VOID OsSchedTaskSwicth(LosTaskCB *runTask, LosTaskCB *newTask) { UINT64 endTime; - OsSchedSwitchCheck(runTask, newTask); + OsSchedSwitchCheck(runTask, newTask); // 检查任务切换的相关条件 - runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING; - newTask->taskStatus |= OS_TASK_STATUS_RUNNING; + runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING; // 清除当前任务的运行状态标志 + newTask->taskStatus |= OS_TASK_STATUS_RUNNING; // 设置新任务的运行状态标志 #ifdef LOSCFG_KERNEL_SMP /* mask new running task's owner processor */ - runTask->currCpu = OS_TASK_INVALID_CPUID; - newTask->currCpu = ArchCurrCpuid(); + runTask->currCpu = OS_TASK_INVALID_CPUID; // 设置当前任务的 CPU ID 为无效值 + newTask->currCpu = ArchCurrCpuid(); // 设置新任务的 CPU ID 为当前 CPU 的 ID #endif - OsCurrTaskSet((VOID *)newTask); - LosProcessCB *newProcess = OS_PCB_FROM_PID(newTask->processID); - LosProcessCB *runProcess = OS_PCB_FROM_PID(runTask->processID); - if (runProcess != newProcess) { - OsSchedSwitchProcess(runProcess, newProcess); + OsCurrTaskSet((VOID *)newTask); // 设置当前任务为新任务 + LosProcessCB *newProcess = OS_PCB_FROM_PID(newTask->processID); // 获取新任务所属的进程 + LosProcessCB *runProcess = OS_PCB_FROM_PID(runTask->processID); // 获取当前任务所属的进程 + if (runProcess != newProcess) { // 如果当前任务和新任务所属的进程不同 + OsSchedSwitchProcess(runProcess, newProcess); // 进行进程切换 } - if (OsProcessIsUserMode(newProcess)) { - OsCurrUserTaskSet(newTask->userArea); + if (OsProcessIsUserMode(newProcess)) { // 如果新进程是用户态进程 + OsCurrUserTaskSet(newTask->userArea); // 设置当前用户态任务为新任务的用户态区域 } #ifdef LOSCFG_KERNEL_CPUP - OsCpupCycleEndStart(runTask->taskID, newTask->taskID); + OsCpupCycleEndStart(runTask->taskID, newTask->taskID); // 记录当前任务和新任务的 CPU 周期计数 #endif #ifdef LOSCFG_SCHED_DEBUG - UINT64 waitStartTime = newTask->startTime; + UINT64 waitStartTime = newTask->startTime; // 保存等待调度的起始时间 #endif if (runTask->taskStatus & OS_TASK_STATUS_READY) { /* When a thread enters the ready queue, its slice of time is updated */ - newTask->startTime = runTask->startTime; + newTask->startTime = runTask->startTime; // 如果当前任务是就绪状态,则将新任务的起始时间设置为当前任务的起始时间 } else { /* The currently running task is blocked */ - newTask->startTime = OsGetCurrSchedTimeCycle(); + newTask->startTime = OsGetCurrSchedTimeCycle(); // 如果当前任务是阻塞状态,则将新任务的起始时间设置为当前调度时间 /* The task is in a blocking state and needs to update its time slice before pend */ - OsTimeSliceUpdate(runTask, newTask->startTime); + OsTimeSliceUpdate(runTask, newTask->startTime); // 更新当前任务的时间片 if (runTask->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) { - OsAdd2SortLink(&runTask->sortList, runTask->startTime, runTask->waitTimes, OS_SORT_LINK_TASK); + OsAdd2SortLink(&runTask->sortList, runTask->startTime, runTask->waitTimes, OS_SORT_LINK_TASK); // 将当前任务添加到排序链表中 } } if (newTask->policy == LOS_SCHED_RR) { - endTime = newTask->startTime + newTask->timeSlice; + endTime = newTask->startTime + newTask->timeSlice; // 如果新任务是轮转调度策略,则计算新任务的结束时间 } else { - endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; + endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; // 如果新任务不是轮转调度策略,则设置新任务的结束时间为最大响应时间 } - OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, endTime, runTask->taskID); + OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, endTime, runTask->taskID); // 设置下一个任务的到期时间 #ifdef LOSCFG_SCHED_DEBUG - newTask->schedStat.waitSchedTime += newTask->startTime - waitStartTime; - newTask->schedStat.waitSchedCount++; - runTask->schedStat.runTime = runTask->schedStat.allRuntime; - runTask->schedStat.switchCount++; + newTask->schedStat.waitSchedTime += newTask->startTime - waitStartTime; // 更新新任务的等待调度时间 + newTask->schedStat.waitSchedCount++; // 增加新任务的等待调度次数 + runTask->schedStat.runTime = runTask->schedStat.allRuntime; // 更新当前任务的运行时间 + runTask->schedStat.switchCount++; // 增加当前任务的切换次数 #endif /* do the task context switch */ - OsTaskSchedule(newTask, runTask); + OsTaskSchedule(newTask, runTask); // 进行任务上下文切换 } - +/*在切换任务之前,它首先调用OsSchedSwitchCheck函数来检查任务切换的相关条件。然后,它更新当前任务和新任务的运行状态标志, +并进行一些其他操作,如设置当前任务、进行进程切换、设置用户态任务等。接下来,它根据任务的状态更新新任务的起始时间,并设置 +下一个任务的到期时间。最后,它调用OsTaskSchedule函数进行任务上下文切换。 +*/ VOID OsSchedIrqEndCheckNeedSched(VOID) { - Percpu *percpu = OsPercpuGet(); - LosTaskCB *runTask = OsCurrTaskGet(); + Percpu *percpu = OsPercpuGet(); // 获取当前 CPU 的数据结构指针 + LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务 - OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle()); - if (runTask->timeSlice <= OS_TIME_SLICE_MIN) { - percpu->schedFlag |= INT_PEND_RESCH; + OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle()); // 更新当前任务的时间片 + if (runTask->timeSlice <= OS_TIME_SLICE_MIN) { // 如果当前任务的时间片小于等于最小时间片 + percpu->schedFlag |= INT_PEND_RESCH; // 设置调度标志,表示需要进行任务切换 } - if (OsPreemptable() && (percpu->schedFlag & INT_PEND_RESCH)) { - percpu->schedFlag &= ~INT_PEND_RESCH; + if (OsPreemptable() && (percpu->schedFlag & INT_PEND_RESCH)) { // 如果可以抢占且需要进行任务切换 + percpu->schedFlag &= ~INT_PEND_RESCH; // 清除调度标志 - LOS_SpinLock(&g_taskSpin); + LOS_SpinLock(&g_taskSpin); // 获取任务自旋锁 - OsSchedTaskEnQueue(runTask); + OsSchedTaskEnQueue(runTask); // 将当前任务加入就绪队列 - LosTaskCB *newTask = OsGetTopTask(); - if (runTask != newTask) { - OsSchedTaskSwicth(runTask, newTask); - LOS_SpinUnlock(&g_taskSpin); + LosTaskCB *newTask = OsGetTopTask(); // 获取优先级最高的任务 + if (runTask != newTask) { // 如果当前任务不是优先级最高的任务 + OsSchedTaskSwicth(runTask, newTask); // 进行任务切换 + LOS_SpinUnlock(&g_taskSpin); // 释放任务自旋锁 return; } - LOS_SpinUnlock(&g_taskSpin); + LOS_SpinUnlock(&g_taskSpin); // 释放任务自旋锁 } - if (percpu->schedFlag & INT_PEND_TICK) { - OsSchedUpdateExpireTime(runTask->startTime); + if (percpu->schedFlag & INT_PEND_TICK) { // 如果有时钟中断挂起 + OsSchedUpdateExpireTime(runTask->startTime); // 更新任务的到期时间 } } VOID OsSchedResched(VOID) { - LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); + LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); // 断言任务自旋锁已持有 #ifdef LOSCFG_KERNEL_SMP - LOS_ASSERT(OsPercpuGet()->taskLockCnt == 1); + LOS_ASSERT(OsPercpuGet()->taskLockCnt == 1); // 断言任务锁计数为1 #else - LOS_ASSERT(OsPercpuGet()->taskLockCnt == 0); + LOS_ASSERT(OsPercpuGet()->taskLockCnt == 0); // 断言任务锁计数为0 #endif - OsPercpuGet()->schedFlag &= ~INT_PEND_RESCH; - LosTaskCB *runTask = OsCurrTaskGet(); - LosTaskCB *newTask = OsGetTopTask(); - if (runTask == newTask) { + OsPercpuGet()->schedFlag &= ~INT_PEND_RESCH; // 清除调度标志 + LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务 + LosTaskCB *newTask = OsGetTopTask(); // 获取优先级最高的任务 + if (runTask == newTask) { // 如果当前任务就是优先级最高的任务 return; } - OsSchedTaskSwicth(runTask, newTask); + OsSchedTaskSwicth(runTask, newTask); // 进行任务切换 } +/*这段代码实现了在中断结束时检查是否需要进行任务切换的函数OsSchedIrqEndCheckNeedSched, +以及在调度器需要重新调度时执行任务切换的函数OsSchedResched。 + +OsSchedIrqEndCheckNeedSched函数首先更新当前任务的时间片,并检查当前任务的时间片是否小于 +等于最小时间片。如果是,则设置调度标志,表示需要进行任务切换。然后,它检查是否可以抢占且 +调度标志已被设置。如果满足条件,则获取任务自旋锁,并将当前任务加入就绪队列。接下来,它获 +取优先级最高的任务,如果当前任务不是优先级最高的任务,则进行任务切换,并释放任务自旋锁。 +最后,如果有时钟中断挂起,它更新任务的到期时间。 + +OsSchedResched函数首先断言任务自旋锁已持有,并根据配置选项判断任务锁计数是否为1(SMP) +或者为0(非SMP)。然后,它清除调度标志,并获取当前运行的任务和优先级最高的任务。如果当前 +任务就是优先级最高的任务,则直接返回。否则,它进行任务切换。*/ VOID LOS_Schedule(VOID) { UINT32 intSave; - LosTaskCB *runTask = OsCurrTaskGet(); + LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务 - if (OS_INT_ACTIVE) { - OsPercpuGet()->schedFlag |= INT_PEND_RESCH; + if (OS_INT_ACTIVE) { // 如果处于中断上下文 + OsPercpuGet()->schedFlag |= INT_PEND_RESCH; // 设置调度标志,表示需要进行任务切换 return; } - if (!OsPreemptable()) { + if (!OsPreemptable()) { // 如果不允许抢占 return; } /* * trigger schedule in task will also do the slice check - * if neccessary, it will give up the timeslice more in time. - * otherwhise, there's no other side effects. + * if necessary, it will give up the timeslice more in time. + * otherwise, there's no other side effects. */ - SCHEDULER_LOCK(intSave); + SCHEDULER_LOCK(intSave); // 获取调度器锁,禁止调度器抢占 - OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle()); + OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle()); // 更新当前任务的时间片 /* add run task back to ready queue */ - OsSchedTaskEnQueue(runTask); + OsSchedTaskEnQueue(runTask); // 将当前任务加入就绪队列 /* reschedule to new thread */ - OsSchedResched(); + OsSchedResched(); // 进行任务切换 - SCHEDULER_UNLOCK(intSave); + SCHEDULER_UNLOCK(intSave); // 释放调度器锁 } STATIC INLINE LOS_DL_LIST *OsSchedLockPendFindPosSub(const LosTaskCB *runTask, const LOS_DL_LIST *lockList) @@ -1151,20 +1203,23 @@ LOS_DL_LIST *OsSchedLockPendFindPos(const LosTaskCB *runTask, LOS_DL_LIST *lockL { LOS_DL_LIST *node = NULL; - if (LOS_ListEmpty(lockList)) { + if (LOS_ListEmpty(lockList)) { // 如果锁的等待队列为空 node = lockList; } else { LosTaskCB *pendedTask1 = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(lockList)); LosTaskCB *pendedTask2 = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_LAST(lockList)); - if (pendedTask1->priority > runTask->priority) { + if (pendedTask1->priority > runTask->priority) { // 如果最高优先级的等待任务的优先级高于当前任务的优先级 node = lockList->pstNext; - } else if (pendedTask2->priority <= runTask->priority) { + } else if (pendedTask2->priority <= runTask->priority) { // 如果最低优先级的等待任务的优先级小于等于当前任务的优先级 node = lockList; } else { - node = OsSchedLockPendFindPosSub(runTask, lockList); + node = OsSchedLockPendFindPosSub(runTask, lockList); // 在等待队列中查找当前任务应该插入的位置 } } return node; } - +/*LOS_Schedule函数用于触发调度器进行任务切换。在函数中,首先判断是否处于中断上下文中, +如果是,则设置调度标志,表示需要进行任务切换,然后返回。接下来,判断当前任务是否可被抢占, +如果不可抢占,则直接返回。然后,获取调度器锁,并更新当前任务的时间片。接着,将当前任务加入就绪队列, +并调用OsSchedResched函数进行任务*/ \ No newline at end of file diff --git a/sched/sched_sq/los_sortlink.c b/sched/sched_sq/los_sortlink.c index 9115892..52770ad 100644 --- a/sched/sched_sq/los_sortlink.c +++ b/sched/sched_sq/los_sortlink.c @@ -35,94 +35,105 @@ #include "los_percpu_pri.h" #include "los_sched_pri.h" #include "los_mp.h" - UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader) { - LOS_ListInit(&sortLinkHeader->sortLink); - sortLinkHeader->nodeNum = 0; + LOS_ListInit(&sortLinkHeader->sortLink); // 初始化排序链表头 + sortLinkHeader->nodeNum = 0; // 初始化节点数量为0 return LOS_OK; } STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) { - LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; + LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; // 获取排序链表头指针 - if (LOS_ListEmpty(head)) { - LOS_ListHeadInsert(head, &sortList->sortLinkNode); - sortLinkHeader->nodeNum++; + if (LOS_ListEmpty(head)) { // 如果链表为空 + LOS_ListHeadInsert(head, &sortList->sortLinkNode); // 将节点插入链表头 + sortLinkHeader->nodeNum++; // 节点数量加1 return; } - SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode); - if (listSorted->responseTime > sortList->responseTime) { - LOS_ListAdd(head, &sortList->sortLinkNode); - sortLinkHeader->nodeNum++; + SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode); // 获取链表中的第一个节点 + if (listSorted->responseTime > sortList->responseTime) { // 如果插入节点的响应时间小于第一个节点的响应时间 + LOS_ListAdd(head, &sortList->sortLinkNode); // 将节点插入链表头之前 + sortLinkHeader->nodeNum++; // 节点数量加1 return; - } else if (listSorted->responseTime == sortList->responseTime) { - LOS_ListAdd(head->pstNext, &sortList->sortLinkNode); - sortLinkHeader->nodeNum++; + } else if (listSorted->responseTime == sortList->responseTime) { // 如果插入节点的响应时间等于第一个节点的响应时间 + LOS_ListAdd(head->pstNext, &sortList->sortLinkNode); // 将节点插入第一个节点之后 + sortLinkHeader->nodeNum++; // 节点数量加1 return; } - LOS_DL_LIST *prevNode = head->pstPrev; + LOS_DL_LIST *prevNode = head->pstPrev; // 获取链表中的最后一个节点 do { - listSorted = LOS_DL_LIST_ENTRY(prevNode, SortLinkList, sortLinkNode); - if (listSorted->responseTime <= sortList->responseTime) { - LOS_ListAdd(prevNode, &sortList->sortLinkNode); - sortLinkHeader->nodeNum++; + listSorted = LOS_DL_LIST_ENTRY(prevNode, SortLinkList, sortLinkNode); // 获取当前节点 + if (listSorted->responseTime <= sortList->responseTime) { // 如果插入节点的响应时间小于等于当前节点的响应时间 + LOS_ListAdd(prevNode, &sortList->sortLinkNode); // 将节点插入当前节点之前 + sortLinkHeader->nodeNum++; // 节点数量加1 break; } - prevNode = prevNode->pstPrev; + prevNode = prevNode->pstPrev; // 继续向前遍历 } while (1); } +/*OsSortLinkInit函数用于初始化排序链表头。在函数中,它调用LOS_ListInit函数初始化排序链表头,并将节点数量设置为0,然后返回LOS_OK。 +OsAddNode2SortLink函数用于将节点插入排序链表中。在函数中,首先获取排序链表头指针。然后,如果链表为空,将节点插入链表头,并增加节点数量, +然后返回。如果链表不为空,获取链表中的第一个节点,并比较插入节点的响应时间与第一个节点的响应时间。如果插入节点的响应时间小于第一个节点的 +响应时间,将节点插入链表头之前,并增加节点数量,然后返回。如果插入节点的响应时间等于第一个节点的响应时间,将节点插入第一个节点之后, +并增加节点数量,然后返回。如果插入节点的响应时间大于第一个节点的响应时间,获取链表中的最后一个节点,并从链表尾部向前遍历。在遍历过程中, +如果插入节点的响应时间小于等于当前节点的响应时间,将节点插入当前节点之前,并增加节点数量,然后退出循环。最后,返回。*/ VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) { - LOS_ListDelete(&sortList->sortLinkNode); - SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME); - sortLinkHeader->nodeNum--; + LOS_ListDelete(&sortList->sortLinkNode); // 从排序链表中删除节点 + SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME); // 将节点的响应时间设置为无效值 + sortLinkHeader->nodeNum--; // 节点数量减1 } STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime) { - LOS_DL_LIST *head = &sortHeader->sortLink; - LOS_DL_LIST *list = head->pstNext; + LOS_DL_LIST *head = &sortHeader->sortLink; // 获取排序链表头指针 + LOS_DL_LIST *list = head->pstNext; // 获取链表中的第一个节点 - if (LOS_ListEmpty(head)) { - return OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; + if (LOS_ListEmpty(head)) { // 如果链表为空 + return OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; // 返回最大响应时间减去精度 } - SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode); - if (listSorted->responseTime <= (startTime + OS_TICK_RESPONSE_PRECISION)) { - return startTime + OS_TICK_RESPONSE_PRECISION; + SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode); // 获取第一个节点 + if (listSorted->responseTime <= (startTime + OS_TICK_RESPONSE_PRECISION)) { // 如果第一个节点的响应时间小于等于(开始时间加上精度) + return startTime + OS_TICK_RESPONSE_PRECISION; // 返回开始时间加上精度 } - return listSorted->responseTime; + return listSorted->responseTime; // 返回第一个节点的响应时间 } STATIC Percpu *OsFindIdleCpu(UINT16 *idleCpuID) { - Percpu *idleCpu = OsPercpuGetByID(0); - *idleCpuID = 0; + Percpu *idleCpu = OsPercpuGetByID(0); // 获取CPU 0 的PerCPU结构体指针 + *idleCpuID = 0; // 将空闲CPU的ID设置为0 +/*OsDeleteNodeSortLink函数用于从排序链表中删除节点。在函数中,它调用LOS_ListDelete函数删除节点,并将节点的响应时间设置为无效值,然后将节点数量减1。 + +OsGetSortLinkNextExpireTime函数用于获取排序链表中下一个即将到期的节点的响应时间。在函数中,首先获取排序链表头指针和链表中的第一个节点。 +然后,如果链表为空,返回最大响应时间减去精度。如果第一个节点的响应时间小于等于(开始时间加上精度),返回开始时间加上精度。否则,返回第一个节点的响应时间。 + +OsFindIdleCpu函数用于查找空闲的CPU。在函数中,它通过调用OsPercpuGetByID函数获取CPU 0 的PerCPU结构体指针,并将空闲CPU的ID设置为0。*/ #ifdef LOSCFG_KERNEL_SMP - UINT16 cpuID = 1; - UINT32 nodeNum = idleCpu->taskSortLink.nodeNum + idleCpu->swtmrSortLink.nodeNum; + UINT16 cpuID = 1; // 初始化CPU ID为1 + UINT32 nodeNum = idleCpu->taskSortLink.nodeNum + idleCpu->swtmrSortLink.nodeNum; // 获取当前CPU的任务排序链表和软件定时器排序链表的节点数量之和 do { - Percpu *cpu = OsPercpuGetByID(cpuID); - UINT32 temp = cpu->taskSortLink.nodeNum + cpu->swtmrSortLink.nodeNum; - if (nodeNum > temp) { - idleCpu = cpu; - *idleCpuID = cpuID; + Percpu *cpu = OsPercpuGetByID(cpuID); // 获取指定CPU的PerCPU结构体指针 + UINT32 temp = cpu->taskSortLink.nodeNum + cpu->swtmrSortLink.nodeNum; // 获取指定CPU的任务排序链表和软件定时器排序链表的节点数量之和 + if (nodeNum > temp) { // 如果当前CPU的节点数量之和大于指定CPU的节点数量之和 + idleCpu = cpu; // 更新空闲CPU指针 + *idleCpuID = cpuID; // 更新空闲CPU的ID } - cpuID++; - } while (cpuID < LOSCFG_KERNEL_CORE_NUM); + cpuID++; // 继续遍历下一个CPU + } while (cpuID < LOSCFG_KERNEL_CORE_NUM); // 遍历完所有的CPU #endif - return idleCpu; + return idleCpu; // 返回空闲CPU的指针 } VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type) @@ -133,100 +144,107 @@ VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, Sort SPIN_LOCK_S *spinLock = NULL; UINT16 idleCpu; - if (OS_SCHEDULER_ACTIVE) { - cpu = OsFindIdleCpu(&idleCpu); + if (OS_SCHEDULER_ACTIVE) { // 如果调度器处于活动状态 + cpu = OsFindIdleCpu(&idleCpu); // 查找空闲的CPU } else { - idleCpu = ArchCurrCpuid(); - cpu = OsPercpuGet(); + idleCpu = ArchCurrCpuid(); // 获取当前CPU的ID + cpu = OsPercpuGet(); // 获取当前CPU的PerCPU结构体指针 } if (type == OS_SORT_LINK_TASK) { - sortLinkHeader = &cpu->taskSortLink; - spinLock = &cpu->taskSortLinkSpin; + sortLinkHeader = &cpu->taskSortLink; // 获取任务排序链表头指针 + spinLock = &cpu->taskSortLinkSpin; // 获取任务排序链表自旋锁 } else if (type == OS_SORT_LINK_SWTMR) { - sortLinkHeader = &cpu->swtmrSortLink; - spinLock = &cpu->swtmrSortLinkSpin; + sortLinkHeader = &cpu->swtmrSortLink; // 获取软件定时器排序链表头指针 + spinLock = &cpu->swtmrSortLinkSpin; // 获取软件定时器排序链表自旋锁 } else { - LOS_Panic("Sort link type error : %u\n", type); + LOS_Panic("Sort link type error : %u\n", type); // 报错,排序链表类型错误 } - LOS_SpinLockSave(spinLock, &intSave); - SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK); - OsAddNode2SortLink(sortLinkHeader, node); + LOS_SpinLockSave(spinLock, &intSave); // 保存自旋锁状态并禁止中断 + SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK); // 设置节点的响应时间 + OsAddNode2SortLink(sortLinkHeader, node); // 将节点插入排序链表中 #ifdef LOSCFG_KERNEL_SMP - node->cpuid = idleCpu; - if (idleCpu != ArchCurrCpuid()) { - LOS_MpSchedule(CPUID_TO_AFFI_MASK(idleCpu)); + node->cpuid = idleCpu; // 设置节点的CPU ID为空闲CPU的ID + if (idleCpu != ArchCurrCpuid()) { // 如果空闲CPU的ID不等于当前CPU的ID + LOS_MpSchedule(CPUID_TO_AFFI_MASK(idleCpu)); // 调度空闲CPU执行任务 } #endif - LOS_SpinUnlockRestore(spinLock, intSave); + LOS_SpinUnlockRestore(spinLock, intSave); // 恢复自旋锁状态并允许中断 } VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type) { UINT32 intSave; #ifdef LOSCFG_KERNEL_SMP - Percpu *cpu = OsPercpuGetByID(node->cpuid); + Percpu *cpu = OsPercpuGetByID(node->cpuid); // 获取节点所在CPU的PerCPU结构体指针 #else - Percpu *cpu = OsPercpuGetByID(0); + Percpu *cpu = OsPercpuGetByID(0); // 获取CPU 0 的PerCPU结构体指针 #endif +/*OsAdd2SortLink函数用于将节点插入排序链表中。在函数中,首先根据调度器的活动状态选择空闲的CPU。 +如果调度器处于活动状态,调用OsFindIdleCpu函数查找空闲的CPU;否则,获取当前CPU的ID, +并通过OsPercpuGet函数获取当前CPU的PerCPU结构体指针。然后,根据排序链表类型选择相应的排序链表头指针和自旋锁。 +接下来,保存自旋锁状态并禁止中断,设置节点的响应时间,将节点插入排序链表中,根据SMP配置设置节点的CPU ID, +并如果空闲CPU的ID不等于当前CPU的ID,调度空闲CPU执行任务。最后,恢复自旋锁状态并允许中断。 + +OsDeleteSortLink函数用于从排序链表中删除节点。在函数中,首先保存自旋锁状态并禁止中断。如果SMP配置开启, +根据节点的CPU ID获取节点所在CPU的PerCPU结构体指针;否则,获取CPU 0 的PerCPU结构体指针。*/ SPIN_LOCK_S *spinLock = NULL; SortLinkAttribute *sortLinkHeader = NULL; if (type == OS_SORT_LINK_TASK) { - sortLinkHeader = &cpu->taskSortLink; - spinLock = &cpu->taskSortLinkSpin; + sortLinkHeader = &cpu->taskSortLink; // 获取任务排序链表头指针 + spinLock = &cpu->taskSortLinkSpin; // 获取任务排序链表自旋锁 } else if (type == OS_SORT_LINK_SWTMR) { - sortLinkHeader = &cpu->swtmrSortLink; - spinLock = &cpu->swtmrSortLinkSpin; + sortLinkHeader = &cpu->swtmrSortLink; // 获取软件定时器排序链表头指针 + spinLock = &cpu->swtmrSortLinkSpin; // 获取软件定时器排序链表自旋锁 } else { - LOS_Panic("Sort link type error : %u\n", type); + LOS_Panic("Sort link type error : %u\n", type); // 报错,排序链表类型错误 } - LOS_SpinLockSave(spinLock, &intSave); - if (node->responseTime != OS_SORT_LINK_INVALID_TIME) { - OsDeleteNodeSortLink(sortLinkHeader, node); + LOS_SpinLockSave(spinLock, &intSave); // 保存自旋锁状态并禁止中断 + if (node->responseTime != OS_SORT_LINK_INVALID_TIME) { // 如果节点的响应时间不为无效时间 + OsDeleteNodeSortLink(sortLinkHeader, node); // 从排序链表中删除节点 } - LOS_SpinUnlockRestore(spinLock, intSave); + LOS_SpinUnlockRestore(spinLock, intSave); // 恢复自旋锁状态并允许中断 } - UINT64 OsGetNextExpireTime(UINT64 startTime) { UINT32 intSave; - Percpu *cpu = OsPercpuGet(); - SortLinkAttribute *taskHeader = &cpu->taskSortLink; - SortLinkAttribute *swtmrHeader = &cpu->swtmrSortLink; + Percpu *cpu = OsPercpuGet(); // 获取当前CPU的PerCPU结构体指针 + SortLinkAttribute *taskHeader = &cpu->taskSortLink; // 获取任务排序链表头指针 + SortLinkAttribute *swtmrHeader = &cpu->swtmrSortLink; // 获取软件定时器排序链表头指针 - LOS_SpinLockSave(&cpu->taskSortLinkSpin, &intSave); - UINT64 taskExpirTime = OsGetSortLinkNextExpireTime(taskHeader, startTime); - LOS_SpinUnlockRestore(&cpu->taskSortLinkSpin, intSave); + LOS_SpinLockSave(&cpu->taskSortLinkSpin, &intSave); // 保存任务排序链表自旋锁状态并禁止中断 + UINT64 taskExpirTime = OsGetSortLinkNextExpireTime(taskHeader, startTime); // 获取任务排序链表中下一个过期时间 + LOS_SpinUnlockRestore(&cpu->taskSortLinkSpin, intSave); // 恢复任务排序链表自旋锁状态并允许中断 - LOS_SpinLockSave(&cpu->swtmrSortLinkSpin, &intSave); - UINT64 swtmrExpirTime = OsGetSortLinkNextExpireTime(swtmrHeader, startTime); - LOS_SpinUnlockRestore(&cpu->swtmrSortLinkSpin, intSave); + LOS_SpinLockSave(&cpu->swtmrSortLinkSpin, &intSave); // 保存软件定时器排序链表自旋锁状态并禁止中断 + UINT64 swtmrExpirTime = OsGetSortLinkNextExpireTime(swtmrHeader, startTime); // 获取软件定时器排序链表中下一个过期时间 + LOS_SpinUnlockRestore(&cpu->swtmrSortLinkSpin, intSave); // 恢复软件定时器排序链表自旋锁状态并允许中断 - return (taskExpirTime < swtmrExpirTime) ? taskExpirTime : swtmrExpirTime; + return (taskExpirTime < swtmrExpirTime) ? taskExpirTime : swtmrExpirTime; // 返回较小的过期时间 } UINT32 OsSortLinkGetTargetExpireTime(const SortLinkList *targetSortList) { - UINT64 currTimes = OsGetCurrSchedTimeCycle(); - if (currTimes >= targetSortList->responseTime) { - return 0; + UINT64 currTimes = OsGetCurrSchedTimeCycle(); // 获取当前调度时间 + if (currTimes >= targetSortList->responseTime) { // 如果当前时间大于等于目标排序链表节点的响应时间 + return 0; // 返回0,表示已经过期 } - return (UINT32)(targetSortList->responseTime - currTimes) / OS_CYCLE_PER_TICK; + return (UINT32)(targetSortList->responseTime - currTimes) / OS_CYCLE_PER_TICK; // 计算剩余的滴答数 } UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader) { - LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; + LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; // 获取排序链表头节点 - if (LOS_ListEmpty(head)) { - return 0; + if (LOS_ListEmpty(head)) { // 如果排序链表为空 + return 0; // 返回0,表示没有过期时间 } - SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode); - return OsSortLinkGetTargetExpireTime(listSorted); + SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode); // 获取排序链表中的第一个节点 + return OsSortLinkGetTargetExpireTime(listSorted); // 获取目标排序链表节点的过期时间 } diff --git a/sched/sched_sq/调度器.docx b/sched/sched_sq/调度器.docx new file mode 100644 index 0000000..b1a030e Binary files /dev/null and b/sched/sched_sq/调度器.docx differ diff --git a/实验步骤.docx b/实验步骤.docx new file mode 100644 index 0000000..5c50625 Binary files /dev/null and b/实验步骤.docx differ diff --git a/用例描述.docx b/用例描述.docx new file mode 100644 index 0000000..bb0a563 Binary files /dev/null and b/用例描述.docx differ