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