diff --git a/kernel/include/los_sched.h b/kernel/include/los_sched.h index e7ac66e160b3af8b87825fdc8fe4daf244a98f0d..baf0cfca711269b2f7de542030f31fb7fd19285d 100644 --- a/kernel/include/los_sched.h +++ b/kernel/include/los_sched.h @@ -42,6 +42,9 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ +#define OS_TICK_MINI_PERIOD 1 /* A tick */ +#define OS_SCHED_MINI_PERIOD (OS_SYS_CLOCK / 1000) +#define OS_TICK_RESPONSE_PRECISION ((UINT32)(((UINT64)750 * OS_SYS_CLOCK) / OS_SYS_US_PER_SECOND)) #define OS_SCHED_MAX_RESPONSE_TIME (UINT64)(((UINT64)-1) - 1U) extern UINT32 g_taskScheduled; diff --git a/kernel/include/los_sortlink.h b/kernel/include/los_sortlink.h index 2e0c5a85d6deb2c3c5133cc8ac5a27b179fb4616..17cbdcae58002b382c52dff17358be0d03c44ac4 100644 --- a/kernel/include/los_sortlink.h +++ b/kernel/include/los_sortlink.h @@ -46,6 +46,8 @@ typedef enum { OS_SORT_LINK_SWTMR = 2, } SortLinkType; +extern UINT32 g_tickMiniCount; + typedef struct { LOS_DL_LIST sortLinkNode; UINT64 responseTime; @@ -57,15 +59,26 @@ typedef struct { #define OS_SORT_LINK_INVALID_TIME ((UINT64)-1) #define SET_SORTLIST_VALUE(sortList, value) (((SortLinkList *)(sortList))->responseTime = (value)) +#define GET_SORTLIST_VALUE(sortList) (((SortLinkList *)(sortList))->responseTime) + +STATIC INLINE UINT64 OsSortLinkGetRemainTime(UINT64 currTime, const SortLinkList *targetSortList) +{ + if (currTime >= targetSortList->responseTime) { + return 0; + } + return (targetSortList->responseTime - currTime); +} SortLinkAttribute *OsGetSortLinkAttribute(SortLinkType type); UINT64 OsGetNextExpireTime(UINT64 startTime); UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader); -VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList); -VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type); -VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type); -UINT32 OsSortLinkGetTargetExpireTime(UINT64 currTime, const SortLinkList *targetSortList); -UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader); +VOID OsSortLinkMiniPeriodEnable(VOID); +VOID OsAddTask2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks); +VOID OsDeleteTaskFromSortLink(SortLinkList *node); +VOID OsAddSwtmr2SortLink(SortLinkList *node, UINT64 startTime, UINT64 waitTime, UINT32 ticks); +VOID OsDeleteSwtmrFromSortLink(SortLinkList *node, UINT32 ticks); +UINT32 OsSortLinkGetTargetRemainTimeTick(UINT64 currTime, const SortLinkList *targetSortList); +UINT32 OsSortLinkGetNextExpireTimeTick(const SortLinkAttribute *sortLinkHeader); #ifdef __cplusplus #if __cplusplus diff --git a/kernel/include/los_swtmr.h b/kernel/include/los_swtmr.h index b86f1bf0a85f873a2aa9601c6fc30e672051ec99..c517c7a59dd59be90b39819490b8e55653c42527 100644 --- a/kernel/include/los_swtmr.h +++ b/kernel/include/los_swtmr.h @@ -276,12 +276,12 @@ typedef struct tagSwTmrCtrl { UINT8 ucSensitive; /* align enable */ #endif UINT32 usTimerID; /* Software timer ID */ - UINT32 uwCount; /* Times that a software timer works */ UINT32 uwInterval; /* Timeout interval of a periodic software timer */ UINT32 uwArg; /* Parameter passed in when the callback function that handles software timer timeout is called */ SWTMR_PROC_FUNC pfnHandler; /* Callback function that handles software timer timeout */ SortLinkList stSortList; + UINT64 startTime; } SWTMR_CTRL_S; diff --git a/kernel/src/los_sched.c b/kernel/src/los_sched.c index bd95f9d496a5641b0399d1b1258f92f9984ec9d4..e95b4f008f4ec61baef445f873a9e30b0aeac543 100644 --- a/kernel/src/los_sched.c +++ b/kernel/src/los_sched.c @@ -56,6 +56,8 @@ STATIC LOS_DL_LIST g_priQueueList[OS_PRIORITY_QUEUE_NUM]; STATIC UINT32 g_queueBitmap; STATIC UINT32 g_schedResponseID = 0; +STATIC UINT16 g_tickIntLock = 0; +STATIC UINT64 g_tickStartTime = 0; STATIC UINT64 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME; STATIC VOID (*SchedRealSleepTimeSet)(UINT64) = NULL; @@ -124,69 +126,97 @@ STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime) taskCB->startTime = currTime; } -STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, BOOL timeUpdate) +STATIC INLINE VOID OsSchedTickReload(UINT64 nextResponseTime, UINT32 responseID, BOOL isTimeSlice, BOOL timeUpdate) { - UINT64 nextExpireTime = OsGetNextExpireTime(startTime); - UINT64 nextResponseTime; - BOOL isTimeSlice = FALSE; + UINT64 currTime, nextExpireTime; + UINT32 usedTime; - /* The current thread's time slice has been consumed, but the current system lock task cannot - * trigger the schedule to release the CPU - */ - if (taskEndTime < nextExpireTime) { - nextExpireTime = taskEndTime; - isTimeSlice = TRUE; + currTime = OsGetCurrSchedTimeCycle(); + if (g_tickStartTime != 0) { + usedTime = currTime - g_tickStartTime; + g_tickStartTime = 0; } - - if ((g_schedResponseTime > nextExpireTime) && ((g_schedResponseTime - nextExpireTime) >= OS_CYCLE_PER_TICK)) { - nextResponseTime = nextExpireTime - startTime; - if (nextResponseTime > OS_TICK_RESPONSE_TIME_MAX) { - if (SchedRealSleepTimeSet != NULL) { - SchedRealSleepTimeSet(nextResponseTime); - } - nextResponseTime = OS_TICK_RESPONSE_TIME_MAX; - nextExpireTime = startTime + nextResponseTime; - } else if (nextResponseTime < OS_CYCLE_PER_TICK) { - if (SchedRealSleepTimeSet != NULL) { - SchedRealSleepTimeSet(0); - } - nextResponseTime = OS_CYCLE_PER_TICK; - nextExpireTime = startTime + nextResponseTime; - if (nextExpireTime >= g_schedResponseTime) { - return; - } - } + if ((nextResponseTime > usedTime) && ((nextResponseTime - usedTime) > OS_TICK_RESPONSE_PRECISION)) { + nextResponseTime -= usedTime; } else { - /* There is no point earlier than the current expiration date */ + nextResponseTime = OS_TICK_RESPONSE_PRECISION; + } + + nextExpireTime = currTime + nextResponseTime; + if (nextExpireTime >= g_schedResponseTime) { return; } +#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0) + if (timeUpdate) { + g_schedTimerBase = currTime; + } +#endif + if (isTimeSlice) { /* The expiration time of the current system is the thread's slice expiration time */ g_schedResponseID = responseID; } else { g_schedResponseID = OS_INVALID; } - g_schedResponseTime = nextExpireTime; -#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0) - if (timeUpdate) { - g_schedTimerBase = OsGetCurrSchedTimeCycle(); - } -#endif HalSysTickReload(nextResponseTime); } +STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID, UINT64 taskEndTime, BOOL timeUpdate) +{ + UINT64 nextExpireTime; + UINT64 nextResponseTime = 0; + BOOL isTimeSlice = FALSE; + + if (g_tickMiniCount) { + nextResponseTime = OS_SCHED_MINI_PERIOD; + g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME; + g_schedResponseID = OS_INVALID; + } else { + nextExpireTime = OsGetNextExpireTime(startTime); + /* The response time of the task time slice is aligned to the next response time in the delay queue */ + if ((nextExpireTime > taskEndTime) && ((nextExpireTime - taskEndTime) > OS_SCHED_MINI_PERIOD)) { + nextExpireTime = taskEndTime; + isTimeSlice = TRUE; + } + + if ((g_schedResponseTime > nextExpireTime) && + ((g_schedResponseTime - nextExpireTime) >= OS_TICK_RESPONSE_PRECISION)) { + nextResponseTime = nextExpireTime - startTime; + if (nextResponseTime > OS_TICK_RESPONSE_TIME_MAX) { + if (SchedRealSleepTimeSet != NULL) { + SchedRealSleepTimeSet(nextResponseTime); + } + nextResponseTime = OS_TICK_RESPONSE_TIME_MAX; + } + + if (SchedRealSleepTimeSet != NULL) { + SchedRealSleepTimeSet(0); + } + } else { + /* There is no point earlier than the current expiration date */ + return; + } + } + + OsSchedTickReload(nextResponseTime, responseID, isTimeSlice, timeUpdate); +} + VOID OsSchedUpdateExpireTime(UINT64 startTime, BOOL timeUpdate) { UINT64 endTime; LosTaskCB *runTask = g_losTask.runTask; + if (g_tickIntLock) { + return; + } + if (runTask->taskID != g_idleTaskID) { INT32 timeSlice = (runTask->timeSlice <= OS_TIME_SLICE_MIN) ? OS_SCHED_TIME_SLICES : runTask->timeSlice; endTime = startTime + timeSlice; } else { - endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_CYCLE_PER_TICK; + endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; } OsSchedSetNextExpireTime(startTime, runTask->taskID, endTime, timeUpdate); } @@ -243,6 +273,7 @@ STATIC INLINE VOID OsSchedWakePendTimeTask(UINT64 currTime, LosTaskCB *taskCB, B STATIC INLINE BOOL OsSchedScanTimerList(VOID) { + UINT64 currTime; BOOL needSchedule = FALSE; LOS_DL_LIST *listObject = &g_taskSortLinkList->sortLink; /* @@ -259,10 +290,10 @@ STATIC INLINE BOOL OsSchedScanTimerList(VOID) } SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode); - UINT64 currTime = OsGetCurrSchedTimeCycle(); + currTime = OsGetCurrSchedTimeCycle(); while (sortList->responseTime <= currTime) { LosTaskCB *taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList); - OsDeleteNodeSortLink(g_taskSortLinkList, &taskCB->sortList); + OsDeleteTaskFromSortLink(&taskCB->sortList); OsSchedWakePendTimeTask(currTime, taskCB, &needSchedule); @@ -317,7 +348,7 @@ VOID OsSchedTaskExit(LosTaskCB *taskCB) } if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) { - OsDeleteSortLink(&taskCB->sortList, OS_SORT_LINK_TASK); + OsDeleteTaskFromSortLink(&taskCB->sortList); taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME); } } @@ -354,7 +385,7 @@ VOID OsSchedTaskWake(LosTaskCB *resumedTask) resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND; if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) { - OsDeleteSortLink(&resumedTask->sortList, OS_SORT_LINK_TASK); + OsDeleteTaskFromSortLink(&resumedTask->sortList); resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME; } @@ -400,7 +431,7 @@ UINT32 OsSchedSwtmrScanRegister(SchedScan func) UINT32 OsTaskNextSwitchTimeGet(VOID) { UINT32 intSave = LOS_IntLock(); - UINT32 ticks = OsSortLinkGetNextExpireTime(g_taskSortLinkList); + UINT32 ticks = OsSortLinkGetNextExpireTimeTick(g_taskSortLinkList); LOS_IntRestore(intSave); return ticks; } @@ -421,6 +452,10 @@ UINT32 OsSchedInit(VOID) OsSortLinkInit(g_taskSortLinkList); g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME; + if (OS_CYCLE_PER_TICK == OS_SCHED_MINI_PERIOD) { + OsSortLinkMiniPeriodEnable(); + } + return LOS_OK; } @@ -466,7 +501,7 @@ BOOL OsSchedTaskSwitch(VOID) OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle()); if (runTask->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) { - OsAdd2SortLink(&runTask->sortList, runTask->startTime, runTask->waitTimes, OS_SORT_LINK_TASK); + OsAddTask2SortLink(&runTask->sortList, runTask->startTime, runTask->waitTimes); } else if (!(runTask->taskStatus & (OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND | OS_TASK_STATUS_UNUSED))) { OsSchedTaskEnQueue(runTask); } @@ -491,7 +526,7 @@ BOOL OsSchedTaskSwitch(VOID) if (newTask->taskID != g_idleTaskID) { endTime = newTask->startTime + newTask->timeSlice; } else { - endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_CYCLE_PER_TICK; + endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; } OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, endTime, TRUE); @@ -520,7 +555,6 @@ UINT64 LOS_SchedTickTimeoutNsGet(VOID) VOID LOS_SchedTickHandler(VOID) { - UINT64 currTime; BOOL needSched = FALSE; if (!g_taskScheduled) { @@ -528,22 +562,23 @@ VOID LOS_SchedTickHandler(VOID) } UINT32 intSave = LOS_IntLock(); - + g_tickStartTime = OsGetCurrSchedTimeCycle(); if (g_schedResponseID == OS_INVALID) { + g_tickIntLock++; if (g_swtmrScan != NULL) { needSched = g_swtmrScan(); } needSched |= OsSchedScanTimerList(); + g_tickIntLock--; } g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME; if (needSched && LOS_CHECK_SCHEDULE) { HalTaskSchedule(); } else { - currTime = OsGetCurrSchedTimeCycle(); - OsTimeSliceUpdate(g_losTask.runTask, currTime); - OsSchedUpdateExpireTime(currTime, TRUE); + OsTimeSliceUpdate(g_losTask.runTask, g_tickStartTime); + OsSchedUpdateExpireTime(g_tickStartTime, TRUE); } LOS_IntRestore(intSave); diff --git a/kernel/src/los_sortlink.c b/kernel/src/los_sortlink.c index e1783063733f592a58ba10f105e25a722fdb2b15..31834f75620daa8fc45e0f9cc3edfa2a05c76196 100644 --- a/kernel/src/los_sortlink.c +++ b/kernel/src/los_sortlink.c @@ -41,6 +41,13 @@ extern "C" { STATIC SortLinkAttribute g_taskSortLink; STATIC SortLinkAttribute g_swtmrSortLink; +STATIC BOOL g_isMiniPeriod = FALSE; +UINT32 g_tickMiniCount; + +VOID OsSortLinkMiniPeriodEnable(VOID) +{ + g_isMiniPeriod = TRUE; +} UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader) { @@ -78,7 +85,7 @@ STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLin } while (1); } -VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) +STATIC INLINE VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) { LOS_ListDelete(&sortList->sortLinkNode); SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME); @@ -86,76 +93,74 @@ VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortL STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime) { - UINT64 expirTime = 0; - UINT64 nextExpirTime = 0; + UINT64 expireTime = 0; + UINT64 nextExpireTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; LOS_DL_LIST *head = &sortHeader->sortLink; LOS_DL_LIST *list = head->pstNext; if (LOS_ListEmpty(head)) { - return OS_SCHED_MAX_RESPONSE_TIME - OS_CYCLE_PER_TICK; + return nextExpireTime; } do { SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode); - if (listSorted->responseTime <= startTime) { - expirTime = startTime; + if (listSorted->responseTime <= (startTime + OS_TICK_RESPONSE_PRECISION)) { + expireTime = listSorted->responseTime; list = list->pstNext; } else { - nextExpirTime = listSorted->responseTime; + nextExpireTime = listSorted->responseTime; break; } } while (list != head); - if (expirTime == 0) { - return nextExpirTime; + if (expireTime >= startTime) { + return expireTime; } - if (nextExpirTime == 0) { - return expirTime; + /* An existing node times out */ + if (expireTime) { + return startTime; } - if ((nextExpirTime - expirTime) <= OS_US_PER_TICK) { - return nextExpirTime; - } - - return expirTime; + return nextExpireTime; } -VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type) +VOID OsAddTask2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks) { - UINT32 intSave; - SortLinkAttribute *sortLinkHeader = NULL; - - if (type == OS_SORT_LINK_TASK) { - sortLinkHeader = &g_taskSortLink; - } else if (type == OS_SORT_LINK_SWTMR) { - sortLinkHeader = &g_swtmrSortLink; - } else { - LOS_Panic("Sort link type error : %u\n", type); - } - - intSave = LOS_IntLock(); + UINT32 intSave = LOS_IntLock(); SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK); - OsAddNode2SortLink(sortLinkHeader, node); + OsAddNode2SortLink(&g_taskSortLink, node); LOS_IntRestore(intSave); } -VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type) +VOID OsDeleteTaskFromSortLink(SortLinkList *node) { - UINT32 intSave; - SortLinkAttribute *sortLinkHeader = NULL; + UINT32 intSave = LOS_IntLock(); + if (node->responseTime != OS_SORT_LINK_INVALID_TIME) { + OsDeleteNodeSortLink(&g_taskSortLink, node); + } + LOS_IntRestore(intSave); +} - if (type == OS_SORT_LINK_TASK) { - sortLinkHeader = &g_taskSortLink; - } else if (type == OS_SORT_LINK_SWTMR) { - sortLinkHeader = &g_swtmrSortLink; - } else { - LOS_Panic("Sort link type error : %u\n", type); +VOID OsAddSwtmr2SortLink(SortLinkList *node, UINT64 startTime, UINT64 waitTime, UINT32 ticks) +{ + UINT32 intSave = LOS_IntLock(); + SET_SORTLIST_VALUE(node, startTime + waitTime); + OsAddNode2SortLink(&g_swtmrSortLink, node); + if (g_isMiniPeriod && (ticks == OS_TICK_MINI_PERIOD)) { + g_tickMiniCount++; } + LOS_IntRestore(intSave); +} - intSave = LOS_IntLock(); +VOID OsDeleteSwtmrFromSortLink(SortLinkList *node, UINT32 ticks) +{ + UINT32 intSave = LOS_IntLock(); if (node->responseTime != OS_SORT_LINK_INVALID_TIME) { - OsDeleteNodeSortLink(sortLinkHeader, node); + OsDeleteNodeSortLink(&g_swtmrSortLink, node); + if (g_isMiniPeriod && (ticks == OS_TICK_MINI_PERIOD)) { + g_tickMiniCount--; + } } LOS_IntRestore(intSave); } @@ -186,16 +191,16 @@ UINT64 OsGetNextExpireTime(UINT64 startTime) return (taskExpirTime < swtmrExpirTime) ? taskExpirTime : swtmrExpirTime; } -UINT32 OsSortLinkGetTargetExpireTime(UINT64 currTime, const SortLinkList *targetSortList) +UINT32 OsSortLinkGetTargetRemainTimeTick(UINT64 currTime, const SortLinkList *targetSortList) { if (currTime >= targetSortList->responseTime) { return 0; } - return (UINT32)(((targetSortList->responseTime - currTime) * LOSCFG_BASE_CORE_TICK_PER_SECOND) / OS_SYS_CLOCK); + return (UINT32)((targetSortList->responseTime - currTime) / OS_CYCLE_PER_TICK); } -UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader) +UINT32 OsSortLinkGetNextExpireTimeTick(const SortLinkAttribute *sortLinkHeader) { LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; @@ -204,7 +209,7 @@ UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader) } SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode); - return OsSortLinkGetTargetExpireTime(OsGetCurrSchedTimeCycle(), listSorted); + return OsSortLinkGetTargetRemainTimeTick(OsGetCurrSchedTimeCycle(), listSorted); } #ifdef __cplusplus diff --git a/kernel/src/los_swtmr.c b/kernel/src/los_swtmr.c index f0343c2fef554e7e44930b5e759aaa7bb685c4ae..e91218c6b713353aedca014c4458a0a8b259e0df 100644 --- a/kernel/src/los_swtmr.c +++ b/kernel/src/los_swtmr.c @@ -120,103 +120,116 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrTaskCreate(VOID) } #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1) -STATIC_INLINE UINT32 OsSwtmrCalcAlignCount(UINT64 currTime, UINT32 interval, UINT32 timerId) +STATIC UINT64 OsSwtmrGetRemainTime(UINT64 currTime, SWTMR_CTRL_S *swtmr, const SWTMR_CTRL_S *alignSwtmr) { - UINT32 count; + UINT32 usedTime; + UINT64 alignEnd = alignSwtmr->uwInterval * OS_CYCLE_PER_TICK; + UINT64 swtmrTime = swtmr->uwInterval * OS_CYCLE_PER_TICK; + UINT64 remainTime = OsSortLinkGetRemainTime(currTime, &alignSwtmr->stSortList); + if (remainTime == 0) { + swtmr->startTime = GET_SORTLIST_VALUE(&alignSwtmr->stSortList); + } else { + usedTime = alignEnd - remainTime; + swtmr->startTime = alignSwtmr->startTime + (usedTime / swtmrTime) * swtmrTime; + } + + return remainTime; +} - if (interval == 0) { - return interval; - } - SWTMR_CTRL_S *cur = g_swtmrCBArray + timerId % LOSCFG_BASE_CORE_SWTMR_LIMIT; - count = OsSortLinkGetTargetExpireTime(currTime, &cur->stSortList); - return (interval - (cur->uwInterval - count) % interval); +STATIC_INLINE UINT64 OsSwtmrCalcAlignCount(UINT64 currTime, SWTMR_CTRL_S *swtmr, const SWTMR_CTRL_S *alignSwtmr) +{ + UINT64 remainTime = OsSwtmrGetRemainTime(currTime, swtmr, alignSwtmr); + UINT64 alignEnd = alignSwtmr->uwInterval * OS_CYCLE_PER_TICK; + UINT64 swtmrTime = swtmr->uwInterval * OS_CYCLE_PER_TICK; + + return (swtmrTime - (alignEnd - remainTime) % swtmrTime); } -VOID OsSwtmrFindAlignPos(UINT64 currTime, SWTMR_CTRL_S *swtmr) +UINT64 OsSwtmrFindAlignPos(UINT64 currTime, SWTMR_CTRL_S *swtmr) { SWTMR_CTRL_S *minInLarge = (SWTMR_CTRL_S *)NULL; SWTMR_CTRL_S *maxInLittle = (SWTMR_CTRL_S *)NULL; - UINT32 currSwtmrTimes, swtmrTimes; UINT32 minInLargeVal = OS_NULL_INT; UINT32 maxInLittleVal = OS_NULL_INT; - LOS_DL_LIST *listHead = &g_swtmrSortLinkList->sortLink; + SwtmrAlignData swtmrAlgInfo = g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT]; + LOS_DL_LIST *listObject = listHead->pstNext; + if (LOS_ListEmpty(listHead)) { - return; + goto RETURN_PERIOD; } - SwtmrAlignData currSwtmrAlgInfo = g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT]; - currSwtmrTimes = currSwtmrAlgInfo.times; - LOS_DL_LIST *listObject = listHead->pstNext; - do { SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject, SortLinkList, sortLinkNode); - SWTMR_CTRL_S *cur = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList); - SwtmrAlignData swtmrAlgInfo = g_swtmrAlignID[cur->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT]; + SWTMR_CTRL_S *swtmrListNode = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList); + SwtmrAlignData alignListNode = g_swtmrAlignID[swtmrListNode->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT]; + /* swtmr not start */ - if ((swtmrAlgInfo.isAligned == 0) || (swtmrAlgInfo.canAlign == 0)) { + if ((alignListNode.isAligned == 0) || (alignListNode.canAlign == 0)) { goto CONTINUE_NEXT_NODE; } + /* find same interval timer, directly return */ - if (cur->uwInterval == swtmr->uwInterval) { - swtmr->uwCount = OsSortLinkGetTargetExpireTime(currTime, &cur->stSortList); - return; + if (swtmrListNode->uwInterval == swtmr->uwInterval) { + return OsSwtmrGetRemainTime(currTime, swtmr, swtmrListNode); } - if ((currSwtmrAlgInfo.canMultiple != 1) || (swtmrAlgInfo.times == 0)) { + if ((swtmrAlgInfo.canMultiple != 1) || (alignListNode.times == 0)) { goto CONTINUE_NEXT_NODE; } - swtmrTimes = swtmrAlgInfo.times; - if (currSwtmrTimes == 0) { - return; + + if (swtmrAlgInfo.times == 0) { + goto RETURN_PERIOD; } - if ((swtmrTimes >= currSwtmrTimes) && ((swtmrTimes % currSwtmrTimes) == 0)) { - if (minInLargeVal > (swtmrTimes / currSwtmrTimes)) { - minInLargeVal = swtmrTimes / currSwtmrTimes; - minInLarge = cur; + + if ((alignListNode.times >= swtmrAlgInfo.times) && ((alignListNode.times % swtmrAlgInfo.times) == 0)) { + if (minInLargeVal > (alignListNode.times / swtmrAlgInfo.times)) { + minInLargeVal = alignListNode.times / swtmrAlgInfo.times; + minInLarge = swtmrListNode; } - } else if ((swtmrTimes < currSwtmrTimes) && ((currSwtmrTimes % swtmrTimes) == 0)) { - if (maxInLittleVal > (currSwtmrTimes / swtmrTimes)) { - maxInLittleVal = currSwtmrTimes / swtmrTimes; - maxInLittle = cur; + } else if ((alignListNode.times < swtmrAlgInfo.times) && ((swtmrAlgInfo.times % alignListNode.times) == 0)) { + if (maxInLittleVal > (swtmrAlgInfo.times / alignListNode.times)) { + maxInLittleVal = swtmrAlgInfo.times / alignListNode.times; + maxInLittle = swtmrListNode; } } + CONTINUE_NEXT_NODE: listObject = listObject->pstNext; } while (listObject != listHead); if (minInLarge != NULL) { - swtmr->uwCount = OsSwtmrCalcAlignCount(currTime, swtmr->uwInterval, minInLarge->usTimerID); + return OsSwtmrCalcAlignCount(currTime, swtmr, minInLarge); } else if (maxInLittle != NULL) { - swtmr->uwCount = OsSortLinkGetTargetExpireTime(currTime, &maxInLittle->stSortList); + return OsSwtmrGetRemainTime(currTime, swtmr, maxInLittle); } - return; +RETURN_PERIOD: + return ((UINT64)swtmr->uwInterval * OS_CYCLE_PER_TICK); } #endif /***************************************************************************** Function : OsSwtmrStart Description : Start Software Timer +Input : currTime ------- Current system time Input : swtmr ---------- Need to start Software Timer Output : None Return : None *****************************************************************************/ -LITE_OS_SEC_TEXT VOID OsSwtmrStart(SWTMR_CTRL_S *swtmr) +LITE_OS_SEC_TEXT VOID OsSwtmrStart(UINT64 currTime, SWTMR_CTRL_S *swtmr) { - UINT64 currTime = OsGetCurrSchedTimeCycle(); - - swtmr->uwCount = swtmr->uwInterval; + UINT64 time = (UINT64)swtmr->uwInterval * OS_CYCLE_PER_TICK; swtmr->ucState = OS_SWTMR_STATUS_TICKING; #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1) if ((g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].canAlign == 1) && (g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned == 0)) { g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned = 1; - OsSwtmrFindAlignPos(currTime, swtmr); + time = OsSwtmrFindAlignPos(currTime, swtmr); } #endif - OsAdd2SortLink(&swtmr->stSortList, currTime, swtmr->uwCount, OS_SORT_LINK_SWTMR); + OsAddSwtmr2SortLink(&swtmr->stSortList, swtmr->startTime, time, swtmr->uwInterval); if (LOS_TaskIsRunning()) { OsSchedUpdateExpireTime(currTime, TRUE); } @@ -245,7 +258,7 @@ STATIC_INLINE VOID OsSwtmrDelete(SWTMR_CTRL_S *swtmr) LITE_OS_SEC_TEXT VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr) { - OsDeleteSortLink(&swtmr->stSortList, OS_SORT_LINK_SWTMR); + OsDeleteSwtmrFromSortLink(&swtmr->stSortList, swtmr->uwInterval); swtmr->ucState = OS_SWTMR_STATUS_CREATED; if (LOS_TaskIsRunning()) { @@ -256,7 +269,7 @@ LITE_OS_SEC_TEXT VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr) } } -STATIC VOID OsSwtmrTimeoutHandle(SWTMR_CTRL_S *swtmr) +STATIC VOID OsSwtmrTimeoutHandle(UINT64 currTime, SWTMR_CTRL_S *swtmr) { SwtmrHandlerItem swtmrHandler; @@ -272,7 +285,7 @@ STATIC VOID OsSwtmrTimeoutHandle(SWTMR_CTRL_S *swtmr) swtmr->usTimerID %= LOSCFG_BASE_CORE_SWTMR_LIMIT; } } else if (swtmr->ucMode == LOS_SWTMR_MODE_PERIOD) { - OsSwtmrStart(swtmr); + OsSwtmrStart(currTime, swtmr); } else if (swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE) { swtmr->ucState = OS_SWTMR_STATUS_CREATED; } @@ -280,6 +293,7 @@ STATIC VOID OsSwtmrTimeoutHandle(SWTMR_CTRL_S *swtmr) STATIC BOOL OsSwtmrScan(VOID) { + UINT64 currTime; BOOL needSchedule = FALSE; LOS_DL_LIST *listObject = &g_swtmrSortLinkList->sortLink; @@ -288,13 +302,14 @@ STATIC BOOL OsSwtmrScan(VOID) } SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode); - UINT64 currTime = OsGetCurrSchedTimeCycle(); + currTime = OsGetCurrSchedTimeCycle(); while (sortList->responseTime <= currTime) { - OsDeleteNodeSortLink(g_swtmrSortLinkList, sortList); - SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList); + swtmr->startTime = GET_SORTLIST_VALUE(sortList); + + OsDeleteSwtmrFromSortLink(sortList, swtmr->uwInterval); OsHookCall(LOS_HOOK_TYPE_SWTMR_EXPIRED, swtmr); - OsSwtmrTimeoutHandle(swtmr); + OsSwtmrTimeoutHandle(currTime, swtmr); needSchedule = TRUE; if (LOS_ListEmpty(listObject)) { @@ -317,14 +332,14 @@ Return : Count of the Timer list LITE_OS_SEC_TEXT UINT32 OsSwtmrGetNextTimeout(VOID) { UINT32 intSave = LOS_IntLock(); - UINT32 ticks = OsSortLinkGetNextExpireTime(g_swtmrSortLinkList); + UINT32 ticks = OsSortLinkGetNextExpireTimeTick(g_swtmrSortLinkList); LOS_IntRestore(intSave); return ticks; } LITE_OS_SEC_TEXT UINT32 OsSwtmrTimeGet(const SWTMR_CTRL_S *swtmr) { - return OsSortLinkGetTargetExpireTime(OsGetCurrSchedTimeCycle(), &swtmr->stSortList); + return OsSortLinkGetTargetRemainTimeTick(OsGetCurrSchedTimeCycle(), &swtmr->stSortList); } /***************************************************************************** @@ -468,7 +483,6 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval, swtmr->ucMode = mode; swtmr->uwInterval = interval; swtmr->pstNext = (SWTMR_CTRL_S *)NULL; - swtmr->uwCount = 0; swtmr->uwArg = arg; #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1) swtmr->ucRouses = rouses; @@ -523,7 +537,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT32 swtmrId) OsSwtmrStop(swtmr); /* fall through */ case OS_SWTMR_STATUS_CREATED: - OsSwtmrStart(swtmr); + swtmr->startTime = OsGetCurrSchedTimeCycle(); + OsSwtmrStart(swtmr->startTime, swtmr); break; default: ret = LOS_ERRNO_SWTMR_STATUS_INVALID;