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
42 #ifdef __cplusplus
43 #if __cplusplus
44 extern "C" {
45 #endif /* __cplusplus */
46 #endif /* __cplusplus */
47
48 #define OS_PRIORITY_QUEUE_NUM 32
49 #define PRIQUEUE_PRIOR0_BIT 0x80000000U
50 #define OS_SCHED_TIME_SLICES ((LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE)
51 #define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */
52 #define OS_TICK_RESPONSE_TIME_MAX LOSCFG_BASE_CORE_TICK_RESPONSE_MAX
53 #define OS_TICK_RESPONSE_PRECISION (UINT32)((OS_SCHED_MINI_PERIOD * 75) / 100)
54 #if (LOSCFG_BASE_CORE_TICK_RESPONSE_MAX == 0)
55 #error "Must specify the maximum value that tick timer counter supports!"
56 #endif
57
58 #define OS_TASK_BLOCKED_STATUS (OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND | \
59 OS_TASK_STATUS_EXIT | OS_TASK_STATUS_UNUSED)
60
61 STATIC SchedScan g_swtmrScan = NULL;
62 STATIC SortLinkAttribute *g_taskSortLinkList = NULL;
63 STATIC LOS_DL_LIST g_priQueueList[OS_PRIORITY_QUEUE_NUM];
64 STATIC UINT32 g_queueBitmap;
65
66 STATIC UINT32 g_schedResponseID = 0;
67 STATIC UINT16 g_tickIntLock = 0;
68 STATIC UINT64 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
69
OsSchedResetSchedResponseTime(UINT64 responseTime)70 VOID OsSchedResetSchedResponseTime(UINT64 responseTime)
71 {
72 if (responseTime <= g_schedResponseTime) {
73 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
74 }
75 }
76
OsTimeSliceUpdate(LosTaskCB * taskCB,UINT64 currTime)77 STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime)
78 {
79 LOS_ASSERT(currTime >= taskCB->startTime);
80
81 INT32 incTime = currTime - taskCB->startTime;
82 if (taskCB->taskID != g_idleTaskID) {
83 taskCB->timeSlice -= incTime;
84 }
85 taskCB->startTime = currTime;
86 }
87
OsSchedSetNextExpireTime(UINT32 responseID,UINT64 taskEndTime)88 STATIC INLINE VOID OsSchedSetNextExpireTime(UINT32 responseID, UINT64 taskEndTime)
89 {
90 UINT64 nextResponseTime;
91 BOOL isTimeSlice = FALSE;
92
93 UINT64 currTime = OsGetCurrSchedTimeCycle();
94 UINT64 nextExpireTime = OsGetNextExpireTime(currTime, OS_TICK_RESPONSE_PRECISION);
95 /* The response time of the task time slice is aligned to the next response time in the delay queue */
96 if ((nextExpireTime > taskEndTime) && ((nextExpireTime - taskEndTime) > OS_SCHED_MINI_PERIOD)) {
97 nextExpireTime = taskEndTime;
98 isTimeSlice = TRUE;
99 }
100
101 if ((g_schedResponseTime <= nextExpireTime) ||
102 ((g_schedResponseTime - nextExpireTime) < OS_TICK_RESPONSE_PRECISION)) {
103 return;
104 }
105
106 if (isTimeSlice) {
107 /* The expiration time of the current system is the thread's slice expiration time */
108 g_schedResponseID = responseID;
109 } else {
110 g_schedResponseID = OS_INVALID;
111 }
112
113 nextResponseTime = nextExpireTime - currTime;
114 if (nextResponseTime < OS_TICK_RESPONSE_PRECISION) {
115 nextResponseTime = OS_TICK_RESPONSE_PRECISION;
116 }
117 g_schedResponseTime = currTime + OsTickTimerReload(nextResponseTime);
118 }
119
OsSchedUpdateExpireTime(VOID)120 VOID OsSchedUpdateExpireTime(VOID)
121 {
122 UINT64 endTime;
123 BOOL isPmMode = FALSE;
124 LosTaskCB *runTask = g_losTask.runTask;
125
126 if (!g_taskScheduled || g_tickIntLock) {
127 return;
128 }
129
130 #if (LOSCFG_KERNEL_PM == 1)
131 isPmMode = OsIsPmMode();
132 #endif
133 if ((runTask->taskID != g_idleTaskID) && !isPmMode) {
134 INT32 timeSlice = (runTask->timeSlice <= OS_TIME_SLICE_MIN) ? (INT32)OS_SCHED_TIME_SLICES : runTask->timeSlice;
135 endTime = runTask->startTime + timeSlice;
136 } else {
137 endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION;
138 }
139 OsSchedSetNextExpireTime(runTask->taskID, endTime);
140 }
141
OsSchedPriQueueEnHead(LOS_DL_LIST * priqueueItem,UINT32 priority)142 STATIC INLINE VOID OsSchedPriQueueEnHead(LOS_DL_LIST *priqueueItem, UINT32 priority)
143 {
144 /*
145 * Task control blocks are inited as zero. And when task is deleted,
146 * and at the same time would be deleted from priority queue or
147 * other lists, task pend node will restored as zero.
148 */
149 if (LOS_ListEmpty(&g_priQueueList[priority])) {
150 g_queueBitmap |= PRIQUEUE_PRIOR0_BIT >> priority;
151 }
152
153 LOS_ListAdd(&g_priQueueList[priority], priqueueItem);
154 }
155
OsSchedPriQueueEnTail(LOS_DL_LIST * priqueueItem,UINT32 priority)156 STATIC INLINE VOID OsSchedPriQueueEnTail(LOS_DL_LIST *priqueueItem, UINT32 priority)
157 {
158 if (LOS_ListEmpty(&g_priQueueList[priority])) {
159 g_queueBitmap |= PRIQUEUE_PRIOR0_BIT >> priority;
160 }
161
162 LOS_ListTailInsert(&g_priQueueList[priority], priqueueItem);
163 }
164
OsSchedPriQueueDelete(LOS_DL_LIST * priqueueItem,UINT32 priority)165 STATIC INLINE VOID OsSchedPriQueueDelete(LOS_DL_LIST *priqueueItem, UINT32 priority)
166 {
167 LOS_ListDelete(priqueueItem);
168 if (LOS_ListEmpty(&g_priQueueList[priority])) {
169 g_queueBitmap &= ~(PRIQUEUE_PRIOR0_BIT >> priority);
170 }
171 }
172
OsSchedWakePendTimeTask(LosTaskCB * taskCB,BOOL * needSchedule)173 STATIC INLINE VOID OsSchedWakePendTimeTask(LosTaskCB *taskCB, BOOL *needSchedule)
174 {
175 UINT16 tempStatus = taskCB->taskStatus;
176 if (tempStatus & (OS_TASK_STATUS_PEND | OS_TASK_STATUS_DELAY)) {
177 taskCB->taskStatus &= ~(OS_TASK_STATUS_PEND | OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY);
178 if (tempStatus & OS_TASK_STATUS_PEND) {
179 taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
180 LOS_ListDelete(&taskCB->pendList);
181 taskCB->taskMux = NULL;
182 taskCB->taskSem = NULL;
183 }
184
185 if (!(tempStatus & OS_TASK_STATUS_SUSPEND)) {
186 OsSchedTaskEnQueue(taskCB);
187 *needSchedule = TRUE;
188 }
189 }
190 }
191
OsSchedScanTimerList(VOID)192 STATIC INLINE BOOL OsSchedScanTimerList(VOID)
193 {
194 BOOL needSchedule = FALSE;
195 LOS_DL_LIST *listObject = &g_taskSortLinkList->sortLink;
196 /*
197 * When task is pended with timeout, the task block is on the timeout sortlink
198 * (per cpu) and ipc(mutex,sem and etc.)'s block at the same time, it can be waken
199 * up by either timeout or corresponding ipc it's waiting.
200 *
201 * Now synchronize sortlink procedure is used, therefore the whole task scan needs
202 * to be protected, preventing another core from doing sortlink deletion at same time.
203 */
204
205 if (LOS_ListEmpty(listObject)) {
206 return needSchedule;
207 }
208
209 SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
210 UINT64 currTime = OsGetCurrSchedTimeCycle();
211 while (sortList->responseTime <= currTime) {
212 LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList);
213 OsDeleteNodeSortLink(&taskCB->sortList);
214 OsSchedWakePendTimeTask(taskCB, &needSchedule);
215 if (LOS_ListEmpty(listObject)) {
216 break;
217 }
218
219 sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
220 }
221
222 return needSchedule;
223 }
224
OsSchedTaskEnQueue(LosTaskCB * taskCB)225 VOID OsSchedTaskEnQueue(LosTaskCB *taskCB)
226 {
227 LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY));
228
229 if (taskCB->taskID != g_idleTaskID) {
230 if (taskCB->timeSlice > OS_TIME_SLICE_MIN) {
231 OsSchedPriQueueEnHead(&taskCB->pendList, taskCB->priority);
232 } else {
233 taskCB->timeSlice = OS_SCHED_TIME_SLICES;
234 OsSchedPriQueueEnTail(&taskCB->pendList, taskCB->priority);
235 }
236 OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOREADYSTATE, taskCB);
237 }
238
239 taskCB->taskStatus &= ~(OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND |
240 OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME);
241
242 taskCB->taskStatus |= OS_TASK_STATUS_READY;
243 }
244
OsSchedTaskDeQueue(LosTaskCB * taskCB)245 VOID OsSchedTaskDeQueue(LosTaskCB *taskCB)
246 {
247 if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
248 if (taskCB->taskID != g_idleTaskID) {
249 OsSchedPriQueueDelete(&taskCB->pendList, taskCB->priority);
250 }
251
252 taskCB->taskStatus &= ~OS_TASK_STATUS_READY;
253 }
254 }
255
OsSchedTaskExit(LosTaskCB * taskCB)256 VOID OsSchedTaskExit(LosTaskCB *taskCB)
257 {
258 if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
259 OsSchedTaskDeQueue(taskCB);
260 } else if (taskCB->taskStatus & OS_TASK_STATUS_PEND) {
261 LOS_ListDelete(&taskCB->pendList);
262 taskCB->taskStatus &= ~OS_TASK_STATUS_PEND;
263 }
264
265 if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) {
266 OsDeleteSortLink(&taskCB->sortList);
267 taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME);
268 }
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, OS_TICK_RESPONSE_PRECISION);
421 }
422
OsSchedInit(VOID)423 UINT32 OsSchedInit(VOID)
424 {
425 UINT16 pri;
426 for (pri = 0; pri < OS_PRIORITY_QUEUE_NUM; pri++) {
427 LOS_ListInit(&g_priQueueList[pri]);
428 }
429 g_queueBitmap = 0;
430
431 g_taskSortLinkList = OsGetSortLinkAttribute(OS_SORT_LINK_TASK);
432 if (g_taskSortLinkList == NULL) {
433 return LOS_NOK;
434 }
435
436 OsSortLinkInit(g_taskSortLinkList);
437 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
438
439 return LOS_OK;
440 }
441
OsGetTopTask(VOID)442 LosTaskCB *OsGetTopTask(VOID)
443 {
444 UINT32 priority;
445 LosTaskCB *newTask = NULL;
446 if (g_queueBitmap) {
447 priority = CLZ(g_queueBitmap);
448 newTask = LOS_DL_LIST_ENTRY(((LOS_DL_LIST *)&g_priQueueList[priority])->pstNext, LosTaskCB, pendList);
449 } else {
450 newTask = OS_TCB_FROM_TID(g_idleTaskID);
451 }
452
453 return newTask;
454 }
455
OsSchedStart(VOID)456 VOID OsSchedStart(VOID)
457 {
458 PRINTK("Entering scheduler\n");
459
460 (VOID)LOS_IntLock();
461 LosTaskCB *newTask = OsGetTopTask();
462
463 newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
464 g_losTask.newTask = newTask;
465 g_losTask.runTask = g_losTask.newTask;
466
467 newTask->startTime = OsGetCurrSchedTimeCycle();
468 OsSchedTaskDeQueue(newTask);
469
470 OsTickSysTimerStartTimeSet(newTask->startTime);
471
472 OsSwtmrResponseTimeReset(newTask->startTime);
473
474 /* Initialize the schedule timeline and enable scheduling */
475 g_taskScheduled = TRUE;
476
477 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
478 g_schedResponseID = OS_INVALID;
479 OsSchedSetNextExpireTime(newTask->taskID, newTask->startTime + newTask->timeSlice);
480 }
481
OsSchedTaskSwitch(VOID)482 BOOL OsSchedTaskSwitch(VOID)
483 {
484 UINT64 endTime;
485 BOOL isTaskSwitch = FALSE;
486 LosTaskCB *runTask = g_losTask.runTask;
487 OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle());
488
489 if (runTask->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) {
490 OsAdd2SortLink(&runTask->sortList, runTask->startTime, runTask->waitTimes, OS_SORT_LINK_TASK);
491 } else if (!(runTask->taskStatus & OS_TASK_BLOCKED_STATUS)) {
492 OsSchedTaskEnQueue(runTask);
493 }
494
495 LosTaskCB *newTask = OsGetTopTask();
496 g_losTask.newTask = newTask;
497
498 if (runTask != newTask) {
499 #if (LOSCFG_BASE_CORE_TSK_MONITOR == 1)
500 OsTaskSwitchCheck();
501 #endif
502 runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING;
503 newTask->taskStatus |= OS_TASK_STATUS_RUNNING;
504 newTask->startTime = runTask->startTime;
505 isTaskSwitch = TRUE;
506
507 OsHookCall(LOS_HOOK_TYPE_TASK_SWITCHEDIN);
508 }
509
510 OsSchedTaskDeQueue(newTask);
511
512 if (newTask->taskID != g_idleTaskID) {
513 endTime = newTask->startTime + newTask->timeSlice;
514 } else {
515 endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION;
516 }
517
518 if (g_schedResponseID == runTask->taskID) {
519 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
520 }
521 OsSchedSetNextExpireTime(newTask->taskID, endTime);
522
523 return isTaskSwitch;
524 }
525
LOS_SchedTickTimeoutNsGet(VOID)526 UINT64 LOS_SchedTickTimeoutNsGet(VOID)
527 {
528 UINT32 intSave;
529 UINT64 responseTime;
530 UINT64 currTime;
531
532 intSave = LOS_IntLock();
533 responseTime = g_schedResponseTime;
534 currTime = OsGetCurrSchedTimeCycle();
535 LOS_IntRestore(intSave);
536
537 if (responseTime > currTime) {
538 responseTime = responseTime - currTime;
539 } else {
540 responseTime = 0; /* Tick interrupt already timeout */
541 }
542
543 return OS_SYS_CYCLE_TO_NS(responseTime, g_sysClock);
544 }
545
LOS_SchedTickHandler(VOID)546 VOID LOS_SchedTickHandler(VOID)
547 {
548 if (!g_taskScheduled) {
549 return;
550 }
551
552 UINT32 intSave = LOS_IntLock();
553 UINT64 tickStartTime = OsGetCurrSchedTimeCycle();
554 if (g_schedResponseID == OS_INVALID) {
555 g_tickIntLock++;
556 if (g_swtmrScan != NULL) {
557 (VOID)g_swtmrScan();
558 }
559
560 (VOID)OsSchedScanTimerList();
561 g_tickIntLock--;
562 }
563
564 OsTimeSliceUpdate(g_losTask.runTask, tickStartTime);
565 g_losTask.runTask->startTime = OsGetCurrSchedTimeCycle();
566
567 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME;
568 if (LOS_CHECK_SCHEDULE) {
569 ArchTaskSchedule();
570 } else {
571 OsSchedUpdateExpireTime();
572 }
573
574 LOS_IntRestore(intSave);
575 }
576
LOS_Schedule(VOID)577 VOID LOS_Schedule(VOID)
578 {
579 if (g_taskScheduled && LOS_CHECK_SCHEDULE) {
580 ArchTaskSchedule();
581 }
582 }
583
584 #ifdef __cplusplus
585 #if __cplusplus
586 }
587 #endif /* __cplusplus */
588 #endif /* __cplusplus */
589