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:
@@ -939,7 +939,37 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSystemProcessCreate(VOID)
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 prio, UINT16 policy)
|
||||
INT32 OsSchedulerParamCheck(UINT16 policy, BOOL isThread, const LosSchedParam *param)
|
||||
{
|
||||
if (param == NULL) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if ((policy == LOS_SCHED_RR) || (isThread && (policy == LOS_SCHED_FIFO))) {
|
||||
if ((param->priority < OS_PROCESS_PRIORITY_HIGHEST) ||
|
||||
(param->priority > OS_PROCESS_PRIORITY_LOWEST)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
if (policy == LOS_SCHED_DEADLINE) {
|
||||
if ((param->runTimeUs < OS_SCHED_EDF_MIN_RUNTIME) || (param->runTimeUs >= param->deadlineUs)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
if ((param->deadlineUs < OS_SCHED_EDF_MIN_DEADLINE) || (param->deadlineUs > OS_SCHED_EDF_MAX_DEADLINE)) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
if (param->periodUs < param->deadlineUs) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
STATIC INLINE INT32 ProcessSchedulerParamCheck(INT32 which, INT32 pid, UINT16 policy, const LosSchedParam *param)
|
||||
{
|
||||
if (OS_PID_CHECK_INVALID(pid)) {
|
||||
return LOS_EINVAL;
|
||||
@@ -949,19 +979,11 @@ STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 p
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (prio > OS_PROCESS_PRIORITY_LOWEST) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
if (policy != LOS_SCHED_RR) {
|
||||
return LOS_EINVAL;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
return OsSchedulerParamCheck(policy, FALSE, param);
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_SECURITY_CAPABILITY
|
||||
STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedParam *param, UINT16 prio)
|
||||
STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedParam *param, UINT16 policy, UINT16 prio)
|
||||
{
|
||||
LosProcessCB *runProcess = OsCurrProcessGet();
|
||||
|
||||
@@ -971,7 +993,7 @@ STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedPa
|
||||
}
|
||||
|
||||
/* user mode process can reduce the priority of itself */
|
||||
if ((runProcess->processID == processCB->processID) && (prio > param->basePrio)) {
|
||||
if ((runProcess->processID == processCB->processID) && (policy == LOS_SCHED_RR) && (prio > param->basePrio)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -983,12 +1005,13 @@ STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedPa
|
||||
}
|
||||
#endif
|
||||
|
||||
LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy)
|
||||
LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 policy, const LosSchedParam *schedParam)
|
||||
{
|
||||
SchedParam param = { 0 };
|
||||
BOOL needSched = FALSE;
|
||||
UINT32 intSave;
|
||||
|
||||
INT32 ret = OsProcessSchedlerParamCheck(which, pid, prio, policy);
|
||||
INT32 ret = ProcessSchedulerParamCheck(which, pid, policy, schedParam);
|
||||
if (ret != LOS_OK) {
|
||||
return -ret;
|
||||
}
|
||||
@@ -996,22 +1019,45 @@ LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio
|
||||
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (OsProcessIsInactive(processCB)) {
|
||||
ret = LOS_ESRCH;
|
||||
goto EXIT;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return -LOS_ESRCH;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_SECURITY_CAPABILITY
|
||||
if (!OsProcessCapPermitCheck(processCB, ¶m, prio)) {
|
||||
ret = LOS_EPERM;
|
||||
goto EXIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
LosTaskCB *taskCB = processCB->threadGroup;
|
||||
taskCB->ops->schedParamGet(taskCB, ¶m);
|
||||
param.basePrio = prio;
|
||||
|
||||
BOOL needSched = taskCB->ops->schedParamModify(taskCB, ¶m);
|
||||
#ifdef LOSCFG_SECURITY_CAPABILITY
|
||||
if (!OsProcessCapPermitCheck(processCB, ¶m, policy, schedParam->priority)) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return -LOS_EPERM;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (param.policy != policy) {
|
||||
if (policy == LOS_SCHED_DEADLINE) { /* HPF -> EDF */
|
||||
if (processCB->threadNumber > 1) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return -LOS_EPERM;
|
||||
}
|
||||
OsSchedParamInit(taskCB, policy, NULL, schedParam);
|
||||
needSched = TRUE;
|
||||
goto TO_SCHED;
|
||||
} else if (param.policy == LOS_SCHED_DEADLINE) { /* EDF -> HPF */
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return -LOS_EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
if (policy == LOS_SCHED_DEADLINE) {
|
||||
param.runTimeUs = schedParam->runTimeUs;
|
||||
param.deadlineUs = schedParam->deadlineUs;
|
||||
param.periodUs = schedParam->periodUs;
|
||||
} else {
|
||||
param.basePrio = schedParam->priority;
|
||||
}
|
||||
needSched = taskCB->ops->schedParamModify(taskCB, ¶m);
|
||||
|
||||
TO_SCHED:
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
LOS_MpSchedule(OS_MP_CPU_ALL);
|
||||
@@ -1019,25 +1065,26 @@ LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio
|
||||
LOS_Schedule();
|
||||
}
|
||||
return LOS_OK;
|
||||
|
||||
EXIT:
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return -ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT INT32 LOS_SetProcessScheduler(INT32 pid, UINT16 policy, UINT16 prio)
|
||||
LITE_OS_SEC_TEXT INT32 LOS_SetProcessScheduler(INT32 pid, UINT16 policy, const LosSchedParam *schedParam)
|
||||
{
|
||||
return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, prio, policy);
|
||||
return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, policy, schedParam);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT INT32 LOS_GetProcessScheduler(INT32 pid)
|
||||
LITE_OS_SEC_TEXT INT32 LOS_GetProcessScheduler(INT32 pid, INT32 *policy, LosSchedParam *schedParam)
|
||||
{
|
||||
UINT32 intSave;
|
||||
SchedParam param = { 0 };
|
||||
|
||||
if (OS_PID_CHECK_INVALID(pid)) {
|
||||
return -LOS_EINVAL;
|
||||
}
|
||||
|
||||
if ((policy == NULL) && (schedParam == NULL)) {
|
||||
return -LOS_EINVAL;
|
||||
}
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
|
||||
if (OsProcessIsUnused(processCB)) {
|
||||
@@ -1045,14 +1092,48 @@ LITE_OS_SEC_TEXT INT32 LOS_GetProcessScheduler(INT32 pid)
|
||||
return -LOS_ESRCH;
|
||||
}
|
||||
|
||||
LosTaskCB *taskCB = processCB->threadGroup;
|
||||
taskCB->ops->schedParamGet(taskCB, ¶m);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
return LOS_SCHED_RR;
|
||||
if (policy != NULL) {
|
||||
if (param.policy == LOS_SCHED_FIFO) {
|
||||
*policy = LOS_SCHED_RR;
|
||||
} else {
|
||||
*policy = param.policy;
|
||||
}
|
||||
}
|
||||
|
||||
if (schedParam != NULL) {
|
||||
if (param.policy == LOS_SCHED_DEADLINE) {
|
||||
schedParam->runTimeUs = param.runTimeUs;
|
||||
schedParam->deadlineUs = param.deadlineUs;
|
||||
schedParam->periodUs = param.periodUs;
|
||||
} else {
|
||||
schedParam->priority = param.basePrio;
|
||||
}
|
||||
}
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT INT32 LOS_SetProcessPriority(INT32 pid, UINT16 prio)
|
||||
LITE_OS_SEC_TEXT INT32 LOS_SetProcessPriority(INT32 pid, INT32 prio)
|
||||
{
|
||||
return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, prio, LOS_GetProcessScheduler(pid));
|
||||
INT32 ret;
|
||||
INT32 policy;
|
||||
LosSchedParam param = {
|
||||
.priority = prio,
|
||||
};
|
||||
|
||||
ret = LOS_GetProcessScheduler(pid, &policy, NULL);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (policy == LOS_SCHED_DEADLINE) {
|
||||
return -LOS_EINVAL;
|
||||
}
|
||||
|
||||
return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, (UINT16)policy, ¶m);
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid)
|
||||
@@ -1079,6 +1160,11 @@ LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid)
|
||||
LosTaskCB *taskCB = processCB->threadGroup;
|
||||
taskCB->ops->schedParamGet(taskCB, ¶m);
|
||||
|
||||
if (param.policy == LOS_SCHED_DEADLINE) {
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return -LOS_EINVAL;
|
||||
}
|
||||
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
return param.basePrio;
|
||||
}
|
||||
@@ -1850,6 +1936,38 @@ STATIC UINT32 OsCopyUser(LosProcessCB *childCB, LosProcessCB *parentCB)
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
STATIC VOID GetCopyTaskParam(LosProcessCB *childProcessCB, UINTPTR entry, UINT32 size,
|
||||
TSK_INIT_PARAM_S *taskParam, SchedParam *param)
|
||||
{
|
||||
UINT32 intSave;
|
||||
LosTaskCB *runTask = OsCurrTaskGet();
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (OsProcessIsUserMode(childProcessCB)) {
|
||||
taskParam->pfnTaskEntry = runTask->taskEntry;
|
||||
taskParam->uwStackSize = runTask->stackSize;
|
||||
taskParam->userParam.userArea = runTask->userArea;
|
||||
taskParam->userParam.userMapBase = runTask->userMapBase;
|
||||
taskParam->userParam.userMapSize = runTask->userMapSize;
|
||||
} else {
|
||||
taskParam->pfnTaskEntry = (TSK_ENTRY_FUNC)entry;
|
||||
taskParam->uwStackSize = size;
|
||||
}
|
||||
if (runTask->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
|
||||
taskParam->uwResved = LOS_TASK_ATTR_JOINABLE;
|
||||
}
|
||||
|
||||
runTask->ops->schedParamGet(runTask, param);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
taskParam->policy = param->policy;
|
||||
taskParam->runTimeUs = param->runTimeUs;
|
||||
taskParam->deadlineUs = param->deadlineUs;
|
||||
taskParam->periodUs = param->periodUs;
|
||||
taskParam->usTaskPrio = param->priority;
|
||||
taskParam->processID = (UINTPTR)childProcessCB;
|
||||
}
|
||||
|
||||
STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size)
|
||||
{
|
||||
LosTaskCB *runTask = OsCurrTaskGet();
|
||||
@@ -1857,28 +1975,8 @@ STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR
|
||||
UINT32 ret, taskID, intSave;
|
||||
SchedParam param = { 0 };
|
||||
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (OsProcessIsUserMode(childProcessCB)) {
|
||||
taskParam.pfnTaskEntry = runTask->taskEntry;
|
||||
taskParam.uwStackSize = runTask->stackSize;
|
||||
taskParam.userParam.userArea = runTask->userArea;
|
||||
taskParam.userParam.userMapBase = runTask->userMapBase;
|
||||
taskParam.userParam.userMapSize = runTask->userMapSize;
|
||||
} else {
|
||||
taskParam.pfnTaskEntry = (TSK_ENTRY_FUNC)entry;
|
||||
taskParam.uwStackSize = size;
|
||||
}
|
||||
if (runTask->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
|
||||
taskParam.uwResved = LOS_TASK_ATTR_JOINABLE;
|
||||
}
|
||||
|
||||
runTask->ops->schedParamGet(runTask, ¶m);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
|
||||
taskParam.pcName = (CHAR *)name;
|
||||
taskParam.policy = param.policy;
|
||||
taskParam.usTaskPrio = param.priority;
|
||||
taskParam.processID = (UINTPTR)childProcessCB;
|
||||
GetCopyTaskParam(childProcessCB, entry, size, &taskParam, ¶m);
|
||||
|
||||
ret = LOS_TaskCreateOnly(&taskID, &taskParam);
|
||||
if (ret != LOS_OK) {
|
||||
|
||||
@@ -543,6 +543,7 @@ STATIC UINT32 TaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam)
|
||||
UINT32 ret;
|
||||
UINT32 numCount;
|
||||
SchedParam schedParam = { 0 };
|
||||
LosSchedParam initSchedParam = {0};
|
||||
UINT16 policy = (initParam->policy == LOS_SCHED_NORMAL) ? LOS_SCHED_RR : initParam->policy;
|
||||
|
||||
TaskCBBaseInit(taskCB, initParam);
|
||||
@@ -553,7 +554,14 @@ STATIC UINT32 TaskCBInit(LosTaskCB *taskCB, const TSK_INIT_PARAM_S *initParam)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = OsSchedParamInit(taskCB, policy, &schedParam, initParam);
|
||||
if (policy == LOS_SCHED_DEADLINE) {
|
||||
initSchedParam.runTimeUs = initParam->runTimeUs;
|
||||
initSchedParam.deadlineUs = initParam->deadlineUs;
|
||||
initSchedParam.periodUs = initParam->periodUs;
|
||||
} else {
|
||||
initSchedParam.priority = initParam->usTaskPrio;
|
||||
}
|
||||
ret = OsSchedParamInit(taskCB, policy, &schedParam, &initSchedParam);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
@@ -1365,6 +1373,8 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsCreateUserTask(UINTPTR processID, TSK_INIT_PARAM_
|
||||
UINT32 taskID;
|
||||
UINT32 ret;
|
||||
UINT32 intSave;
|
||||
INT32 policy;
|
||||
SchedParam param;
|
||||
|
||||
ret = OsCreateUserTaskParamCheck(processID, initParam);
|
||||
if (ret != LOS_OK) {
|
||||
@@ -1373,14 +1383,25 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsCreateUserTask(UINTPTR processID, TSK_INIT_PARAM_
|
||||
|
||||
initParam->uwStackSize = OS_USER_TASK_SYSCALL_STACK_SIZE;
|
||||
initParam->usTaskPrio = OS_TASK_PRIORITY_LOWEST;
|
||||
initParam->policy = LOS_SCHED_RR;
|
||||
if (processID == OS_INVALID_VALUE) {
|
||||
SCHEDULER_LOCK(intSave);
|
||||
LosProcessCB *processCB = OsCurrProcessGet();
|
||||
initParam->processID = (UINTPTR)processCB;
|
||||
initParam->consoleID = processCB->consoleID;
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
ret = LOS_GetProcessScheduler(processCB->processID, &policy, NULL);
|
||||
if (ret != LOS_OK) {
|
||||
return OS_INVALID_VALUE;
|
||||
}
|
||||
initParam->policy = policy;
|
||||
if (policy == LOS_SCHED_DEADLINE) {
|
||||
OsSchedProcessDefaultSchedParamGet((UINT16)policy, ¶m);
|
||||
initParam->runTimeUs = param.runTimeUs;
|
||||
initParam->deadlineUs = param.deadlineUs;
|
||||
initParam->periodUs = param.periodUs;
|
||||
}
|
||||
} else {
|
||||
initParam->policy = LOS_SCHED_RR;
|
||||
initParam->processID = processID;
|
||||
initParam->consoleID = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user