feat: 调度tick响应时间计算优化

1.tick timer与调度进一步剥离
2.性能敏感函数内敛化

Signed-off-by: zhushengle <zhushengle@huawei.com>
Change-Id: Icf62f002fa57d452cdd23a4c7b5e6610e2785f8e
This commit is contained in:
zhushengle 2022-01-18 20:50:35 +08:00
parent 8e356c99c7
commit f47da44b39
9 changed files with 108 additions and 150 deletions

View File

@ -46,7 +46,7 @@ extern VOID HalClockInit(VOID);
extern UINT64 HalClockGetCycles(VOID);
extern VOID HalDelayUs(UINT32 usecs);
extern UINT32 HalClockGetTickTimerCycles(VOID);
extern VOID HalClockTickTimerReload(UINT64 cycles);
extern UINT64 HalClockTickTimerReload(UINT64 cycles);
extern UINT32 HrtimersInit(VOID);
extern VOID HrtimerClockIrqClear(VOID);

View File

@ -31,7 +31,6 @@
#include "los_hw_pri.h"
#include "los_tick_pri.h"
#include "los_sched_pri.h"
#include "los_sys_pri.h"
#include "gic_common.h"
@ -139,11 +138,6 @@ LITE_OS_SEC_TEXT_INIT VOID HalClockInit(VOID)
LITE_OS_SEC_TEXT_INIT VOID HalClockStart(VOID)
{
UINT32 ret = OsSchedSetTickTimerType(64); /* 64 bit tick timer */
if (ret != LOS_OK) {
return;
}
HalIrqUnmask(OS_TICK_INT_NUM);
/* triggle the first tick */
@ -175,7 +169,7 @@ UINT32 HalClockGetTickTimerCycles(VOID)
return (UINT32)((cval > cycles) ? (cval - cycles) : 0);
}
VOID HalClockTickTimerReload(UINT64 cycles)
UINT64 HalClockTickTimerReload(UINT64 cycles)
{
HalIrqMask(OS_TICK_INT_NUM);
HalIrqClear(OS_TICK_INT_NUM);
@ -185,4 +179,5 @@ VOID HalClockTickTimerReload(UINT64 cycles)
TimerCtlWrite(1);
HalIrqUnmask(OS_TICK_INT_NUM);
return cycles;
}

View File

