fix: tick 动态化计算优化,消除中断执行时间对系统总体时间的影响,保证软件定时器的响应精度。
方案描述: 1.周期软件定时器超时添加一个startTime字段,用于记录当前软件定时器的开始计时的时间, 在定时器响应时,开始时间修改为上一次响应的结束时间(消除了中断执行时间对软件定时器 的影响)。 2.在执行tick中断的过程当中,持有tick动态计算锁,保证在该过程中不会触发tick周期 的计算,在tick中断结束时统一计算设置。 --- 提升tick中断的执行效率 3.在设置tick周期时,减掉tick中断执行的时间,减小周期动态化带来的时间误差 4.新增LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI配置宏,用于配置tick中断的最小响应精度 Close #I43UQJ Signed-off-by: zhushengle <zhushengle@huawei.com> Change-Id: Icd1159a1890046b13602b7a18dcd6234d5c61a89
This commit is contained in:
parent
9ec208a273
commit
8df3e8c965
|
@ -34,7 +34,6 @@ kernel_module(module_name) {
|
||||||
sources = [
|
sources = [
|
||||||
"core/los_bitmap.c",
|
"core/los_bitmap.c",
|
||||||
"core/los_process.c",
|
"core/los_process.c",
|
||||||
"core/los_sortlink.c",
|
|
||||||
"core/los_swtmr.c",
|
"core/los_swtmr.c",
|
||||||
"core/los_sys.c",
|
"core/los_sys.c",
|
||||||
"core/los_task.c",
|
"core/los_task.c",
|
||||||
|
@ -68,6 +67,7 @@ kernel_module(module_name) {
|
||||||
"mp/los_stat.c",
|
"mp/los_stat.c",
|
||||||
"om/los_err.c",
|
"om/los_err.c",
|
||||||
"sched/sched_sq/los_sched.c",
|
"sched/sched_sq/los_sched.c",
|
||||||
|
"sched/sched_sq/los_sortlink.c",
|
||||||
"vm/los_vm_boot.c",
|
"vm/los_vm_boot.c",
|
||||||
"vm/los_vm_dump.c",
|
"vm/los_vm_dump.c",
|
||||||
"vm/los_vm_fault.c",
|
"vm/los_vm_fault.c",
|
||||||
|
@ -83,9 +83,7 @@ kernel_module(module_name) {
|
||||||
]
|
]
|
||||||
|
|
||||||
if (defined(LOSCFG_SHELL_CMD_DEBUG)) {
|
if (defined(LOSCFG_SHELL_CMD_DEBUG)) {
|
||||||
configs += [
|
configs += [ "$HDFTOPDIR:hdf_config" ]
|
||||||
"$HDFTOPDIR:hdf_config"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public_configs = [ ":public" ]
|
public_configs = [ ":public" ]
|
||||||
|
|
|
@ -178,10 +178,9 @@ ERROR:
|
||||||
* Description: Start Software Timer
|
* Description: Start Software Timer
|
||||||
* Input : swtmr --- Need to start software timer
|
* Input : swtmr --- Need to start software timer
|
||||||
*/
|
*/
|
||||||
LITE_OS_SEC_TEXT VOID OsSwtmrStart(SWTMR_CTRL_S *swtmr)
|
LITE_OS_SEC_TEXT VOID OsSwtmrStart(UINT64 currTime, SWTMR_CTRL_S *swtmr)
|
||||||
{
|
{
|
||||||
UINT32 ticks;
|
UINT32 ticks;
|
||||||
UINT64 currTime = OsGetCurrSchedTimeCycle();
|
|
||||||
|
|
||||||
if ((swtmr->uwOverrun == 0) && ((swtmr->ucMode == LOS_SWTMR_MODE_ONCE) ||
|
if ((swtmr->uwOverrun == 0) && ((swtmr->ucMode == LOS_SWTMR_MODE_ONCE) ||
|
||||||
(swtmr->ucMode == LOS_SWTMR_MODE_OPP) ||
|
(swtmr->ucMode == LOS_SWTMR_MODE_OPP) ||
|
||||||
|
@ -192,10 +191,8 @@ LITE_OS_SEC_TEXT VOID OsSwtmrStart(SWTMR_CTRL_S *swtmr)
|
||||||
}
|
}
|
||||||
swtmr->ucState = OS_SWTMR_STATUS_TICKING;
|
swtmr->ucState = OS_SWTMR_STATUS_TICKING;
|
||||||
|
|
||||||
OsAdd2SortLink(&swtmr->stSortList, currTime, ticks, OS_SORT_LINK_SWTMR);
|
OsAdd2SortLink(&swtmr->stSortList, swtmr->startTime, ticks, OS_SORT_LINK_SWTMR);
|
||||||
if (OS_SCHEDULER_ACTIVE) {
|
OsSchedUpdateExpireTime(currTime);
|
||||||
OsSchedUpdateExpireTime(currTime);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +208,7 @@ STATIC INLINE VOID OsSwtmrDelete(SWTMR_CTRL_S *swtmr)
|
||||||
swtmr->uwOwnerPid = 0;
|
swtmr->uwOwnerPid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC INLINE VOID OsWakePendTimeSwtmr(Percpu *cpu, SWTMR_CTRL_S *swtmr)
|
STATIC INLINE VOID OsWakePendTimeSwtmr(Percpu *cpu, UINT64 currTime, SWTMR_CTRL_S *swtmr)
|
||||||
{
|
{
|
||||||
LOS_SpinLock(&g_swtmrSpin);
|
LOS_SpinLock(&g_swtmrSpin);
|
||||||
SwtmrHandlerItemPtr swtmrHandler = (SwtmrHandlerItemPtr)LOS_MemboxAlloc(g_swtmrHandlerPool);
|
SwtmrHandlerItemPtr swtmrHandler = (SwtmrHandlerItemPtr)LOS_MemboxAlloc(g_swtmrHandlerPool);
|
||||||
|
@ -236,7 +233,7 @@ STATIC INLINE VOID OsWakePendTimeSwtmr(Percpu *cpu, SWTMR_CTRL_S *swtmr)
|
||||||
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
|
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
|
||||||
} else {
|
} else {
|
||||||
swtmr->uwOverrun++;
|
swtmr->uwOverrun++;
|
||||||
OsSwtmrStart(swtmr);
|
OsSwtmrStart(currTime, swtmr);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOS_SpinUnlock(&g_swtmrSpin);
|
LOS_SpinUnlock(&g_swtmrSpin);
|
||||||
|
@ -267,12 +264,12 @@ LITE_OS_SEC_TEXT VOID OsSwtmrScan(VOID)
|
||||||
UINT64 currTime = OsGetCurrSchedTimeCycle();
|
UINT64 currTime = OsGetCurrSchedTimeCycle();
|
||||||
while (sortList->responseTime <= currTime) {
|
while (sortList->responseTime <= currTime) {
|
||||||
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
|
sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
|
||||||
OsDeleteNodeSortLink(swtmrSortLink, sortList);
|
|
||||||
|
|
||||||
SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
|
SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
|
||||||
|
swtmr->startTime = GET_SORTLIST_VALUE(sortList);
|
||||||
|
OsDeleteNodeSortLink(swtmrSortLink, sortList);
|
||||||
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
|
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
|
||||||
|
|
||||||
OsWakePendTimeSwtmr(cpu, swtmr);
|
OsWakePendTimeSwtmr(cpu, currTime, swtmr);
|
||||||
|
|
||||||
LOS_SpinLock(&cpu->swtmrSortLinkSpin);
|
LOS_SpinLock(&cpu->swtmrSortLinkSpin);
|
||||||
if (LOS_ListEmpty(listObject)) {
|
if (LOS_ListEmpty(listObject)) {
|
||||||
|
@ -305,9 +302,7 @@ LITE_OS_SEC_TEXT STATIC VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr)
|
||||||
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
|
swtmr->ucState = OS_SWTMR_STATUS_CREATED;
|
||||||
swtmr->uwOverrun = 0;
|
swtmr->uwOverrun = 0;
|
||||||
|
|
||||||
if (OS_SCHEDULER_ACTIVE) {
|
OsSchedUpdateExpireTime(OsGetCurrSchedTimeCycle());
|
||||||
OsSchedUpdateExpireTime(OsGetCurrSchedTimeCycle());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -403,7 +398,8 @@ LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT16 swtmrID)
|
||||||
OsSwtmrStop(swtmr);
|
OsSwtmrStop(swtmr);
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case OS_SWTMR_STATUS_CREATED:
|
case OS_SWTMR_STATUS_CREATED:
|
||||||
OsSwtmrStart(swtmr);
|
swtmr->startTime = OsGetCurrSchedTimeCycle();
|
||||||
|
OsSwtmrStart(swtmr->startTime, swtmr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
|
ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
|
||||||
|
|
|
@ -57,6 +57,7 @@ typedef struct {
|
||||||
SortLinkAttribute swtmrSortLink; /* swtmr sort link */
|
SortLinkAttribute swtmrSortLink; /* swtmr sort link */
|
||||||
SPIN_LOCK_S swtmrSortLinkSpin; /* swtmr sort link spin lock */
|
SPIN_LOCK_S swtmrSortLinkSpin; /* swtmr sort link spin lock */
|
||||||
UINT64 responseTime; /* Response time for current nuclear Tick interrupts */
|
UINT64 responseTime; /* Response time for current nuclear Tick interrupts */
|
||||||
|
UINT64 tickStartTime; /* The time when the tick interrupt starts processing */
|
||||||
UINT32 responseID; /* The response ID of the current nuclear TICK interrupt */
|
UINT32 responseID; /* The response ID of the current nuclear TICK interrupt */
|
||||||
UINTPTR runProcess; /* The address of the process control block pointer to which
|
UINTPTR runProcess; /* The address of the process control block pointer to which
|
||||||
the current kernel is running */
|
the current kernel is running */
|
||||||
|
|
|
@ -45,6 +45,10 @@ extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#define OS_SCHED_MINI_PERIOD (OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI)
|
||||||
|
#define OS_TICK_RESPONSE_PRECISION (UINT32)((OS_SCHED_MINI_PERIOD * 75) / 100)
|
||||||
|
#define OS_SCHED_MAX_RESPONSE_TIME (UINT64)(((UINT64)-1) - 1U)
|
||||||
|
|
||||||
extern UINT32 g_taskScheduled;
|
extern UINT32 g_taskScheduled;
|
||||||
typedef BOOL (*SchedScan)(VOID);
|
typedef BOOL (*SchedScan)(VOID);
|
||||||
|
|
||||||
|
@ -86,8 +90,9 @@ STATIC INLINE VOID OsSchedIrqStartTime(VOID)
|
||||||
#define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid()))
|
#define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid()))
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
INT_NO_RESCH = 0, /* no needs to schedule */
|
INT_NO_RESCH = 0x0, /* no needs to schedule */
|
||||||
INT_PEND_RESCH, /* pending schedule flag */
|
INT_PEND_RESCH = 0x1, /* pending schedule flag */
|
||||||
|
INT_PEND_TICK = 0x2, /* pending tick */
|
||||||
} SchedFlag;
|
} SchedFlag;
|
||||||
|
|
||||||
/* Check if preemptable with counter flag */
|
/* Check if preemptable with counter flag */
|
||||||
|
@ -102,7 +107,7 @@ STATIC INLINE BOOL OsPreemptable(VOID)
|
||||||
BOOL preemptable = (OsPercpuGet()->taskLockCnt == 0);
|
BOOL preemptable = (OsPercpuGet()->taskLockCnt == 0);
|
||||||
if (!preemptable) {
|
if (!preemptable) {
|
||||||
/* Set schedule flag if preemption is disabled */
|
/* Set schedule flag if preemption is disabled */
|
||||||
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
|
OsPercpuGet()->schedFlag |= INT_PEND_RESCH;
|
||||||
}
|
}
|
||||||
LOS_IntRestore(intSave);
|
LOS_IntRestore(intSave);
|
||||||
return preemptable;
|
return preemptable;
|
||||||
|
@ -124,7 +129,7 @@ STATIC INLINE BOOL OsPreemptableInSched(VOID)
|
||||||
#endif
|
#endif
|
||||||
if (!preemptable) {
|
if (!preemptable) {
|
||||||
/* Set schedule flag if preemption is disabled */
|
/* Set schedule flag if preemption is disabled */
|
||||||
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
|
OsPercpuGet()->schedFlag |= INT_PEND_RESCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
return preemptable;
|
return preemptable;
|
||||||
|
@ -139,8 +144,8 @@ STATIC INLINE VOID OsCpuSchedUnlock(Percpu *cpu, UINT32 intSave)
|
||||||
{
|
{
|
||||||
if (cpu->taskLockCnt > 0) {
|
if (cpu->taskLockCnt > 0) {
|
||||||
cpu->taskLockCnt--;
|
cpu->taskLockCnt--;
|
||||||
if ((cpu->taskLockCnt == 0) && (cpu->schedFlag == INT_PEND_RESCH) && OS_SCHEDULER_ACTIVE) {
|
if ((cpu->taskLockCnt == 0) && (cpu->schedFlag & INT_PEND_RESCH) && OS_SCHEDULER_ACTIVE) {
|
||||||
cpu->schedFlag = INT_NO_RESCH;
|
cpu->schedFlag &= ~INT_PEND_RESCH;
|
||||||
LOS_IntRestore(intSave);
|
LOS_IntRestore(intSave);
|
||||||
LOS_Schedule();
|
LOS_Schedule();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -62,6 +62,7 @@ typedef struct {
|
||||||
|
|
||||||
#define OS_SORT_LINK_INVALID_TIME ((UINT64)-1)
|
#define OS_SORT_LINK_INVALID_TIME ((UINT64)-1)
|
||||||
#define SET_SORTLIST_VALUE(sortList, value) (((SortLinkList *)(sortList))->responseTime = (value))
|
#define SET_SORTLIST_VALUE(sortList, value) (((SortLinkList *)(sortList))->responseTime = (value))
|
||||||
|
#define GET_SORTLIST_VALUE(sortList) (((SortLinkList *)(sortList))->responseTime)
|
||||||
|
|
||||||
extern UINT64 OsGetNextExpireTime(UINT64 startTime);
|
extern UINT64 OsGetNextExpireTime(UINT64 startTime);
|
||||||
extern UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader);
|
extern UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader);
|
||||||
|
|
|
@ -54,6 +54,9 @@ LITE_OS_SEC_DATA_MINOR STATIC CHAR g_shellSwtmrStatus[][SWTMR_STRLEN] = {
|
||||||
|
|
||||||
STATIC VOID OsPrintSwtmrMsg(const SWTMR_CTRL_S *swtmr)
|
STATIC VOID OsPrintSwtmrMsg(const SWTMR_CTRL_S *swtmr)
|
||||||
{
|
{
|
||||||
|
UINT32 ticks = 0;
|
||||||
|
(VOID)LOS_SwtmrTimeGet(swtmr->usTimerID, &ticks);
|
||||||
|
|
||||||
PRINTK("0x%08x "
|
PRINTK("0x%08x "
|
||||||
"%-7s "
|
"%-7s "
|
||||||
"%-6s "
|
"%-6s "
|
||||||
|
@ -65,7 +68,7 @@ STATIC VOID OsPrintSwtmrMsg(const SWTMR_CTRL_S *swtmr)
|
||||||
g_shellSwtmrStatus[swtmr->ucState],
|
g_shellSwtmrStatus[swtmr->ucState],
|
||||||
g_shellSwtmrMode[swtmr->ucMode],
|
g_shellSwtmrMode[swtmr->ucMode],
|
||||||
swtmr->uwInterval,
|
swtmr->uwInterval,
|
||||||
swtmr->uwCount,
|
ticks,
|
||||||
swtmr->uwArg,
|
swtmr->uwArg,
|
||||||
swtmr->pfnHandler);
|
swtmr->pfnHandler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ VOID OsMpScheduleHandler(VOID)
|
||||||
* set schedule flag to differ from wake function,
|
* set schedule flag to differ from wake function,
|
||||||
* so that the scheduler can be triggered at the end of irq.
|
* so that the scheduler can be triggered at the end of irq.
|
||||||
*/
|
*/
|
||||||
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
|
OsPercpuGet()->schedFlag |= INT_PEND_RESCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID OsMpHaltHandler(VOID)
|
VOID OsMpHaltHandler(VOID)
|
||||||
|
|
|
@ -47,8 +47,6 @@
|
||||||
#include "los_stat_pri.h"
|
#include "los_stat_pri.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define OS_32BIT_MAX 0xFFFFFFFFUL
|
#define OS_32BIT_MAX 0xFFFFFFFFUL
|
||||||
#define OS_64BIT_MAX 0xFFFFFFFFFFFFFFFFULL
|
#define OS_64BIT_MAX 0xFFFFFFFFFFFFFFFFULL
|
||||||
#define OS_SCHED_FIFO_TIMEOUT 0x7FFFFFFF
|
#define OS_SCHED_FIFO_TIMEOUT 0x7FFFFFFF
|
||||||
|
@ -59,7 +57,6 @@
|
||||||
#define OS_SCHED_TIME_SLICES_DIFF (OS_SCHED_TIME_SLICES_MAX - OS_SCHED_TIME_SLICES_MIN)
|
#define OS_SCHED_TIME_SLICES_DIFF (OS_SCHED_TIME_SLICES_MAX - OS_SCHED_TIME_SLICES_MIN)
|
||||||
#define OS_SCHED_READY_MAX 30
|
#define OS_SCHED_READY_MAX 30
|
||||||
#define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */
|
#define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */
|
||||||
#define OS_SCHED_MAX_RESPONSE_TIME (UINT64)(OS_64BIT_MAX - 1U)
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LOS_DL_LIST priQueueList[OS_PRIORITY_QUEUE_NUM];
|
LOS_DL_LIST priQueueList[OS_PRIORITY_QUEUE_NUM];
|
||||||
|
@ -120,6 +117,7 @@ UINT32 OsShellShowTickRespo(VOID)
|
||||||
{
|
{
|
||||||
UINT32 intSave;
|
UINT32 intSave;
|
||||||
UINT16 cpu;
|
UINT16 cpu;
|
||||||
|
UINT64 allTime;
|
||||||
|
|
||||||
UINT32 tickSize = sizeof(SchedTickDebug) * LOSCFG_KERNEL_CORE_NUM;
|
UINT32 tickSize = sizeof(SchedTickDebug) * LOSCFG_KERNEL_CORE_NUM;
|
||||||
SchedTickDebug *schedDebug = (SchedTickDebug *)LOS_MemAlloc(m_aucSysMem1, tickSize);
|
SchedTickDebug *schedDebug = (SchedTickDebug *)LOS_MemAlloc(m_aucSysMem1, tickSize);
|
||||||
|
@ -141,15 +139,18 @@ UINT32 OsShellShowTickRespo(VOID)
|
||||||
PRINTK("cpu : %u sched data num : %u set time count : %u SortMax : %u\n",
|
PRINTK("cpu : %u sched data num : %u set time count : %u SortMax : %u\n",
|
||||||
cpu, schedData->index, schedData->setTickCount, sortLinkNum[cpu]);
|
cpu, schedData->index, schedData->setTickCount, sortLinkNum[cpu]);
|
||||||
UINT32 *data = schedData->tickResporeTime;
|
UINT32 *data = schedData->tickResporeTime;
|
||||||
for (UINT32 i = 0; i < schedData->index; i++) {
|
allTime = 0;
|
||||||
|
for (UINT32 i = 1; i < schedData->index; i++) {
|
||||||
|
allTime += data[i];
|
||||||
UINT32 timeUs = (data[i] * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
|
UINT32 timeUs = (data[i] * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
|
||||||
PRINTK(" %u(%u)", timeUs, timeUs / OS_US_PER_TICK);
|
PRINTK(" %u(%u)", timeUs, timeUs / OS_US_PER_TICK);
|
||||||
if ((i != 0) && ((i % 5) == 0)) {
|
if ((i != 0) && ((i % 5) == 0)) { /* A row of 5 data */
|
||||||
PRINTK("\n");
|
PRINTK("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINTK("\n");
|
allTime = (allTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
|
||||||
|
PRINTK("\nTick Indicates the average response period: %llu(us)\n", allTime / (schedData->index - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
(VOID)LOS_MemFree(m_aucSysMem1, schedDebug);
|
(VOID)LOS_MemFree(m_aucSysMem1, schedDebug);
|
||||||
|
@ -279,41 +280,27 @@ STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID,
|
STATIC INLINE VOID OsSchedTickReload(Percpu *currCpu, UINT64 nextResponseTime, UINT32 responseID, BOOL isTimeSlice)
|
||||||
UINT64 taskEndTime, UINT32 oldResponseID)
|
|
||||||
{
|
{
|
||||||
UINT64 nextExpireTime = OsGetNextExpireTime(startTime);
|
UINT64 currTime, nextExpireTime;
|
||||||
Percpu *currCpu = OsPercpuGet();
|
UINT32 usedTime;
|
||||||
UINT64 nextResponseTime;
|
|
||||||
BOOL isTimeSlice = FALSE;
|
|
||||||
|
|
||||||
if (currCpu->responseID == oldResponseID) {
|
currTime = OsGetCurrSchedTimeCycle();
|
||||||
/* This time has expired, and the next time the theory has expired is infinite */
|
if (currCpu->tickStartTime != 0) {
|
||||||
currCpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
usedTime = currTime - currCpu->tickStartTime;
|
||||||
}
|
currCpu->tickStartTime = 0;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((currCpu->responseTime > nextExpireTime) && ((currCpu->responseTime - nextExpireTime) >= OS_CYCLE_PER_TICK)) {
|
|
||||||
nextResponseTime = nextExpireTime - startTime;
|
|
||||||
if (nextResponseTime < OS_CYCLE_PER_TICK) {
|
|
||||||
nextResponseTime = OS_CYCLE_PER_TICK;
|
|
||||||
nextExpireTime = startTime + nextResponseTime;
|
|
||||||
if (nextExpireTime >= currCpu->responseTime) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (nextResponseTime > g_schedTickMaxResponseTime) {
|
|
||||||
nextResponseTime = g_schedTickMaxResponseTime;
|
|
||||||
nextExpireTime = startTime + nextResponseTime;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* There is no point earlier than the current expiration date */
|
usedTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nextResponseTime > usedTime) && ((nextResponseTime - usedTime) > OS_TICK_RESPONSE_PRECISION)) {
|
||||||
|
nextResponseTime -= usedTime;
|
||||||
|
} else {
|
||||||
|
nextResponseTime = OS_TICK_RESPONSE_PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextExpireTime = currTime + nextResponseTime;
|
||||||
|
if (nextExpireTime >= currCpu->responseTime) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +310,6 @@ STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID,
|
||||||
} else {
|
} else {
|
||||||
currCpu->responseID = OS_INVALID_VALUE;
|
currCpu->responseID = OS_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
currCpu->responseTime = nextExpireTime;
|
currCpu->responseTime = nextExpireTime;
|
||||||
HalClockTickTimerReload(nextResponseTime);
|
HalClockTickTimerReload(nextResponseTime);
|
||||||
|
|
||||||
|
@ -335,18 +321,61 @@ STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID,
|
||||||
|
UINT64 taskEndTime, UINT32 oldResponseID)
|
||||||
|
{
|
||||||
|
UINT64 nextExpireTime = OsGetNextExpireTime(startTime);
|
||||||
|
Percpu *currCpu = OsPercpuGet();
|
||||||
|
UINT64 nextResponseTime;
|
||||||
|
BOOL isTimeSlice = FALSE;
|
||||||
|
|
||||||
|
currCpu->schedFlag &= ~INT_PEND_TICK;
|
||||||
|
if (currCpu->responseID == oldResponseID) {
|
||||||
|
/* This time has expired, and the next time the theory has expired is infinite */
|
||||||
|
currCpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The current thread's time slice has been consumed, but the current system lock task cannot
|
||||||
|
* trigger the schedule to release the CPU
|
||||||
|
*/
|
||||||
|
if ((nextExpireTime > taskEndTime) && ((nextExpireTime - taskEndTime) > OS_SCHED_MINI_PERIOD)) {
|
||||||
|
nextExpireTime = taskEndTime;
|
||||||
|
isTimeSlice = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((currCpu->responseTime > nextExpireTime) &&
|
||||||
|
((currCpu->responseTime - nextExpireTime) >= OS_TICK_RESPONSE_PRECISION)) {
|
||||||
|
nextResponseTime = nextExpireTime - startTime;
|
||||||
|
if (nextResponseTime > g_schedTickMaxResponseTime) {
|
||||||
|
nextResponseTime = g_schedTickMaxResponseTime;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* There is no point earlier than the current expiration date */
|
||||||
|
currCpu->tickStartTime = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OsSchedTickReload(currCpu, nextResponseTime, responseID, isTimeSlice);
|
||||||
|
}
|
||||||
|
|
||||||
VOID OsSchedUpdateExpireTime(UINT64 startTime)
|
VOID OsSchedUpdateExpireTime(UINT64 startTime)
|
||||||
{
|
{
|
||||||
UINT64 endTime;
|
UINT64 endTime;
|
||||||
|
Percpu *cpu = OsPercpuGet();
|
||||||
LosTaskCB *runTask = OsCurrTaskGet();
|
LosTaskCB *runTask = OsCurrTaskGet();
|
||||||
|
|
||||||
|
if (!OS_SCHEDULER_ACTIVE || OS_INT_ACTIVE) {
|
||||||
|
cpu->schedFlag |= INT_PEND_TICK;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (runTask->policy == LOS_SCHED_RR) {
|
if (runTask->policy == LOS_SCHED_RR) {
|
||||||
LOS_SpinLock(&g_taskSpin);
|
LOS_SpinLock(&g_taskSpin);
|
||||||
INT32 timeSlice = (runTask->timeSlice <= OS_TIME_SLICE_MIN) ? runTask->initTimeSlice : runTask->timeSlice;
|
INT32 timeSlice = (runTask->timeSlice <= OS_TIME_SLICE_MIN) ? runTask->initTimeSlice : runTask->timeSlice;
|
||||||
LOS_SpinUnlock(&g_taskSpin);
|
LOS_SpinUnlock(&g_taskSpin);
|
||||||
endTime = startTime + timeSlice;
|
endTime = startTime + timeSlice;
|
||||||
} else {
|
} else {
|
||||||
endTime = OS_SCHED_MAX_RESPONSE_TIME;
|
endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION;
|
||||||
}
|
}
|
||||||
|
|
||||||
OsSchedSetNextExpireTime(startTime, runTask->taskID, endTime, runTask->taskID);
|
OsSchedSetNextExpireTime(startTime, runTask->taskID, endTime, runTask->taskID);
|
||||||
|
@ -737,20 +766,23 @@ VOID OsSchedTick(VOID)
|
||||||
Sched *sched = g_sched;
|
Sched *sched = g_sched;
|
||||||
Percpu *currCpu = OsPercpuGet();
|
Percpu *currCpu = OsPercpuGet();
|
||||||
BOOL needSched = FALSE;
|
BOOL needSched = FALSE;
|
||||||
|
LosTaskCB *runTask = OsCurrTaskGet();
|
||||||
|
|
||||||
|
currCpu->tickStartTime = runTask->irqStartTime;
|
||||||
if (currCpu->responseID == OS_INVALID_VALUE) {
|
if (currCpu->responseID == OS_INVALID_VALUE) {
|
||||||
if (sched->swtmrScan != NULL) {
|
if (sched->swtmrScan != NULL) {
|
||||||
(VOID)sched->swtmrScan();
|
(VOID)sched->swtmrScan();
|
||||||
}
|
}
|
||||||
|
|
||||||
needSched = sched->taskScan();
|
needSched = sched->taskScan();
|
||||||
currCpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
|
||||||
|
|
||||||
if (needSched) {
|
if (needSched) {
|
||||||
LOS_MpSchedule(OS_MP_CPU_ALL);
|
LOS_MpSchedule(OS_MP_CPU_ALL);
|
||||||
currCpu->schedFlag = INT_PEND_RESCH;
|
currCpu->schedFlag |= INT_PEND_RESCH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
currCpu->schedFlag |= INT_PEND_TICK;
|
||||||
|
currCpu->responseTime = OS_SCHED_MAX_RESPONSE_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask)
|
VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask)
|
||||||
|
@ -996,7 +1028,7 @@ STATIC VOID OsSchedTaskSwicth(LosTaskCB *runTask, LosTaskCB *newTask)
|
||||||
if (newTask->policy == LOS_SCHED_RR) {
|
if (newTask->policy == LOS_SCHED_RR) {
|
||||||
endTime = newTask->startTime + newTask->timeSlice;
|
endTime = newTask->startTime + newTask->timeSlice;
|
||||||
} else {
|
} else {
|
||||||
endTime = OS_SCHED_MAX_RESPONSE_TIME;
|
endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION;
|
||||||
}
|
}
|
||||||
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, endTime, runTask->taskID);
|
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, endTime, runTask->taskID);
|
||||||
|
|
||||||
|
@ -1017,11 +1049,11 @@ VOID OsSchedIrqEndCheckNeedSched(VOID)
|
||||||
|
|
||||||
OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle());
|
OsTimeSliceUpdate(runTask, OsGetCurrSchedTimeCycle());
|
||||||
if (runTask->timeSlice <= OS_TIME_SLICE_MIN) {
|
if (runTask->timeSlice <= OS_TIME_SLICE_MIN) {
|
||||||
percpu->schedFlag = INT_PEND_RESCH;
|
percpu->schedFlag |= INT_PEND_RESCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OsPreemptable() && (percpu->schedFlag == INT_PEND_RESCH)) {
|
if (OsPreemptable() && (percpu->schedFlag & INT_PEND_RESCH)) {
|
||||||
percpu->schedFlag = INT_NO_RESCH;
|
percpu->schedFlag &= ~INT_PEND_RESCH;
|
||||||
|
|
||||||
LOS_SpinLock(&g_taskSpin);
|
LOS_SpinLock(&g_taskSpin);
|
||||||
|
|
||||||
|
@ -1037,7 +1069,9 @@ VOID OsSchedIrqEndCheckNeedSched(VOID)
|
||||||
LOS_SpinUnlock(&g_taskSpin);
|
LOS_SpinUnlock(&g_taskSpin);
|
||||||
}
|
}
|
||||||
|
|
||||||
OsSchedUpdateExpireTime(runTask->startTime);
|
if (percpu->schedFlag & INT_PEND_TICK) {
|
||||||
|
OsSchedUpdateExpireTime(runTask->startTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID OsSchedResched(VOID)
|
VOID OsSchedResched(VOID)
|
||||||
|
@ -1049,7 +1083,7 @@ VOID OsSchedResched(VOID)
|
||||||
LOS_ASSERT(OsPercpuGet()->taskLockCnt == 0);
|
LOS_ASSERT(OsPercpuGet()->taskLockCnt == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OsPercpuGet()->schedFlag = INT_NO_RESCH;
|
OsPercpuGet()->schedFlag &= ~INT_PEND_RESCH;
|
||||||
LosTaskCB *runTask = OsCurrTaskGet();
|
LosTaskCB *runTask = OsCurrTaskGet();
|
||||||
LosTaskCB *newTask = OsGetTopTask();
|
LosTaskCB *newTask = OsGetTopTask();
|
||||||
if (runTask == newTask) {
|
if (runTask == newTask) {
|
||||||
|
@ -1065,7 +1099,7 @@ VOID LOS_Schedule(VOID)
|
||||||
LosTaskCB *runTask = OsCurrTaskGet();
|
LosTaskCB *runTask = OsCurrTaskGet();
|
||||||
|
|
||||||
if (OS_INT_ACTIVE) {
|
if (OS_INT_ACTIVE) {
|
||||||
OsPercpuGet()->schedFlag = INT_PEND_RESCH;
|
OsPercpuGet()->schedFlag |= INT_PEND_RESCH;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
#include "los_sched_pri.h"
|
#include "los_sched_pri.h"
|
||||||
#include "los_mp.h"
|
#include "los_mp.h"
|
||||||
|
|
||||||
|
|
||||||
UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
|
UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
|
||||||
{
|
{
|
||||||
LOS_ListInit(&sortLinkHeader->sortLink);
|
LOS_ListInit(&sortLinkHeader->sortLink);
|
||||||
|
@ -87,39 +86,19 @@ VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortL
|
||||||
|
|
||||||
STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime)
|
STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime)
|
||||||
{
|
{
|
||||||
UINT64 expirTime = 0;
|
|
||||||
UINT64 nextExpirTime = 0;
|
|
||||||
LOS_DL_LIST *head = &sortHeader->sortLink;
|
LOS_DL_LIST *head = &sortHeader->sortLink;
|
||||||
LOS_DL_LIST *list = head->pstNext;
|
LOS_DL_LIST *list = head->pstNext;
|
||||||
|
|
||||||
if (LOS_ListEmpty(head)) {
|
if (LOS_ListEmpty(head)) {
|
||||||
return (UINT64)-1;
|
return OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode);
|
||||||
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode);
|
if (listSorted->responseTime <= (startTime + OS_TICK_RESPONSE_PRECISION)) {
|
||||||
if (listSorted->responseTime <= startTime) {
|
return startTime + OS_TICK_RESPONSE_PRECISION;
|
||||||
expirTime = startTime;
|
|
||||||
list = list->pstNext;
|
|
||||||
} else {
|
|
||||||
nextExpirTime = listSorted->responseTime;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (list != head);
|
|
||||||
|
|
||||||
if (expirTime == 0) {
|
|
||||||
return nextExpirTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextExpirTime == 0) {
|
return listSorted->responseTime;
|
||||||
return expirTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nextExpirTime - expirTime) <= OS_US_PER_TICK) {
|
|
||||||
return nextExpirTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
return expirTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC Percpu *OsFindIdleCpu(UINT16 *idleCpuID)
|
STATIC Percpu *OsFindIdleCpu(UINT16 *idleCpuID)
|
|
@ -276,6 +276,7 @@ typedef struct tagSwTmrCtrl {
|
||||||
that handles software timer timeout is called */
|
that handles software timer timeout is called */
|
||||||
SWTMR_PROC_FUNC pfnHandler; /**< Callback function that handles software timer timeout */
|
SWTMR_PROC_FUNC pfnHandler; /**< Callback function that handles software timer timeout */
|
||||||
UINT32 uwOwnerPid; /** Owner of this software timer */
|
UINT32 uwOwnerPid; /** Owner of this software timer */
|
||||||
|
UINT64 startTime; /**< Software timer start time */
|
||||||
} SWTMR_CTRL_S;
|
} SWTMR_CTRL_S;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -97,6 +97,22 @@ extern UINT32 __heap_end;
|
||||||
#define LOSCFG_BASE_CORE_TICK_PER_SECOND 1000 /* 1ms per tick */
|
#define LOSCFG_BASE_CORE_TICK_PER_SECOND 1000 /* 1ms per tick */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup los_config
|
||||||
|
* Minimum response error accuracy of tick interrupts, number of ticks in one second
|
||||||
|
*/
|
||||||
|
#ifndef LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI
|
||||||
|
#define LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI 1000UL /* 1ms */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (LOSCFG_BASE_CORE_TICK_PER_SECOND > LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI)
|
||||||
|
#error "LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI must be greater than LOSCFG_BASE_CORE_TICK_PER_SECOND"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI > 1000UL)
|
||||||
|
#error "LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI must be less than or equal to 1000"
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup los_config
|
* @ingroup los_config
|
||||||
* Microseconds of adjtime in one second
|
* Microseconds of adjtime in one second
|
||||||
|
|
Loading…
Reference in New Issue