feat: support EDF

方案描述:
1、liteos_a调度框架支持EDF调度算法,默认优先调度EDF策略的任务
2、用户态musl_c库适配新增调度算法,同步修改相关接口以支持用户态创建EDF进程与线程

BREAKING CHANGE:
support EDF对外变更描述:
以下接口支持SCHED_DEADLINE调度策略:
pthread_attr_getschedparam
pthread_attr_setschedparam
pthread_getschedparam
pthread_setschedparam
pthread_create
sched_getscheduler
sched_getparam
sched_setparam
sched_setscheduler

Close:#I6T3P3

Signed-off-by: zhangdengyu <zhangdengyu2@huawei.com>
Change-Id: Ic9fe6896fcae42ae4ee7fe5dfb8e858a6ed19740
This commit is contained in:
zhangdengyu
2023-04-08 22:47:03 +08:00
parent 4ff66c7f40
commit 13f68dcf9c
33 changed files with 2054 additions and 161 deletions

View File

@@ -0,0 +1,403 @@
/*
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_sched_pri.h"
#include "los_task_pri.h"
#include "los_process_pri.h"
#include "los_hook.h"
#include "los_tick_pri.h"
#include "los_sys_pri.h"
STATIC EDFRunqueue g_schedEDF;
STATIC VOID EDFDequeue(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC VOID EDFEnqueue(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC UINT64 EDFWaitTimeGet(LosTaskCB *taskCB);
STATIC UINT32 EDFWait(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 ticks);
STATIC VOID EDFWake(LosTaskCB *resumedTask);
STATIC BOOL EDFSchedParamModify(LosTaskCB *taskCB, const SchedParam *param);
STATIC UINT32 EDFSchedParamGet(const LosTaskCB *taskCB, SchedParam *param);
STATIC UINT32 EDFDelay(LosTaskCB *runTask, UINT64 waitTime);
STATIC VOID EDFYield(LosTaskCB *runTask);
STATIC VOID EDFExit(LosTaskCB *taskCB);
STATIC UINT32 EDFSuspend(LosTaskCB *taskCB);
STATIC UINT32 EDFResume(LosTaskCB *taskCB, BOOL *needSched);
STATIC UINT64 EDFTimeSliceGet(const LosTaskCB *taskCB);
STATIC VOID EDFTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 currTime);
STATIC INT32 EDFParamCompare(const SchedPolicy *sp1, const SchedPolicy *sp2);
STATIC VOID EDFPriorityInheritance(LosTaskCB *owner, const SchedParam *param);
STATIC VOID EDFPriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const SchedParam *param);
const STATIC SchedOps g_deadlineOps = {
.dequeue = EDFDequeue,
.enqueue = EDFEnqueue,
.waitTimeGet = EDFWaitTimeGet,
.wait = EDFWait,
.wake = EDFWake,
.schedParamModify = EDFSchedParamModify,
.schedParamGet = EDFSchedParamGet,
.delay = EDFDelay,
.yield = EDFYield,
.start = EDFDequeue,
.exit = EDFExit,
.suspend = EDFSuspend,
.resume = EDFResume,
.deadlineGet = EDFTimeSliceGet,
.timeSliceUpdate = EDFTimeSliceUpdate,
.schedParamCompare = EDFParamCompare,
.priorityInheritance = EDFPriorityInheritance,
.priorityRestore = EDFPriorityRestore,
};
STATIC VOID EDFTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 currTime)
{
SchedEDF *sched = (SchedEDF *)&taskCB->sp;
LOS_ASSERT(currTime >= taskCB->startTime);
if (taskCB->timeSlice <= 0) {
taskCB->irqUsedTime = 0;
return;
}
INT32 incTime = (currTime - taskCB->startTime - taskCB->irqUsedTime);
LOS_ASSERT(incTime >= 0);
#ifdef LOSCFG_SCHED_EDF_DEBUG
taskCB->schedStat.timeSliceRealTime += incTime;
taskCB->schedStat.allRuntime += (currTime - taskCB->startTime);
#endif
taskCB->timeSlice -= incTime;
taskCB->irqUsedTime = 0;
taskCB->startTime = currTime;
if ((sched->finishTime > currTime) && (taskCB->timeSlice > 0)) {
return;
}
rq->schedFlag |= INT_PEND_RESCH;
if (sched->finishTime <= currTime) {
#ifdef LOSCFG_SCHED_EDF_DEBUG
EDFDebugRecord((UINTPTR *)taskCB, sched->finishTime);
#endif
taskCB->timeSlice = 0;
PrintExcInfo("EDF task %u is timeout, runTime: %d us period: %llu us\n", taskCB->taskID,
(INT32)OS_SYS_CYCLE_TO_US((UINT64)sched->runTime), OS_SYS_CYCLE_TO_US(sched->period));
}
}
STATIC UINT64 EDFTimeSliceGet(const LosTaskCB *taskCB)
{
SchedEDF *sched = (SchedEDF *)&taskCB->sp;
UINT64 endTime = taskCB->startTime + taskCB->timeSlice;
return (endTime > sched->finishTime) ? sched->finishTime : endTime;
}
STATIC VOID DeadlineQueueInsert(EDFRunqueue *rq, LosTaskCB *taskCB)
{
LOS_DL_LIST *root = &rq->root;
if (LOS_ListEmpty(root)) {
LOS_ListTailInsert(root, &taskCB->pendList);
return;
}
LOS_DL_LIST *list = root->pstNext;
do {
LosTaskCB *readyTask = LOS_DL_LIST_ENTRY(list, LosTaskCB, pendList);
if (EDFParamCompare(&readyTask->sp, &taskCB->sp) > 0) {
LOS_ListHeadInsert(list, &taskCB->pendList);
return;
}
list = list->pstNext;
} while (list != root);
LOS_ListHeadInsert(list, &taskCB->pendList);
}
STATIC VOID EDFEnqueue(SchedRunqueue *rq, LosTaskCB *taskCB)
{
LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY));
EDFRunqueue *erq = rq->edfRunqueue;
SchedEDF *sched = (SchedEDF *)&taskCB->sp;
if (taskCB->timeSlice <= 0) {
#ifdef LOSCFG_SCHED_EDF_DEBUG
UINT64 oldFinish = sched->finishTime;
#endif
UINT64 currTime = OsGetCurrSchedTimeCycle();
if (sched->flags == EDF_INIT) {
sched->finishTime = currTime;
} else if (sched->flags != EDF_NEXT_PERIOD) {
/* The start time of the next period */
sched->finishTime = (sched->finishTime - sched->deadline) + sched->period;
}
/* Calculate the start time of the next period */
while (1) {
/* The deadline of the next period */
UINT64 finishTime = sched->finishTime + sched->deadline;
if ((finishTime <= currTime) || ((sched->finishTime + sched->runTime) > finishTime)) {
/* This period cannot meet the minimum running time, so it is migrated to the next period */
sched->finishTime += sched->period;
continue;
}
break;
}
if (sched->finishTime > currTime) {
/* Wait for the next period to start */
LOS_ListTailInsert(&erq->waitList, &taskCB->pendList);
taskCB->waitTime = OS_SCHED_MAX_RESPONSE_TIME;
if (!OsTaskIsRunning(taskCB)) {
OsSchedTimeoutQueueAdd(taskCB, sched->finishTime);
}
#ifdef LOSCFG_SCHED_EDF_DEBUG
if (oldFinish != sched->finishTime) {
EDFDebugRecord((UINTPTR *)taskCB, oldFinish);
taskCB->schedStat.allRuntime = 0;
taskCB->schedStat.timeSliceRealTime = 0;
taskCB->schedStat.pendTime = 0;
}
#endif
taskCB->taskStatus |= OS_TASK_STATUS_PEND_TIME;
sched->flags = EDF_NEXT_PERIOD;
return;
}
sched->finishTime += sched->deadline;
taskCB->timeSlice = sched->runTime;
sched->flags = EDF_UNUSED;
}
DeadlineQueueInsert(erq, taskCB);
taskCB->taskStatus &= ~(OS_TASK_STATUS_BLOCKED | OS_TASK_STATUS_TIMEOUT);
taskCB->taskStatus |= OS_TASK_STATUS_READY;
}
STATIC VOID EDFDequeue(SchedRunqueue *rq, LosTaskCB *taskCB)
{
(VOID)rq;
LOS_ListDelete(&taskCB->pendList);
taskCB->taskStatus &= ~OS_TASK_STATUS_READY;
}
STATIC VOID EDFExit(LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
EDFDequeue(OsSchedRunqueue(), taskCB);
} else if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) {
LOS_ListDelete(&taskCB->pendList);
taskCB->taskStatus &= ~OS_TASK_STATUS_PENDING;
}
if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) {
OsSchedTimeoutQueueDelete(taskCB);
taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME);
}
}
STATIC VOID EDFYield(LosTaskCB *runTask)
{
SchedRunqueue *rq = OsSchedRunqueue();
runTask->timeSlice = 0;
runTask->startTime = OsGetCurrSchedTimeCycle();
EDFEnqueue(rq, runTask);
OsSchedResched();
}
STATIC UINT32 EDFDelay(LosTaskCB *runTask, UINT64 waitTime)
{
runTask->taskStatus |= OS_TASK_STATUS_DELAY;
runTask->waitTime = waitTime;
OsSchedResched();
return LOS_OK;
}
STATIC UINT64 EDFWaitTimeGet(LosTaskCB *taskCB)
{
const SchedEDF *sched = (const SchedEDF *)&taskCB->sp;
if (sched->flags != EDF_WAIT_FOREVER) {
taskCB->waitTime += taskCB->startTime;
}
return (taskCB->waitTime >= sched->finishTime) ? sched->finishTime : taskCB->waitTime;
}
STATIC UINT32 EDFWait(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 ticks)
{
SchedEDF *sched = (SchedEDF *)&runTask->sp;
runTask->taskStatus |= (OS_TASK_STATUS_PENDING | OS_TASK_STATUS_PEND_TIME);
LOS_ListTailInsert(list, &runTask->pendList);
if (ticks != LOS_WAIT_FOREVER) {
runTask->waitTime = OS_SCHED_TICK_TO_CYCLE(ticks);
} else {
sched->flags = EDF_WAIT_FOREVER;
runTask->waitTime = OS_SCHED_MAX_RESPONSE_TIME;
}
if (OsPreemptableInSched()) {
OsSchedResched();
if (runTask->taskStatus & OS_TASK_STATUS_TIMEOUT) {
runTask->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;
return LOS_ERRNO_TSK_TIMEOUT;
}
}
return LOS_OK;
}
STATIC VOID EDFWake(LosTaskCB *resumedTask)
{
LOS_ListDelete(&resumedTask->pendList);
resumedTask->taskStatus &= ~OS_TASK_STATUS_PENDING;
if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) {
OsSchedTimeoutQueueDelete(resumedTask);
resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
}
if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPENDED)) {
#ifdef LOSCFG_SCHED_EDF_DEBUG
resumedTask->schedStat.pendTime += OsGetCurrSchedTimeCycle() - resumedTask->startTime;
resumedTask->schedStat.pendCount++;
#endif
EDFEnqueue(OsSchedRunqueue(), resumedTask);
}
}
STATIC BOOL EDFSchedParamModify(LosTaskCB *taskCB, const SchedParam *param)
{
SchedRunqueue *rq = OsSchedRunqueue();
SchedEDF *sched = (SchedEDF *)&taskCB->sp;
taskCB->timeSlice = 0;
sched->runTime = (INT32)OS_SYS_US_TO_CYCLE(param->runTimeUs);
sched->period = OS_SYS_US_TO_CYCLE(param->periodUs);
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
EDFDequeue(rq, taskCB);
sched->deadline = OS_SYS_US_TO_CYCLE(param->deadlineUs);
EDFEnqueue(rq, taskCB);
return TRUE;
}
sched->deadline = OS_SYS_US_TO_CYCLE(param->deadlineUs);
if (taskCB->taskStatus & OS_TASK_STATUS_INIT) {
EDFEnqueue(rq, taskCB);
return TRUE;
}
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
return TRUE;
}
return FALSE;
}
STATIC UINT32 EDFSchedParamGet(const LosTaskCB *taskCB, SchedParam *param)
{
SchedEDF *sched = (SchedEDF *)&taskCB->sp;
param->policy = sched->policy;
param->runTimeUs = (INT32)OS_SYS_CYCLE_TO_US((UINT64)sched->runTime);
param->deadlineUs = OS_SYS_CYCLE_TO_US(sched->deadline);
param->periodUs = OS_SYS_CYCLE_TO_US(sched->period);
return LOS_OK;
}
STATIC UINT32 EDFSuspend(LosTaskCB *taskCB)
{
return LOS_EOPNOTSUPP;
}
STATIC UINT32 EDFResume(LosTaskCB *taskCB, BOOL *needSched)
{
return LOS_EOPNOTSUPP;
}
STATIC INT32 EDFParamCompare(const SchedPolicy *sp1, const SchedPolicy *sp2)
{
const SchedEDF *param1 = (const SchedEDF *)sp1;
const SchedEDF *param2 = (const SchedEDF *)sp2;
return (INT32)(param1->finishTime - param2->finishTime);
}
STATIC VOID EDFPriorityInheritance(LosTaskCB *owner, const SchedParam *param)
{
(VOID)owner;
(VOID)param;
}
STATIC VOID EDFPriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const SchedParam *param)
{
(VOID)owner;
(VOID)list;
(VOID)param;
}
UINT32 EDFTaskSchedParamInit(LosTaskCB *taskCB, UINT16 policy,
const SchedParam *parentParam,
const LosSchedParam *param)
{
(VOID)parentParam;
SchedEDF *sched = (SchedEDF *)&taskCB->sp;
sched->flags = EDF_INIT;
sched->policy = policy;
sched->runTime = (INT32)OS_SYS_US_TO_CYCLE((UINT64)param->runTimeUs);
sched->deadline = OS_SYS_US_TO_CYCLE(param->deadlineUs);
sched->period = OS_SYS_US_TO_CYCLE(param->periodUs);
sched->finishTime = 0;
taskCB->timeSlice = 0;
taskCB->ops = &g_deadlineOps;
return LOS_OK;
}
VOID EDFProcessDefaultSchedParamGet(SchedParam *param)
{
param->runTimeUs = OS_SCHED_EDF_MIN_RUNTIME;
param->deadlineUs = OS_SCHED_EDF_MAX_DEADLINE;
param->periodUs = param->deadlineUs;
}
VOID EDFSchedPolicyInit(SchedRunqueue *rq)
{
if (ArchCurrCpuid() > 0) {
rq->edfRunqueue = &g_schedEDF;
return;
}
EDFRunqueue *erq = &g_schedEDF;
erq->period = OS_SCHED_MAX_RESPONSE_TIME;
LOS_ListInit(&erq->root);
LOS_ListInit(&erq->waitList);
rq->edfRunqueue = erq;
}