@ -246,7 +246,7 @@ STATIC INLINE VOID OsWakePendTimeSwtmr(Percpu *cpu, UINT64 currTime, SWTMR_CTRL_
LITE_OS_SEC_TEXT VOID OsSwtmrScan(VOID)
{
Percpu *cpu = OsPercpuGet();
SortLinkAttribute* swtmrSortLink = &OsPercpuGet()->swtmrSortLink;
SortLinkAttribute* swtmrSortLink = &cpu->swtmrSortLink;
LOS_DL_LIST *listObject = &swtmrSortLink->sortLink;
/*
@ -283,6 +283,33 @@ LITE_OS_SEC_TEXT VOID OsSwtmrScan(VOID)
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
}
LITE_OS_SEC_TEXT VOID OsSwtmrResponseTimeReset(UINT64 startTime)
{
UINT32 intSave;
Percpu *cpu = OsPercpuGet();
SortLinkAttribute* swtmrSortLink = &cpu->swtmrSortLink;
LOS_DL_LIST *listHead = &swtmrSortLink->sortLink;
LOS_DL_LIST *listNext = listHead->pstNext;
LOS_SpinLock(&cpu->swtmrSortLinkSpin);
while (listNext != listHead) {
SortLinkList *sortList = LOS_DL_LIST_ENTRY(listNext, SortLinkList, sortLinkNode);
OsDeleteNodeSortLink(swtmrSortLink, sortList);
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
SWTMR_LOCK(intSave);
swtmr->startTime = startTime;
OsSwtmrStart(startTime, swtmr);
SWTMR_UNLOCK(intSave);
LOS_SpinLock(&cpu->swtmrSortLinkSpin);
listNext = listNext->pstNext;
}
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
}
/*
* Description: Get next timeout
* Return : Count of the Timer list

View File

@ -52,15 +52,9 @@ extern "C" {
extern UINT32 g_taskScheduled;
typedef BOOL (*SchedScan)(VOID);
extern UINT64 g_sysSchedStartTime;
STATIC INLINE UINT64 OsGetCurrSchedTimeCycle(VOID)
{
if (g_sysSchedStartTime != OS_64BIT_MAX) {
return (HalClockGetCycles() - g_sysSchedStartTime);
}
return 0;
return HalClockGetCycles();
}
STATIC INLINE VOID OsSchedIrqUpdateUsedTime(VOID)
@ -156,8 +150,6 @@ STATIC INLINE VOID OsCpuSchedUnlock(Percpu *cpu, UINT32 intSave)
LOS_IntRestore(intSave);
}
extern UINT32 OsSchedSetTickTimerType(UINT32 timerType);
extern VOID OsSchedSetIdleTaskSchedParam(LosTaskCB *idleTask);
extern UINT32 OsSchedSwtmrScanRegister(SchedScan func);

View File

@ -64,9 +64,31 @@ typedef struct {
#define SET_SORTLIST_VALUE(sortList, value) (((SortLinkList *)(sortList))->responseTime = (value))
#define GET_SORTLIST_VALUE(sortList) (((SortLinkList *)(sortList))->responseTime)
extern UINT64 OsGetNextExpireTime(UINT64 startTime);
STATIC INLINE VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
{
LOS_ListDelete(&sortList->sortLinkNode);
SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME);
sortLinkHeader->nodeNum--;
}
STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime, UINT32 tickPrecision)
{
LOS_DL_LIST *head = &sortHeader->sortLink;
LOS_DL_LIST *list = head->pstNext;
if (LOS_ListEmpty(head)) {
return OS_SORT_LINK_INVALID_TIME - tickPrecision;
}
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode);
if (listSorted->responseTime <= (startTime + tickPrecision)) {
return startTime + tickPrecision;
}
return listSorted->responseTime;
}
extern UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader);
extern VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList);
extern VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type);
extern VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type);
extern UINT32 OsSortLinkGetTargetExpireTime(const SortLinkList *targetSortList);

View File

@ -104,6 +104,7 @@ extern VOID OsSwtmrScan(VOID);
extern UINT32 OsSwtmrInit(VOID);
extern VOID OsSwtmrTask(VOID);
extern VOID OsSwtmrRecycle(UINT32 processID);
extern VOID OsSwtmrResponseTimeReset(UINT64 startTime);
extern SPIN_LOCK_S g_swtmrSpin;
#ifdef __cplusplus
#if __cplusplus

View File

@ -32,6 +32,7 @@
#include "los_sched_pri.h"
#include "los_hw_pri.h"
#include "los_task_pri.h"
#include "los_swtmr_pri.h"
#include "los_process_pri.h"
#include "los_arch_mmu.h"
#include "los_hook.h"
@ -75,8 +76,6 @@ typedef struct {
} Sched;
STATIC Sched *g_sched = NULL;
STATIC UINT64 g_schedTickMaxResponseTime;
UINT64 g_sysSchedStartTime = OS_64BIT_MAX;
#ifdef LOSCFG_SCHED_TICK_DEBUG
#define OS_SCHED_DEBUG_DATA_NUM 1000
@ -237,30 +236,6 @@ UINT32 OsShellShowSchedParam(VOID)
}
#endif
UINT32 OsSchedSetTickTimerType(UINT32 timerType)
{
switch (timerType) {
case 32: /* 32 bit timer */
g_schedTickMaxResponseTime = OS_32BIT_MAX;
break;
case 64: /* 64 bit timer */
g_schedTickMaxResponseTime = OS_64BIT_MAX;
break;
default:
PRINT_ERR("Unsupported Tick Timer type, The system only supports 32 and 64 bit tick timers\n");
return LOS_NOK;
}
return LOS_OK;
}
STATIC VOID OsSchedSetStartTime(UINT64 currCycle)
{
if (g_sysSchedStartTime == OS_64BIT_MAX) {
g_sysSchedStartTime = currCycle;
}
}
STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime)
{
LOS_ASSERT(currTime >= taskCB->startTime);
@ -283,54 +258,29 @@ STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime)
#endif
}
STATIC INLINE VOID OsSchedTickReload(Percpu *currCpu, UINT64 nextResponseTime, UINT32 responseID, BOOL isTimeSlice)
STATIC INLINE UINT64 GetNextExpireTime(Percpu *cpu, UINT64 startTime, UINT32 tickPrecision)
{
UINT64 currTime, nextExpireTime;
UINT32 usedTime;
SortLinkAttribute *taskHeader = &cpu->taskSortLink;
SortLinkAttribute *swtmrHeader = &cpu->swtmrSortLink;
currTime = OsGetCurrSchedTimeCycle();
if (currCpu->tickStartTime != 0) {
usedTime = currTime - currCpu->tickStartTime;
currCpu->tickStartTime = 0;
} else {
usedTime = 0;
}
LOS_SpinLock(&cpu->taskSortLinkSpin);
UINT64 taskExpireTime = OsGetSortLinkNextExpireTime(taskHeader, startTime, tickPrecision);
LOS_SpinUnlock(&cpu->taskSortLinkSpin);
if ((nextResponseTime > usedTime) && ((nextResponseTime - usedTime) > OS_TICK_RESPONSE_PRECISION)) {
nextResponseTime -= usedTime;
} else {
nextResponseTime = OS_TICK_RESPONSE_PRECISION;
}
LOS_SpinLock(&cpu->swtmrSortLinkSpin);
UINT64 swtmrExpireTime = OsGetSortLinkNextExpireTime(swtmrHeader, startTime, tickPrecision);
LOS_SpinUnlock(&cpu->swtmrSortLinkSpin);
nextExpireTime = currTime + nextResponseTime;
if (nextExpireTime >= currCpu->responseTime) {
return;
}
if (isTimeSlice) {
/* The expiration time of the current system is the thread's slice expiration time */
currCpu->responseID = responseID;
} else {
currCpu->responseID = OS_INVALID_VALUE;
}
currCpu->responseTime = nextExpireTime;
HalClockTickTimerReload(nextResponseTime);
#ifdef LOSCFG_SCHED_TICK_DEBUG
SchedTickDebug *schedDebug = &g_schedTickDebug[ArchCurrCpuid()];
if (schedDebug->index < OS_SCHED_DEBUG_DATA_NUM) {
schedDebug->setTickCount++;
}
#endif
return (taskExpireTime < swtmrExpireTime) ? taskExpireTime : swtmrExpireTime;
}
STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID,
UINT64 taskEndTime, UINT32 oldResponseID)
{
UINT64 nextExpireTime = OsGetNextExpireTime(startTime);
Percpu *currCpu = OsPercpuGet();
UINT64 nextResponseTime;
UINT64 nextResponseTime = 0;
BOOL isTimeSlice = FALSE;
UINT64 nextExpireTime = GetNextExpireTime(currCpu, startTime, OS_TICK_RESPONSE_PRECISION);
currCpu->schedFlag &= ~INT_PEND_TICK;
if (currCpu->responseID == oldResponseID) {
@ -346,19 +296,35 @@ STATIC INLINE VOID OsSchedSetNextExpireTime(UINT64 startTime, UINT32 responseID,
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;
if ((currCpu->responseTime <= nextExpireTime) ||
((currCpu->responseTime - nextExpireTime) < OS_TICK_RESPONSE_PRECISION)) {
return;
}
OsSchedTickReload(currCpu, nextResponseTime, responseID, isTimeSlice);
UINT64 currTime = OsGetCurrSchedTimeCycle();
if (nextExpireTime >= currTime) {
nextResponseTime = nextExpireTime - currTime;
}
if (nextResponseTime < OS_TICK_RESPONSE_PRECISION) {
nextResponseTime = OS_TICK_RESPONSE_PRECISION;
}
if (isTimeSlice) {
/* The expiration time of the current system is the thread's slice expiration time */
currCpu->responseID = responseID;
} else {
currCpu->responseID = OS_INVALID_VALUE;
}
currCpu->responseTime = currTime + HalClockTickTimerReload(nextResponseTime);
#ifdef LOSCFG_SCHED_TICK_DEBUG
SchedTickDebug *schedDebug = &g_schedTickDebug[ArchCurrCpuid()];
if (schedDebug->index < OS_SCHED_DEBUG_DATA_NUM) {
schedDebug->setTickCount++;
}
#endif
}
VOID OsSchedUpdateExpireTime(UINT64 startTime)
@ -843,9 +809,7 @@ VOID OsSchedTick(VOID)
Sched *sched = g_sched;
Percpu *currCpu = OsPercpuGet();
BOOL needSched = FALSE;
LosTaskCB *runTask = OsCurrTaskGet();
currCpu->tickStartTime = runTask->irqStartTime;
if (currCpu->responseID == OS_INVALID_VALUE) {
if (sched->swtmrScan != NULL) {
(VOID)sched->swtmrScan();
@ -970,6 +934,8 @@ VOID OsSchedStart(VOID)
UINT32 cpuid = ArchCurrCpuid();
UINT32 intSave;
PRINTK("cpu %d entering scheduler\n", cpuid);
SCHEDULER_LOCK(intSave);
if (cpuid == 0) {
@ -983,9 +949,6 @@ VOID OsSchedStart(VOID)
newProcess->processStatus |= OS_PROCESS_STATUS_RUNNING;
newProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(newProcess->processStatus);
OsSchedSetStartTime(HalClockGetCycles());
newTask->startTime = OsGetCurrSchedTimeCycle();
#ifdef LOSCFG_KERNEL_SMP
/*
* attention: current cpu needs to be set, in case first task deletion
@ -996,13 +959,15 @@ VOID OsSchedStart(VOID)
OsCurrTaskSet((VOID *)newTask);
newTask->startTime = OsGetCurrSchedTimeCycle();
OsSwtmrResponseTimeReset(newTask->startTime);
/* System start schedule */
OS_SCHEDULER_SET(cpuid);
OsPercpuGet()->responseID = OS_INVALID;
OsSchedSetNextExpireTime(newTask->startTime, newTask->taskID, newTask->startTime + newTask->timeSlice, OS_INVALID);
PRINTK("cpu %d entering scheduler\n", cpuid);
OsTaskContextLoad(newTask);
}

View File

@ -77,30 +77,6 @@ STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLin
} while (1);
}
VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
{
LOS_ListDelete(&sortList->sortLinkNode);
SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME);
sortLinkHeader->nodeNum--;
}
STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime)
{
LOS_DL_LIST *head = &sortHeader->sortLink;
LOS_DL_LIST *list = head->pstNext;
if (LOS_ListEmpty(head)) {
return OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION;
}
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode);
if (listSorted->responseTime <= (startTime + OS_TICK_RESPONSE_PRECISION)) {
return startTime + OS_TICK_RESPONSE_PRECISION;
}
return listSorted->responseTime;
}
STATIC Percpu *OsFindIdleCpu(UINT16 *idleCpuID)
{
Percpu *idleCpu = OsPercpuGetByID(0);
@ -127,7 +103,6 @@ STATIC Percpu *OsFindIdleCpu(UINT16 *idleCpuID)
VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type)
{
UINT32 intSave;
Percpu *cpu = NULL;
SortLinkAttribute *sortLinkHeader = NULL;
SPIN_LOCK_S *spinLock = NULL;
@ -150,7 +125,7 @@ VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, Sort
LOS_Panic("Sort link type error : %u\n", type);
}
LOS_SpinLockSave(spinLock, &intSave);
LOS_SpinLock(spinLock);
SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK);
OsAddNode2SortLink(sortLinkHeader, node);
#ifdef LOSCFG_KERNEL_SMP
@ -159,12 +134,11 @@ VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, Sort
LOS_MpSchedule(CPUID_TO_AFFI_MASK(idleCpu));
}
#endif
LOS_SpinUnlockRestore(spinLock, intSave);
LOS_SpinUnlock(spinLock);
}
VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type)
{
UINT32 intSave;
#ifdef LOSCFG_KERNEL_SMP
Percpu *cpu = OsPercpuGetByID(node->cpuid);
#else
@ -183,29 +157,11 @@ VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type)
LOS_Panic("Sort link type error : %u\n", type);
}
LOS_SpinLockSave(spinLock, &intSave);
LOS_SpinLock(spinLock);
if (node->responseTime != OS_SORT_LINK_INVALID_TIME) {
OsDeleteNodeSortLink(sortLinkHeader, node);
}
LOS_SpinUnlockRestore(spinLock, intSave);
}
UINT64 OsGetNextExpireTime(UINT64 startTime)
{
UINT32 intSave;
Percpu *cpu = OsPercpuGet();
SortLinkAttribute *taskHeader = &cpu->taskSortLink;
SortLinkAttribute *swtmrHeader = &cpu->swtmrSortLink;
LOS_SpinLockSave(&cpu->taskSortLinkSpin, &intSave);
UINT64 taskExpirTime = OsGetSortLinkNextExpireTime(taskHeader, startTime);
LOS_SpinUnlockRestore(&cpu->taskSortLinkSpin, intSave);
LOS_SpinLockSave(&cpu->swtmrSortLinkSpin, &intSave);
UINT64 swtmrExpirTime = OsGetSortLinkNextExpireTime(swtmrHeader, startTime);
LOS_SpinUnlockRestore(&cpu->swtmrSortLinkSpin, intSave);
return (taskExpirTime < swtmrExpirTime) ? taskExpirTime : swtmrExpirTime;
LOS_SpinUnlock(spinLock);
}
UINT32 OsSortLinkGetTargetExpireTime(const SortLinkList *targetSortList)

View File

@ -67,7 +67,7 @@ static int Testcase(VOID)
ICUNIT_ASSERT_EQUAL(err, EINVAL, err);
param.sched_priority = 15; // 15, set pthread priority.
ret = sched_setparam(20, &param); // 20, set the param.
ret = sched_setparam(60, &param); // 60, set the param.
err = errno;
ICUNIT_ASSERT_EQUAL(ret, -1, ret);
ICUNIT_ASSERT_EQUAL(err, ESRCH, err);