• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_sched.h"
33 #include "los_task.h"
34 #include "los_tick.h"
35 #include "los_swtmr.h"
36 #include "los_debug.h"
37 #include "los_hook.h"
38 #if (LOSCFG_KERNEL_PM == 1)
39 #include "los_pm.h"
40 #endif
41 #if (LOSCFG_DEBUG_TOOLS == 1)
42 #include "los_debugtools.h"
43 #endif
44 
45 #define OS_PRIORITY_QUEUE_NUM      32
46 #define PRIQUEUE_PRIOR0_BIT        0x80000000U
47 #define OS_TICK_RESPONSE_TIME_MAX  LOSCFG_BASE_CORE_TICK_RESPONSE_MAX
48 #if (LOSCFG_BASE_CORE_TICK_RESPONSE_MAX == 0)
49 #error "Must specify the maximum value that tick timer counter supports!"
50 #endif
51 
52 #define OS_TASK_BLOCKED_STATUS (OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND | \
53                                 OS_TASK_STATUS_EXIT | OS_TASK_STATUS_UNUSED)
54 
55 STATIC SchedScan  g_swtmrScan = NULL;
56 STATIC SortLinkAttribute *g_taskSortLinkList = NULL;
57 STATIC LOS_DL_LIST g_priQueueList[OS_PRIORITY_QUEUE_NUM];
58 STATIC UINT32 g_queueBitmap;
59 
60 STATIC UINT32 g_schedResponseID = 0;
61 STATIC UINT16 g_tickIntLock = 0;
62 STATIC UINT64 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
63 
64 STATIC INT32 g_schedTimeSlice;
65 STATIC INT32 g_schedTimeSliceMin;
66 STATIC UINT32 g_schedTickMinPeriod;
67 STATIC UINT32 g_tickResponsePrecision;
68 
OsSchedResetSchedResponseTime(UINT64 responseTime)69 VOID OsSchedResetSchedResponseTime(UINT64 responseTime)
70 {
71     if (responseTime <= g_schedResponseTime) {
72         g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
73     }
74 }
75 
OsTimeSliceUpdate(LosTaskCB * taskCB,UINT64 currTime)76 STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime)
77 {
78     LOS_ASSERT(currTime >= taskCB->startTime);
79 
80     INT32 incTime = currTime - taskCB->startTime;
81     if (taskCB->taskID != g_idleTaskID) {
82         taskCB->timeSlice -= incTime;
83     }
84     taskCB->startTime = currTime;
85 }
86 
OsSchedSetNextExpireTime(UINT32 responseID,UINT64 taskEndTime)87 STATIC INLINE VOID OsSchedSetNextExpireTime(UINT32 responseID, UINT64 taskEndTime)
88 {
89     UINT64 nextResponseTime;
90     BOOL isTimeSlice = FALSE;
91 
92     UINT64 currTime = OsGetCurrSchedTimeCycle();
93     UINT64 nextExpireTime = OsGetNextExpireTime(currTime, g_tickResponsePrecision);
94     /* The response time of the task time slice is aligned to the next response time in the delay queue */
95     if ((nextExpireTime > taskEndTime) && ((nextExpireTime - taskEndTime) > g_schedTickMinPeriod)) {
96         nextExpireTime = taskEndTime;
97         isTimeSlice = TRUE;
98     }
99 
100     if ((g_schedResponseTime <= nextExpireTime) ||
101         ((g_schedResponseTime - nextExpireTime) < g_tickResponsePrecision)) {
102         return;
103     }
104 
105     if (isTimeSlice) {
106         /* The expiration time of the current system is the thread's slice expiration time */
107         g_schedResponseID = responseID;
108     } else {
109         g_schedResponseID = OS_INVALID;
110     }
111 
112     nextResponseTime = nextExpireTime - currTime;
113     if (nextResponseTime < g_tickResponsePrecision) {
114         nextResponseTime = g_tickResponsePrecision;
115     }
116     g_schedResponseTime = currTime + OsTickTimerReload(nextResponseTime);
117 }
118 
OsSchedUpdateExpireTime(VOID)119 VOID OsSchedUpdateExpireTime(VOID)
120 {
121     UINT64 endTime;
122     BOOL isPmMode = FALSE;
123     LosTaskCB *runTask = g_losTask.runTask;
124 
125     if (!g_taskScheduled || g_tickIntLock) {
126         return;
127     }
128 
129 #if (LOSCFG_KERNEL_PM == 1)
130     isPmMode = OsIsPmMode();
131 #endif
132     if ((runTask->taskID != g_idleTaskID) && !isPmMode) {
133         INT32 timeSlice = (runTask->timeSlice <= g_schedTimeSliceMin) ? g_schedTimeSlice : runTask->timeSlice;
134         endTime = runTask->startTime + timeSlice;
135     } else {
136         endTime = OS_SCHED_MAX_RESPONSE_TIME - g_tickResponsePrecision;
137     }
138     OsSchedSetNextExpireTime(runTask->taskID, endTime);
139 }
140 
OsSchedPriQueueEnHead(LOS_DL_LIST * priqueueItem,UINT32 priority)141 STATIC INLINE VOID OsSchedPriQueueEnHead(LOS_DL_LIST *priqueueItem, UINT32 priority)
142 {
143     /*
144      * Task control blocks are inited as zero. And when task is deleted,
145      * and at the same time would be deleted from priority queue or
146      * other lists, task pend node will restored as zero.
147      */
148     if (LOS_ListEmpty(&g_priQueueList[priority])) {
149         g_queueBitmap |= PRIQUEUE_PRIOR0_BIT >> priority;
150     }
151 
152     LOS_ListAdd(&g_priQueueList[priority], priqueueItem);
153 }
154 
OsSchedPriQueueEnTail(LOS_DL_LIST * priqueueItem,UINT32 priority)155 STATIC INLINE VOID OsSchedPriQueueEnTail(LOS_DL_LIST *priqueueItem, UINT32 priority)
156 {
157     if (LOS_ListEmpty(&g_priQueueList[priority])) {
158         g_queueBitmap |= PRIQUEUE_PRIOR0_BIT >> priority;
159     }
160 
161     LOS_ListTailInsert(&g_priQueueList[priority], priqueueItem);
162 }
163 
OsSchedPriQueueDelete(LOS_DL_LIST * priqueueItem,UINT32 priority)164 STATIC INLINE VOID OsSchedPriQueueDelete(LOS_DL_LIST *priqueueItem, UINT32 priority)
165 {
166     LOS_ListDelete(priqueueItem);
167     if (LOS_ListEmpty(&g_priQueueList[priority])) {
168         g_queueBitmap &= ~(PRIQUEUE_PRIOR0_BIT >> priority);
169     }
170 }
171 
OsSchedWakePendTimeTask(LosTaskCB * taskCB,BOOL * needSchedule)172 STATIC INLINE VOID OsSchedWakePendTimeTask(LosTaskCB *taskCB, BOOL *needSchedule)
173 {
174     UINT16 tempStatus = taskCB->taskStatus;
175     if (tempStatus & (OS_TASK_STATUS_PEND | OS_TASK_STATUS_DELAY)) {
176         taskCB->taskStatus &= ~(OS_TASK_STATUS_PEND | OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY);
177         if (tempStatus & OS_TASK_STATUS_PEND) {
178             taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
179             LOS_ListDelete(&taskCB->pendList);
180             taskCB->taskMux = NULL;
181             taskCB->taskSem = NULL;
182         }
183 
184         if (!(tempStatus & OS_TASK_STATUS_SUSPEND)) {
185             OsSchedTaskEnQueue(taskCB);
186             *needSchedule = TRUE;
187         }
188     }
189 }
190 
OsSchedScanTimerList(VOID)191 STATIC INLINE BOOL OsSchedScanTimerList(VOID)
192 {
193     BOOL needSchedule = FALSE;
194     LOS_DL_LIST *listObject = &g_taskSortLinkList->sortLink;
195     /*
196      * When task is pended with timeout, the task block is on the timeout sortlink
197      * (per cpu) and ipc(mutex,sem and etc.)'s block at the same time, it can be waken
198      * up by either timeout or corresponding ipc it's waiting.
199      *
200      * Now synchronize sortlink procedure is used, therefore the whole task scan needs
201      * to be protected, preventing another core from doing sortlink deletion at same time.
202      */
203 
204     if (LOS_ListEmpty(listObject)) {
205         return needSchedule;
206     }
207 
208     SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
209     UINT64 currTime = OsGetCurrSchedTimeCycle();
210     while (sortList->responseTime <= currTime) {
211         LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList);
212         OsDeleteNodeSortLink(&taskCB->sortList);
213         OsSchedWakePendTimeTask(taskCB, &needSchedule);
214         if (LOS_ListEmpty(listObject)) {
215             break;
216         }
217 
218         sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
219     }
220 
221     return needSchedule;
222 }
223 
OsSchedTaskEnQueue(LosTaskCB * taskCB)224 VOID OsSchedTaskEnQueue(LosTaskCB *taskCB)
225 {
226     LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY));
227 
228     if (taskCB->taskID != g_idleTaskID) {
229         if (taskCB->timeSlice > g_schedTimeSliceMin) {
230             OsSchedPriQueueEnHead(&taskCB->pendList, taskCB->priority);
231         } else {
232             taskCB->timeSlice = g_schedTimeSlice;
233             OsSchedPriQueueEnTail(&taskCB->pendList, taskCB->priority);
234         }
235         OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOREADYSTATE, taskCB);
236     }
237 
238     taskCB->taskStatus &= ~(OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND |
239                             OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME);
240 
241     taskCB->taskStatus |= OS_TASK_STATUS_READY;
242 }
243 
OsSchedTaskDeQueue(LosTaskCB * taskCB)244 VOID OsSchedTaskDeQueue(LosTaskCB *taskCB)
245 {
246     if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
247         if (taskCB->taskID != g_idleTaskID) {
248             OsSchedPriQueueDelete(&taskCB->pendList, taskCB->priority);
249         }
250 
251         taskCB->taskStatus &= ~OS_TASK_STATUS_READY;
252     }
253 }
254 
OsSchedTaskExit(LosTaskCB * taskCB)255 VOID OsSchedTaskExit(LosTaskCB *taskCB)
256 {
257     if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
258         OsSchedTaskDeQueue(taskCB);
259     } else if (taskCB->taskStatus & OS_TASK_STATUS_PEND) {
260         LOS_ListDelete(&taskCB->pendList);
261         taskCB->taskStatus &= ~OS_TASK_STATUS_PEND;
262     }
263 
264     if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) {
265         OsDeleteSortLink(&taskCB->sortList);
266         taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME);
267     }
268     taskCB->taskStatus |= OS_TASK_STATUS_EXIT;
269 }
270 
OsSchedYield(VOID)271 VOID OsSchedYield(VOID)
272 {
273     LosTaskCB *runTask = g_losTask.runTask;
274 
275     runTask->timeSlice = 0;
276 }
277 
OsSchedDelay(LosTaskCB * runTask,UINT32 tick)278 VOID OsSchedDelay(LosTaskCB *runTask, UINT32 tick)
279 {
280     runTask->taskStatus |= OS_TASK_STATUS_DELAY;
281     runTask->waitTimes = tick;
282 }
283 
OsSchedTaskWait(LOS_DL_LIST * list,UINT32 ticks)284 VOID OsSchedTaskWait(LOS_DL_LIST *list, UINT32 ticks)
285 {
286     LosTaskCB *runTask = g_losTask.runTask;
287 
288     runTask->taskStatus |= OS_TASK_STATUS_PEND;
289     LOS_ListTailInsert(list, &runTask->pendList);
290 
291     if (ticks != LOS_WAIT_FOREVER) {
292         runTask->taskStatus |= OS_TASK_STATUS_PEND_TIME;
293         runTask->waitTimes = ticks;
294     }
295 }
296 
OsSchedTaskWake(LosTaskCB * resumedTask)297 VOID OsSchedTaskWake(LosTaskCB *resumedTask)
298 {
299     LOS_ListDelete(&resumedTask->pendList);
300     resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND;
301 
302     if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) {
303         OsDeleteSortLink(&resumedTask->sortList);
304         resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
305     }
306 
307     if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPEND) &&
308         !(resumedTask->taskStatus & OS_TASK_STATUS_RUNNING)) {
309         OsSchedTaskEnQueue(resumedTask);
310     }
311 }
312 
OsSchedFreezeTask(LosTaskCB * taskCB)313 STATIC VOID OsSchedFreezeTask(LosTaskCB *taskCB)
314 {
315     UINT64 responseTime = GET_SORTLIST_VALUE(&taskCB->sortList);
316     OsDeleteSortLink(&taskCB->sortList);
317     SET_SORTLIST_VALUE(&taskCB->sortList, responseTime);
318     taskCB->taskStatus |= OS_TASK_FLAG_FREEZE;
319     return;
320 }
321 
OsSchedUnfreezeTask(LosTaskCB * taskCB)322 STATIC VOID OsSchedUnfreezeTask(LosTaskCB *taskCB)
323 {
324     UINT64 currTime, responseTime;
325     UINT32 remainTick;
326 
327     taskCB->taskStatus &= ~OS_TASK_FLAG_FREEZE;
328     currTime = OsGetCurrSchedTimeCycle();
329     responseTime = GET_SORTLIST_VALUE(&taskCB->sortList);
330     if (responseTime > currTime) {
331         remainTick = ((responseTime - currTime) + OS_CYCLE_PER_TICK - 1) / OS_CYCLE_PER_TICK;
332         OsAdd2SortLink(&taskCB->sortList, currTime, remainTick, OS_SORT_LINK_TASK);
333         return;
334     }
335 
336     SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME);
337     if (taskCB->taskStatus & OS_TASK_STATUS_PEND) {
338         LOS_ListDelete(&taskCB->pendList);
339     }
340     taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_PEND);
341     return;
342 }
343 
OsSchedSuspend(LosTaskCB * taskCB)344 VOID OsSchedSuspend(LosTaskCB *taskCB)
345 {
346     BOOL isPmMode = FALSE;
347     if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
348         OsSchedTaskDeQueue(taskCB);
349     }
350 
351 #if (LOSCFG_KERNEL_PM == 1)
352     isPmMode = OsIsPmMode();
353 #endif
354     if ((taskCB->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) && isPmMode) {
355         OsSchedFreezeTask(taskCB);
356     }
357 
358     taskCB->taskStatus |= OS_TASK_STATUS_SUSPEND;
359     OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB);
360 }
361 
OsSchedResume(LosTaskCB * taskCB)362 BOOL OsSchedResume(LosTaskCB *taskCB)
363 {
364     if (taskCB->taskStatus & OS_TASK_FLAG_FREEZE) {
365         OsSchedUnfreezeTask(taskCB);
366     }
367 
368     taskCB->taskStatus &= (~OS_TASK_STATUS_SUSPEND);
369     if (!(taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND))) {
370         OsSchedTaskEnQueue(taskCB);
371         return TRUE;
372     }
373 
374     return FALSE;
375 }
376 
OsSchedModifyTaskSchedParam(LosTaskCB * taskCB,UINT16 priority)377 BOOL OsSchedModifyTaskSchedParam(LosTaskCB *taskCB, UINT16 priority)
378 {
379     if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
380         OsSchedTaskDeQueue(taskCB);
381         taskCB->priority = priority;
382         OsSchedTaskEnQueue(taskCB);
383         return TRUE;
384     }
385 
386     taskCB->priority = priority;
387     OsHookCall(LOS_HOOK_TYPE_TASK_PRIMODIFY, taskCB, taskCB->priority);
388     if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
389         return TRUE;
390     }
391 
392     return FALSE;
393 }
394 
OsSchedSetIdleTaskSchedParam(LosTaskCB * idleTask)395 VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask)
396 {
397     OsSchedTaskEnQueue(idleTask);
398 }
399 
OsSchedSwtmrScanRegister(SchedScan func)400 UINT32 OsSchedSwtmrScanRegister(SchedScan func)
401 {
402     if (func == NULL) {
403         return LOS_NOK;
404     }
405 
406     g_swtmrScan = func;
407     return LOS_OK;
408 }
409 
OsTaskNextSwitchTimeGet(VOID)410 UINT32 OsTaskNextSwitchTimeGet(VOID)
411 {
412     UINT32 intSave = LOS_IntLock();
413     UINT32 ticks = OsSortLinkGetNextExpireTime(g_taskSortLinkList);
414     LOS_IntRestore(intSave);
415     return ticks;
416 }
417 
OsSchedGetNextExpireTime(UINT64 startTime)418 UINT64 OsSchedGetNextExpireTime(UINT64 startTime)
419 {
420     return OsGetNextExpireTime(startTime, g_tickResponsePrecision);
421 }
422 
TaskSchedTimeConvertFreq(UINT32 oldFreq)423 STATIC VOID TaskSchedTimeConvertFreq(UINT32 oldFreq)
424 {
425     for (UINT32 loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
426         LosTaskCB *taskCB = (((LosTaskCB *)g_taskCBArray) + loopNum);
427         if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
428             continue;
429         }
430         if (taskCB->timeSlice > 0) {
431             taskCB->timeSlice = (INT32)OsTimeConvertFreq((UINT64)taskCB->timeSlice, oldFreq, g_sysClock);
432         } else {
433             taskCB->timeSlice = 0;
434         }
435 
436         if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
437             taskCB->startTime = OsTimeConvertFreq(taskCB->startTime, oldFreq, g_sysClock);
438         }
439     }
440 }
441 
SchedTimeBaseInit(VOID)442 STATIC VOID SchedTimeBaseInit(VOID)
443 {
444     g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
445 
446     g_schedTickMinPeriod = g_sysClock / LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI;
447     g_tickResponsePrecision =  (g_schedTickMinPeriod * 75) / 100; /* 75 / 100: minimum accuracy */
448     g_schedTimeSlice = (INT32)(((UINT64)g_sysClock * LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT) / OS_SYS_US_PER_SECOND);
449     g_schedTimeSliceMin = (INT32)(((UINT64)g_sysClock * 50) / OS_SYS_US_PER_SECOND); /* Minimum time slice 50 us */
450 }
451 
OsSchedTimeConvertFreq(UINT32 oldFreq)452 VOID OsSchedTimeConvertFreq(UINT32 oldFreq)
453 {
454     SchedTimeBaseInit();
455     TaskSchedTimeConvertFreq(oldFreq);
456     OsSortLinkResponseTimeConvertFreq(oldFreq);
457     OsSchedUpdateExpireTime();
458 }
459 
OsSchedInit(VOID)460 UINT32 OsSchedInit(VOID)
461 {
462     UINT16 pri;
463     for (pri = 0; pri < OS_PRIORITY_QUEUE_NUM; pri++) {
464         LOS_ListInit(&g_priQueueList[pri]);
465     }
466     g_queueBitmap = 0;
467 
468     g_taskSortLinkList = OsGetSortLinkAttribute(OS_SORT_LINK_TASK);
469     if (g_taskSortLinkList == NULL) {
470         return LOS_NOK;
471     }
472 
473     OsSortLinkInit(g_taskSortLinkList);
474     SchedTimeBaseInit();
475 
476     return LOS_OK;
477 }
478 
OsGetTopTask(VOID)479 LosTaskCB *OsGetTopTask(VOID)
480 {
481     UINT32 priority;
482     LosTaskCB *newTask = NULL;
483     if (g_queueBitmap) {
484         priority = CLZ(g_queueBitmap);
485         newTask = LOS_DL_LIST_ENTRY(((LOS_DL_LIST *)&g_priQueueList[priority])->pstNext, LosTaskCB, pendList);
486     } else {
487         newTask = OS_TCB_FROM_TID(g_idleTaskID);
488     }
489 
490     return newTask;
491 }
492 
OsSchedStart(VOID)493 VOID OsSchedStart(VOID)
494 {
495     PRINTK("Entering scheduler\n");
496 
497     (VOID)LOS_IntLock();
498     LosTaskCB *newTask = OsGetTopTask();
499 
500     newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
501     g_losTask.newTask = newTask;
502     g_losTask.runTask = g_losTask.newTask;
503 
504     newTask->startTime = OsGetCurrSchedTimeCycle();
505     OsSchedTaskDeQueue(newTask);
506 
507     OsTickSysTimerStartTimeSet(newTask->startTime);
508 
509 #if (LOSCFG_BASE_CORE_SWTMR == 1)
510     OsSwtmrResponseTimeReset(newTask->startTime);
511 #endif
512 
513     /* Initialize the schedule timeline and enable scheduling */
514     g_taskScheduled = TRUE;
515 
516     g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
517     g_schedResponseID = OS_INVALID;
518     OsSchedSetNextExpireTime(newTask->taskID, newTask->startTime + newTask->timeSlice);
519 }
520 
OsSchedTaskSwitch(VOID)521 BOOL OsSchedTaskSwitch(VOID)
522 {
523     UINT64 endTime;
524     BOOL isTaskSwitch = FALSE;
525     LosTaskCB *runTask = g_losTask.runTask;
526     OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle());
527 
528     if (runTask->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) {
529         OsAdd2SortLink(&runTask->sortList, runTask->startTime, runTask->waitTimes, OS_SORT_LINK_TASK);
530     } else if (!(runTask->taskStatus & OS_TASK_BLOCKED_STATUS)) {
531         OsSchedTaskEnQueue(runTask);
532     }
533 
534     LosTaskCB *newTask = OsGetTopTask();
535     g_losTask.newTask = newTask;
536 
537     if (runTask != newTask) {
538 #if (LOSCFG_BASE_CORE_TSK_MONITOR == 1)
539         OsTaskSwitchCheck();
540 #endif
541         runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING;
542         newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
543         newTask->startTime = runTask->startTime;
544         isTaskSwitch = TRUE;
545 
546         OsHookCall(LOS_HOOK_TYPE_TASK_SWITCHEDIN);
547 #if (LOSCFG_DEBUG_TOOLS == 1)
548         OsSchedTraceRecord(newTask, runTask);
549 #endif
550     }
551 
552     OsSchedTaskDeQueue(newTask);
553 
554     if (newTask->taskID != g_idleTaskID) {
555         endTime = newTask->startTime + newTask->timeSlice;
556     } else {
557         endTime = OS_SCHED_MAX_RESPONSE_TIME - g_tickResponsePrecision;
558     }
559 
560     if (g_schedResponseID == runTask->taskID) {
561         g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
562     }
563     OsSchedSetNextExpireTime(newTask->taskID, endTime);
564 
565     return isTaskSwitch;
566 }
567 
LOS_SchedTickTimeoutNsGet(VOID)568 UINT64 LOS_SchedTickTimeoutNsGet(VOID)
569 {
570     UINT32 intSave;
571     UINT64 responseTime;
572     UINT64 currTime;
573 
574     intSave = LOS_IntLock();
575     responseTime = g_schedResponseTime;
576     currTime = OsGetCurrSchedTimeCycle();
577     LOS_IntRestore(intSave);
578 
579     if (responseTime > currTime) {
580         responseTime = responseTime - currTime;
581     } else {
582         responseTime = 0; /* Tick interrupt already timeout */
583     }
584 
585     return OS_SYS_CYCLE_TO_NS(responseTime, g_sysClock);
586 }
587 
LOS_SchedTickHandler(VOID)588 VOID LOS_SchedTickHandler(VOID)
589 {
590     if (!g_taskScheduled) {
591         return;
592     }
593 
594     UINT32 intSave = LOS_IntLock();
595     UINT64 tickStartTime = OsGetCurrSchedTimeCycle();
596     if (g_schedResponseID == OS_INVALID) {
597         g_tickIntLock++;
598         if (g_swtmrScan != NULL) {
599             (VOID)g_swtmrScan();
600         }
601 
602         (VOID)OsSchedScanTimerList();
603         g_tickIntLock--;
604     }
605 
606     OsTimeSliceUpdate(g_losTask.runTask, tickStartTime);
607     g_losTask.runTask->startTime = OsGetCurrSchedTimeCycle();
608 
609     g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
610     if (LOS_CHECK_SCHEDULE) {
611         ArchTaskSchedule();
612     } else {
613         OsSchedUpdateExpireTime();
614     }
615 
616     LOS_IntRestore(intSave);
617 }
618 
LOS_Schedule(VOID)619 VOID LOS_Schedule(VOID)
620 {
621     if (OsCheckKernelRunning()) {
622         ArchTaskSchedule();
623     }
624 }
625