View File

@@ -48,6 +48,7 @@ STATIC VOID IdlePriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const
const STATIC SchedOps g_idleOps = {
.dequeue = IdleDequeue,
.enqueue = IdleEnqueue,
.waitTimeGet = NULL,
.wait = IdleWait,
.wake = IdleWake,
.schedParamModify = NULL,

View File

@@ -47,6 +47,7 @@ STATIC HPFRunqueue g_schedHPF;
STATIC VOID HPFDequeue(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC VOID HPFEnqueue(SchedRunqueue *rq, LosTaskCB *taskCB);
STATIC UINT64 HPFWaitTimeGet(LosTaskCB *taskCB);
STATIC UINT32 HPFWait(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 ticks);
STATIC VOID HPFWake(LosTaskCB *resumedTask);
STATIC BOOL HPFSchedParamModify(LosTaskCB *taskCB, const SchedParam *param);
@@ -66,6 +67,7 @@ STATIC VOID HPFPriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const
const STATIC SchedOps g_priorityOps = {
.dequeue = HPFDequeue,
.enqueue = HPFEnqueue,
.waitTimeGet = HPFWaitTimeGet,
.wait = HPFWait,
.wake = HPFWake,
.schedParamModify = HPFSchedParamModify,
@@ -94,7 +96,7 @@ STATIC VOID HPFTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 curr
if (sched->policy == LOS_SCHED_RR) {
taskCB->timeSlice -= incTime;
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_HPF_DEBUG
taskCB->schedStat.timeSliceRealTime += incTime;
#endif
}
@@ -107,7 +109,7 @@ STATIC VOID HPFTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 curr
rq->schedFlag |= INT_PEND_RESCH;
}
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_HPF_DEBUG
taskCB->schedStat.allRuntime += incTime;
#endif
}
@@ -215,7 +217,7 @@ STATIC INLINE VOID PriQueInsert(HPFRunqueue *rq, LosTaskCB *taskCB)
sched->initTimeSlice = TimeSliceCalculate(rq, sched->basePrio, sched->priority);
taskCB->timeSlice = sched->initTimeSlice;
PriQueTailInsert(rq, sched->basePrio, &taskCB->pendList, sched->priority);
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_HPF_DEBUG
taskCB->schedStat.timeSliceTime = taskCB->schedStat.timeSliceRealTime;
taskCB->schedStat.timeSliceCount++;
#endif
@@ -244,7 +246,7 @@ STATIC INLINE VOID PriQueInsert(HPFRunqueue *rq, LosTaskCB *taskCB)
STATIC VOID HPFEnqueue(SchedRunqueue *rq, LosTaskCB *taskCB)
{
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_HPF_DEBUG
if (!(taskCB->taskStatus & OS_TASK_STATUS_RUNNING)) {
taskCB->startTime = OsGetCurrSchedTimeCycle();
}
@@ -301,6 +303,12 @@ STATIC UINT32 HPFDelay(LosTaskCB *runTask, UINT64 waitTime)
return LOS_OK;
}
STATIC UINT64 HPFWaitTimeGet(LosTaskCB *taskCB)
{
taskCB->waitTime += taskCB->startTime;
return taskCB->waitTime;
}
STATIC UINT32 HPFWait(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 ticks)
{
runTask->taskStatus |= OS_TASK_STATUS_PENDING;
@@ -333,7 +341,7 @@ STATIC VOID HPFWake(LosTaskCB *resumedTask)
}
if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPENDED)) {
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_HPF_DEBUG
resumedTask->schedStat.pendTime += OsGetCurrSchedTimeCycle() - resumedTask->startTime;
resumedTask->schedStat.pendCount++;
#endif
@@ -508,13 +516,13 @@ STATIC VOID HPFPriorityRestore(LosTaskCB *owner, const LOS_DL_LIST *list, const
VOID HPFTaskSchedParamInit(LosTaskCB *taskCB, UINT16 policy,
const SchedParam *parentParam,
const TSK_INIT_PARAM_S *param)
const LosSchedParam *param)
{
SchedHPF *sched = (SchedHPF *)&taskCB->sp;
sched->policy = policy;
if (param != NULL) {
sched->priority = param->usTaskPrio;
sched->priority = param->priority;
} else {
sched->priority = parentParam->priority;
}

View File

@@ -102,15 +102,26 @@ VOID OsSchedExpireTimeUpdate(VOID)
STATIC INLINE VOID SchedTimeoutTaskWake(SchedRunqueue *rq, UINT64 currTime, LosTaskCB *taskCB, BOOL *needSched)
{
#ifndef LOSCFG_SCHED_DEBUG
(VOID)currTime;
#endif
LOS_SpinLock(&g_taskSpin);
if (OsSchedPolicyIsEDF(taskCB)) {
SchedEDF *sched = (SchedEDF *)&taskCB->sp;
if (sched->finishTime <= currTime) {
if (taskCB->timeSlice >= 0) {
PrintExcInfo("EDF task: %u name: %s is timeout, timeout for %llu us.\n",
taskCB->taskID, taskCB->taskName, OS_SYS_CYCLE_TO_US(currTime - sched->finishTime));
}
taskCB->timeSlice = 0;
}
if (sched->flags == EDF_WAIT_FOREVER) {
taskCB->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
sched->flags = EDF_UNUSED;
}
}
UINT16 tempStatus = taskCB->taskStatus;
if (tempStatus & (OS_TASK_STATUS_PENDING | OS_TASK_STATUS_DELAY)) {
if (tempStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) {
taskCB->taskStatus &= ~(OS_TASK_STATUS_PENDING | OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY);
if (tempStatus & OS_TASK_STATUS_PENDING) {
if (tempStatus & OS_TASK_STATUS_PEND_TIME) {
taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
LOS_ListDelete(&taskCB->pendList);
taskCB->taskMux = NULL;
@@ -118,7 +129,7 @@ STATIC INLINE VOID SchedTimeoutTaskWake(SchedRunqueue *rq, UINT64 currTime, LosT
}
if (!(tempStatus & OS_TASK_STATUS_SUSPENDED)) {
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_HPF_DEBUG
taskCB->schedStat.pendTime += currTime - taskCB->startTime;
taskCB->schedStat.pendCount++;
#endif
@@ -212,8 +223,10 @@ VOID OsSchedRunqueueIdleInit(LosTaskCB *idleTask)
UINT32 OsSchedInit(VOID)
{
for (UINT16 cpuId = 0; cpuId < LOSCFG_KERNEL_CORE_NUM; cpuId++) {
HPFSchedPolicyInit(OsSchedRunqueueByID(cpuId));
for (UINT16 cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
SchedRunqueue *rq = OsSchedRunqueueByID(cpuid);
EDFSchedPolicyInit(rq);
HPFSchedPolicyInit(rq);
}
#ifdef LOSCFG_SCHED_TICK_DEBUG
@@ -247,13 +260,15 @@ INT32 OsSchedParamCompare(const LosTaskCB *task1, const LosTaskCB *task2)
return 0;
}
UINT32 OsSchedParamInit(LosTaskCB *taskCB, UINT16 policy, const SchedParam *parentParam, const TSK_INIT_PARAM_S *param)
UINT32 OsSchedParamInit(LosTaskCB *taskCB, UINT16 policy, const SchedParam *parentParam, const LosSchedParam *param)
{
switch (policy) {
case LOS_SCHED_FIFO:
case LOS_SCHED_RR:
HPFTaskSchedParamInit(taskCB, policy, parentParam, param);
break;
case LOS_SCHED_DEADLINE:
return EDFTaskSchedParamInit(taskCB, policy, parentParam, param);
case LOS_SCHED_IDLE:
IdleTaskSchedParamInit(taskCB);
break;
@@ -271,6 +286,9 @@ VOID OsSchedProcessDefaultSchedParamGet(UINT16 policy, SchedParam *param)
case LOS_SCHED_RR:
HPFProcessDefaultSchedParamGet(param);
break;
case LOS_SCHED_DEADLINE:
EDFProcessDefaultSchedParamGet(param);
break;
case LOS_SCHED_IDLE:
default:
PRINT_ERR("Invalid process-level scheduling policy, %u\n", policy);
@@ -281,12 +299,19 @@ VOID OsSchedProcessDefaultSchedParamGet(UINT16 policy, SchedParam *param)
STATIC LosTaskCB *TopTaskGet(SchedRunqueue *rq)
{
LosTaskCB *newTask = HPFRunqueueTopTaskGet(rq->hpfRunqueue);
if (newTask == NULL) {
newTask = rq->idleTask;
LosTaskCB *newTask = EDFRunqueueTopTaskGet(rq->edfRunqueue);
if (newTask != NULL) {
goto FIND;
}
newTask = HPFRunqueueTopTaskGet(rq->hpfRunqueue);
if (newTask != NULL) {
goto FIND;
}
newTask = rq->idleTask;
FIND:
newTask->ops->start(rq, newTask);
return newTask;
}
@@ -387,7 +412,7 @@ STATIC VOID SchedTaskSwitch(SchedRunqueue *rq, LosTaskCB *runTask, LosTaskCB *ne
OsCpupCycleEndStart(runTask, newTask);
#endif
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_HPF_DEBUG
UINT64 waitStartTime = newTask->startTime;
#endif
if (runTask->taskStatus & OS_TASK_STATUS_READY) {
@@ -400,14 +425,14 @@ STATIC VOID SchedTaskSwitch(SchedRunqueue *rq, LosTaskCB *runTask, LosTaskCB *ne
runTask->ops->timeSliceUpdate(rq, runTask, newTask->startTime);
if (runTask->taskStatus & (OS_TASK_STATUS_PEND_TIME | OS_TASK_STATUS_DELAY)) {
OsSchedTimeoutQueueAdd(runTask, runTask->startTime + runTask->waitTime);
OsSchedTimeoutQueueAdd(runTask, runTask->ops->waitTimeGet(runTask));
}
}
UINT64 deadline = newTask->ops->deadlineGet(newTask);
SchedNextExpireTimeSet(newTask->taskID, deadline, runTask->taskID);
#ifdef LOSCFG_SCHED_DEBUG
#ifdef LOSCFG_SCHED_HPF_DEBUG
newTask->schedStat.waitSchedTime += newTask->startTime - waitStartTime;
newTask->schedStat.waitSchedCount++;
runTask->schedStat.runTime = runTask->schedStat.allRuntime;

View File

@@ -99,6 +99,7 @@ UINT32 OsShellShowTickResponse(VOID)
}
#endif
#ifdef LOSCFG_SCHED_HPF_DEBUG
STATIC VOID SchedDataGet(const LosTaskCB *taskCB, UINT64 *runTime, UINT64 *timeSlice,
UINT64 *pendTime, UINT64 *schedWait)
{
@@ -128,6 +129,7 @@ UINT32 OsShellShowSchedStatistics(VOID)
UINT32 taskLinkNum[LOSCFG_KERNEL_CORE_NUM];
UINT32 intSave;
LosTaskCB task;
SchedEDF *sched = NULL;
SCHEDULER_LOCK(intSave);
for (UINT16 cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) {
@@ -150,6 +152,12 @@ UINT32 OsShellShowSchedStatistics(VOID)
continue;
}
sched = (SchedEDF *)&taskCB->sp;
if (sched->policy == LOS_SCHED_DEADLINE) {
SCHEDULER_UNLOCK(intSave);
continue;
}
(VOID)memcpy_s(&task, sizeof(LosTaskCB), taskCB, sizeof(LosTaskCB));
SCHEDULER_UNLOCK(intSave);
@@ -170,3 +178,168 @@ UINT32 OsShellShowSchedStatistics(VOID)
}
#endif
#ifdef LOSCFG_SCHED_EDF_DEBUG
#define EDF_DEBUG_NODE 20
typedef struct {
UINT32 tid;
INT32 runTimeUs;
UINT64 deadlineUs;
UINT64 periodUs;
UINT64 startTime;
UINT64 finishTime;
UINT64 nextfinishTime;
UINT64 timeSliceUnused;
UINT64 timeSliceRealTime;
UINT64 allRuntime;
UINT64 pendTime;
} EDFDebug;
STATIC EDFDebug g_edfNode[EDF_DEBUG_NODE];
STATIC INT32 g_edfNodePointer = 0;
VOID EDFDebugRecord(UINTPTR *task, UINT64 oldFinish)
{
LosTaskCB *taskCB = (LosTaskCB *)task;
SchedEDF *sched = (SchedEDF *)&taskCB->sp;
SchedParam param;
// when print edf info, will stop record
if (g_edfNodePointer == (EDF_DEBUG_NODE + 1)) {
return;
}
taskCB->ops->schedParamGet(taskCB, &param);
g_edfNode[g_edfNodePointer].tid = taskCB->taskID;
g_edfNode[g_edfNodePointer].runTimeUs =param.runTimeUs;
g_edfNode[g_edfNodePointer].deadlineUs =param.deadlineUs;
g_edfNode[g_edfNodePointer].periodUs =param.periodUs;
g_edfNode[g_edfNodePointer].startTime = taskCB->startTime;
if (taskCB->timeSlice <= 0) {
taskCB->irqUsedTime = 0;
g_edfNode[g_edfNodePointer].timeSliceUnused = 0;
} else {
g_edfNode[g_edfNodePointer].timeSliceUnused = taskCB->timeSlice;
}
g_edfNode[g_edfNodePointer].finishTime = oldFinish;
g_edfNode[g_edfNodePointer].nextfinishTime = sched->finishTime;
g_edfNode[g_edfNodePointer].timeSliceRealTime = taskCB->schedStat.timeSliceRealTime;
g_edfNode[g_edfNodePointer].allRuntime = taskCB->schedStat.allRuntime;
g_edfNode[g_edfNodePointer].pendTime = taskCB->schedStat.pendTime;
g_edfNodePointer++;
if (g_edfNodePointer == EDF_DEBUG_NODE) {
g_edfNodePointer = 0;
}
}
STATIC VOID EDFInfoPrint(int idx)
{
INT32 runTimeUs;
UINT64 deadlineUs;
UINT64 periodUs;
UINT64 startTime;
UINT64 timeSlice;
UINT64 finishTime;
UINT64 nextfinishTime;
UINT64 pendTime;
UINT64 allRuntime;
UINT64 timeSliceRealTime;
CHAR *status = NULL;
startTime = OS_SYS_CYCLE_TO_US(g_edfNode[idx].startTime);
timeSlice = OS_SYS_CYCLE_TO_US(g_edfNode[idx].timeSliceUnused);
finishTime = OS_SYS_CYCLE_TO_US(g_edfNode[idx].finishTime);
nextfinishTime = OS_SYS_CYCLE_TO_US(g_edfNode[idx].nextfinishTime);
pendTime = OS_SYS_CYCLE_TO_US(g_edfNode[idx].pendTime);
allRuntime = OS_SYS_CYCLE_TO_US(g_edfNode[idx].allRuntime);
timeSliceRealTime = OS_SYS_CYCLE_TO_US(g_edfNode[idx].timeSliceRealTime);
runTimeUs = g_edfNode[idx].runTimeUs;
deadlineUs = g_edfNode[idx].deadlineUs;
periodUs = g_edfNode[idx].periodUs;
if (timeSlice > 0) {
status = "TIMEOUT";
} else if (nextfinishTime == finishTime) {
status = "NEXT PERIOD";
} else {
status = "WAIT RUN";
}
PRINTK("%4u%9d%9llu%9llu%12llu%12llu%12llu%9llu%9llu%9llu%9llu %-12s\n",
g_edfNode[idx].tid, runTimeUs, deadlineUs, periodUs,
startTime, finishTime, nextfinishTime, allRuntime, timeSliceRealTime,
timeSlice, pendTime, status);
}
VOID OsEDFDebugPrint(VOID)
{
INT32 max;
UINT32 intSave;
INT32 i;
SCHEDULER_LOCK(intSave);
max = g_edfNodePointer;
g_edfNodePointer = EDF_DEBUG_NODE + 1;
SCHEDULER_UNLOCK(intSave);
PRINTK("\r\nlast %d sched is: (in microsecond)\r\n", EDF_DEBUG_NODE);
PRINTK(" TID RunTime Deadline Period StartTime "
"CurPeriod NextPeriod AllRun RealRun TimeOut WaitTime Status\n");
for (i = max; i < EDF_DEBUG_NODE; i++) {
EDFInfoPrint(i);
}
for (i = 0; i < max; i++) {
EDFInfoPrint(i);
}
SCHEDULER_LOCK(intSave);
g_edfNodePointer = max;
SCHEDULER_UNLOCK(intSave);
}
UINT32 OsShellShowEdfSchedStatistics(VOID)
{
UINT32 intSave;
LosTaskCB task;
UINT64 curTime;
UINT64 deadline;
UINT64 finishTime;
SchedEDF *sched = NULL;
PRINTK("Now Alive EDF Thread:\n");
PRINTK("TID CurTime DeadTime FinishTime taskName\n");
for (UINT32 tid = 0; tid < g_taskMaxNum; tid++) {
LosTaskCB *taskCB = g_taskCBArray + tid;
SCHEDULER_LOCK(intSave);
if (OsTaskIsUnused(taskCB)) {
SCHEDULER_UNLOCK(intSave);
continue;
}
sched = (SchedEDF *)&taskCB->sp;
if (sched->policy != LOS_SCHED_DEADLINE) {
SCHEDULER_UNLOCK(intSave);
continue;
}
(VOID)memcpy_s(&task, sizeof(LosTaskCB), taskCB, sizeof(LosTaskCB));
curTime = OS_SYS_CYCLE_TO_US(HalClockGetCycles());
finishTime = OS_SYS_CYCLE_TO_US(sched->finishTime);
deadline = OS_SYS_CYCLE_TO_US(taskCB->ops->deadlineGet(taskCB));
SCHEDULER_UNLOCK(intSave);
PRINTK("%3u%15llu%15llu%15llu %-32s\n",
task.taskID, curTime, deadline, finishTime, task.taskName);
}
OsEDFDebugPrint();
return LOS_OK;
}
#endif
#endif