本帖最后由 l_xy 于 2020-10-18 17:26 编辑
目录 OsTaskScan()
时钟管理模块很简单,但却有内核最重要的代码段 Os tickHandler(),这是干嘛的,可以理解为 JAVA的定时任务,但这是系统内核的定时器。因鸿蒙目前开放的是 轻量级的内核 lite os (LOS),所以tick的频率不会太高 对应张大爷的故事:很简单就是场馆的那个大钟,每10分响一次,一次就是一个Tick(节拍)
多久Tick一次?看代码
- /**
- * @ingroup los_config
- * Number of Ticks in one second
- */
- #ifndef LOSCFG_BASE_CORE_TICK_PER_SECOND
- #define LOSCFG_BASE_CORE_TICK_PER_SECOND 100 //*kfy 默认每秒100次触发,当然这是可以改的
- #endif
复制代码
每秒100 tick ,即每秒100次调用时钟中断处理程序, 时间片单位为10ms 一次任务分配多少时间给进程执行呢?答案是 2个时间片,即 20ms 对应张大爷的故事:节目喊到后这次进来的总表演时间,10分钟一个时间片,共2片,表演20分钟。
- /**
- * @ingroup los_config
- * Longest execution time of tasks with the same priorities
- */
- #ifndef LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT
- #define LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT 2
- #endif
-
- /**
- * @ingroup los_process
- * Hold the time slice process
- */
- #define OS_PROCESS_SCHED_RR_INTERVAL LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT
复制代码
用完需要可以再分配,但一次就是只给2个时间片,怕你一直占着茅坑,后面还有人在等的.详细代码: OsSchedResched(VOID)
- VOID OsSchedResched(VOID)
- {
- LosTaskCB *runTask = NULL;
- LosTaskCB *newTask = NULL;
- LosProcessCB *runProcess = NULL;
- LosProcessCB *newProcess = NULL;
-
- LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
-
- if (!OsPreemptableInSched()) {
- return;
- }
-
- runTask = OsCurrTaskGet();
- newTask = OsGetTopTask();
-
- /* always be able to get one task */
- LOS_ASSERT(newTask != NULL);
-
- if (runTask == newTask) {
- return;
- }
-
- runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING;
- newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
-
- runProcess = OS_PCB_FROM_PID(runTask->processID);
- newProcess = OS_PCB_FROM_PID(newTask->processID);
-
- OsSchedSwitchProcess(runProcess, newProcess);
-
- #if (LOSCFG_KERNEL_SMP == YES)
- /* mask new running task's owner processor */
- runTask->currCpu = OS_TASK_INVALID_CPUID;
- newTask->currCpu = ArchCurrCpuid();
- #endif
-
- (VOID)OsTaskSwitchCheck(runTask, newTask);
-
- #if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
- OsSchedStatistics(runTask, newTask);
- #endif
-
- if ((newTask->timeSlice == 0) && (newTask->policy == LOS_SCHED_RR)) {
- newTask->timeSlice = LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT; //只给两个时间片
- }
-
- OsCurrTaskSet((VOID*)newTask);
-
- if (OsProcessIsUserMode(newProcess)) {
- OsCurrUserTaskSet(newTask->userArea);
- }
-
- PRINT_TRACE("cpu%d run process name: (%s) pid: %d status: %x threadMap: %x task name: (%s) tid: %d status: %x ->n"
- " new process name: (%s) pid: %d status: %x threadMap: %x task name: (%s) tid: %d status: %x!n",
- ArchCurrCpuid(),
- runProcess->processName, runProcess->processID, runProcess->processStatus,
- runProcess->threadScheduleMap, runTask->taskName, runTask->taskID, runTask->taskStatus,
- newProcess->processName, newProcess->processID, newProcess->processStatus,
- newProcess->threadScheduleMap, newTask->taskName, newTask->taskID, newTask->taskStatus);
-
- /* do the task context switch */
- OsTaskSchedule(newTask, runTask);
- }
复制代码
在哪里设置tick的回调函数?从main中可以看到tick 的初始化和中断服务程序的注册
- // 由 main 函数调用,注册中断处理函数 OsTickEntry
- VOID HalClockInit(VOID)
- {
- UINT32 ret;
-
- ret = LOS_HwiCreate(PRVTIMER_INT_NUM, 0xa0, 0, OsTickEntry, NULL);
- if (ret != LOS_OK) {
- PRINT_ERR("%s, %d create tick irq failed, ret:0x%xn", __FUNCTION__, __LINE__, ret);
- }
- }
复制代码
OsTickHandler 是tick 的中断处理程序,其中完成了时间片的检查和任务的扫描。
- /*
- * Description : Tick interruption handler
- */
- LITE_OS_SEC_TEXT VOID OsTickHandler(VOID)
- {
- UINT32 intSave;
-
- TICK_LOCK(intSave);
- g_tickCount[ArchCurrCpuid()]++;
- TICK_UNLOCK(intSave);
-
- #ifdef LOSCFG_KERNEL_VDSO
- OsUpdateVdsoTimeval();
- #endif
-
- #ifdef LOSCFG_KERNEL_TICKLESS
- OsTickIrqFlagSet(OsTicklessFlagGet());
- #endif
-
- #if (LOSCFG_BASE_CORE_TICK_HW_TIME == YES)
- HalClockIrqClear(); /* diff from every platform */
- #endif
-
- OsTimesliceCheck();
-
- OsTaskScan(); /* task timeout scan */
-
- #if (LOSCFG_BASE_CORE_SWTMR == YES)
- OsSwtmrScan();
- #endif
- }
- LITE_OS_SEC_TEXT VOID OsTimesliceCheck(VOID)
- {
- LosTaskCB *runTask = NULL;
- LosProcessCB *runProcess = OsCurrProcessGet();
- if (runProcess->policy != LOS_SCHED_RR) {
- goto SCHED_TASK;
- }
-
- if (runProcess->timeSlice != 0) {
- runProcess->timeSlice--;//进程时间片减少一次
- if (runProcess->timeSlice == 0) {
- LOS_Schedule();//进程时间片用完,发起调度
- }
- }
-
- SCHED_TASK:
- runTask = OsCurrTaskGet();
- if (runTask->policy != LOS_SCHED_RR) {
- return;
- }
-
- if (runTask->timeSlice != 0) {
- runTask->timeSlice--;//对应任务时间片也减少一次
- if (runTask->timeSlice == 0) {
- LOS_Schedule();
- }
- }
- }
复制代码
OsTaskScan() OsTaskScan()不断查task的状态,有任务就去执行,毫不夸张的可以说是 进程有序执行的源动力之所在!
- LITE_OS_SEC_TEXT VOID OsTaskScan(VOID)
- {
- SortLinkList *sortList = NULL;
- LosTaskCB *taskCB = NULL;
- BOOL needSchedule = FALSE;
- UINT16 tempStatus;
- LOS_DL_LIST *listObject = NULL;
- SortLinkAttribute *taskSortLink = NULL;
-
- taskSortLink = &OsPercpuGet()->taskSortLink;
- taskSortLink->cursor = (taskSortLink->cursor + 1) & OS_TSK_SORTLINK_MASK;
- listObject = taskSortLink->sortLink + taskSortLink->cursor;
-
- /*
- * 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.
- *
- * 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(&g_taskSpin);
-
- if (LOS_ListEmpty(listObject)) {
- LOS_SpinUnlock(&g_taskSpin);
- return;
- }
- sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
- ROLLNUM_DEC(sortList->idxRollNum);
-
- while (ROLLNUM(sortList->idxRollNum) == 0) {
- LOS_ListDelete(&sortList->sortLinkNode);
- taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList);
- taskCB->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
- tempStatus = taskCB->taskStatus;
- if (tempStatus & OS_TASK_STATUS_PEND) {
- taskCB->taskStatus &= ~OS_TASK_STATUS_PEND;
- #if (LOSCFG_KERNEL_LITEIPC == YES)
- taskCB->ipcStatus &= ~IPC_THREAD_STATUS_PEND;
- #endif
- taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
- LOS_ListDelete(&taskCB->pendList);
- taskCB->taskSem = NULL;
- taskCB->taskMux = NULL;
- } else {
- taskCB->taskStatus &= ~OS_TASK_STATUS_DELAY;
- }
-
- if (!(tempStatus & OS_TASK_STATUS_SUSPEND)) {
- OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, OS_PROCESS_STATUS_PEND);
- needSchedule = TRUE;
- }
-
- if (LOS_ListEmpty(listObject)) {
- break;
- }
-
- sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
- }
-
- LOS_SpinUnlock(&g_taskSpin);
-
- if (needSchedule != FALSE) {
- LOS_MpSchedule(OS_MP_CPU_ALL);
- LOS_Schedule();
- }
- }
复制代码
0
|
|
|
|