diff --git a/Kconfig b/Kconfig index c286f28ba88d590422fab033e41d9cd764480bc6..562e352ac3f892b4bd18b3c3c1af46f3d8db79ab 100644 --- a/Kconfig +++ b/Kconfig @@ -235,7 +235,12 @@ config SCHED_DEBUG depends on DEBUG_VERSION help If you wish to build LiteOS with support for sched debug. - +config SCHED_EDF_DEBUG + bool "Enable sched EDF debug Feature" + default n + depends on SCHED_DEBUG + help + If you wish to build LiteOS with support for sched debug. config USER_INIT_DEBUG bool "Enable user init Debug" default n diff --git a/kernel/base/BUILD.gn b/kernel/base/BUILD.gn index 3212a9a3761918c60c4ca409bc83b208352bdb02..45fdb56bd82ea810adc1bfccb4863e29a7c356c8 100644 --- a/kernel/base/BUILD.gn +++ b/kernel/base/BUILD.gn @@ -76,6 +76,7 @@ kernel_module(module_name) { "mp/los_percpu.c", "mp/los_spinlock.c", "om/los_err.c", + "sched/los_deadline.c", "sched/los_idle.c", "sched/los_priority.c", "sched/los_sched.c", diff --git a/kernel/base/core/los_process.c b/kernel/base/core/los_process.c index b72f69944080da9fefae4b5793940c97c11b32a0..724ecf66490759119fdcb02a4d7beaa22b2168e5 100644 --- a/kernel/base/core/los_process.c +++ b/kernel/base/core/los_process.c @@ -939,29 +939,51 @@ 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 (OS_PID_CHECK_INVALID(pid)) { + if (param == NULL) { return LOS_EINVAL; } - if (which != LOS_PRIO_PROCESS) { - 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; } - if (prio > OS_PROCESS_PRIORITY_LOWEST) { + 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; } - if (policy != LOS_SCHED_RR) { + if (which != LOS_PRIO_PROCESS) { 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; } + LosTaskCB *taskCB = processCB->threadGroup; + taskCB->ops->schedParamGet(taskCB, ¶m); + #ifdef LOSCFG_SECURITY_CAPABILITY - if (!OsProcessCapPermitCheck(processCB, ¶m, prio)) { - ret = LOS_EPERM; - goto EXIT; + if (!OsProcessCapPermitCheck(processCB, ¶m, policy, schedParam->priority)) { + SCHEDULER_UNLOCK(intSave); + return -LOS_EPERM; } #endif - LosTaskCB *taskCB = processCB->threadGroup; - taskCB->ops->schedParamGet(taskCB, ¶m); - param.basePrio = prio; + 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; + } + } - BOOL needSched = taskCB->ops->schedParamModify(taskCB, ¶m); + 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,35 +1936,47 @@ STATIC UINT32 OsCopyUser(LosProcessCB *childCB, LosProcessCB *parentCB) return LOS_OK; } -STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size) +STATIC VOID GetCopyTaskParam(LosProcessCB *childProcessCB, UINTPTR entry, UINT32 size, + TSK_INIT_PARAM_S *taskParam, SchedParam *param) { + UINT32 intSave; LosTaskCB *runTask = OsCurrTaskGet(); - TSK_INIT_PARAM_S taskParam = { 0 }; - 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; + 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; + taskParam->pfnTaskEntry = (TSK_ENTRY_FUNC)entry; + taskParam->uwStackSize = size; } if (runTask->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) { - taskParam.uwResved = LOS_TASK_ATTR_JOINABLE; + taskParam->uwResved = LOS_TASK_ATTR_JOINABLE; } - runTask->ops->schedParamGet(runTask, ¶m); + 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(); + TSK_INIT_PARAM_S taskParam = { 0 }; + UINT32 ret, taskID, intSave; + SchedParam param = { 0 }; + 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) { diff --git a/kernel/base/core/los_task.c b/kernel/base/core/los_task.c index 01b1257a0ecec6083b19e207bc6bb1a500702cfa..2bd80726e5e5f5debc0c69e8a262b76f974c4067 100644 --- a/kernel/base/core/los_task.c +++ b/kernel/base/core/los_task.c @@ -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; } diff --git a/kernel/base/include/los_process_pri.h b/kernel/base/include/los_process_pri.h index 1fa5acbb5cffde54bbbe76d4537a090b58e666c6..accd618c1a4806a5a6d41acf81f6ebb89cdd9d0e 100644 --- a/kernel/base/include/los_process_pri.h +++ b/kernel/base/include/los_process_pri.h @@ -535,7 +535,7 @@ extern LosVmSpace *OsExecProcessVmSpaceReplace(LosVmSpace *newSpace, UINTPTR sta extern UINT32 OsExecRecycleAndInit(LosProcessCB *processCB, const CHAR *name, LosVmSpace *oldAspace, UINTPTR oldFiles); extern UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINTPTR mapBase, UINT32 mapSize); extern UINT32 OsSetProcessName(LosProcessCB *processCB, const CHAR *name); -extern INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy); +extern INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 policy, const LosSchedParam *param); extern INT32 OsGetProcessPriority(INT32 which, INT32 pid); extern LosProcessCB *OsGetUserInitProcess(VOID); extern LosProcessCB *OsGetIdleProcess(VOID); @@ -553,6 +553,7 @@ extern VOID OsProcessThreadGroupDestroy(VOID); extern UINT32 OsGetProcessGroupCB(UINT32 pid, UINTPTR *ppgroupLeader); extern LosProcessCB *OsGetDefaultProcessCB(VOID); extern ProcessGroup *OsCreateProcessGroup(LosProcessCB *processCB); +INT32 OsSchedulerParamCheck(UINT16 policy, BOOL isThread, const LosSchedParam *param); #ifdef __cplusplus #if __cplusplus } diff --git a/kernel/base/include/los_sched_pri.h b/kernel/base/include/los_sched_pri.h index 1eae0a62fe63548aec9c3e0ec51785f63df6781a..1bbf007029c14a58034adcbc8624d0b724cba147 100644 --- a/kernel/base/include/los_sched_pri.h +++ b/kernel/base/include/los_sched_pri.h @@ -68,6 +68,10 @@ extern "C" { #define OS_SCHED_TICK_TO_CYCLE(ticks) ((UINT64)ticks * OS_CYCLE_PER_TICK) #define AFFI_MASK_TO_CPUID(mask) ((UINT16)((mask) - 1)) +#define OS_SCHED_EDF_MIN_RUNTIME 100 /* 100 us */ +#define OS_SCHED_EDF_MIN_DEADLINE 400 /* 400 us */ +#define OS_SCHED_EDF_MAX_DEADLINE 5000000 /* 5 s */ + extern UINT32 g_taskScheduled; #define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid())) #define OS_SCHEDULER_ALL_ACTIVE (g_taskScheduled == LOSCFG_KERNEL_CPU_MASK) @@ -98,9 +102,16 @@ typedef struct { UINT32 queueBitmap; } HPFRunqueue; +typedef struct { + LOS_DL_LIST root; + LOS_DL_LIST waitList; + UINT64 period; +} EDFRunqueue; + typedef struct { SortLinkAttribute timeoutQueue; /* task timeout queue */ HPFRunqueue *hpfRunqueue; + EDFRunqueue *edfRunqueue; UINT64 responseTime; /* Response time for current CPU tick interrupts */ UINT32 responseID; /* The response ID of the current CPU tick interrupt */ LosTaskCB *idleTask; /* idle task id */ @@ -212,30 +223,52 @@ STATIC INLINE VOID OsSchedRunqueuePendingSet(VOID) OsSchedRunqueue()->schedFlag |= INT_PEND_RESCH; } -#define LOS_SCHED_NORMAL 0U -#define LOS_SCHED_FIFO 1U -#define LOS_SCHED_RR 2U -#define LOS_SCHED_IDLE 3U +#define LOS_SCHED_NORMAL 0U +#define LOS_SCHED_FIFO 1U +#define LOS_SCHED_RR 2U +#define LOS_SCHED_IDLE 3U +#define LOS_SCHED_DEADLINE 6U typedef struct { UINT16 policy; + /* HPF scheduling parameters */ UINT16 basePrio; UINT16 priority; UINT32 timeSlice; + + /* EDF scheduling parameters */ + INT32 runTimeUs; + UINT32 deadlineUs; + UINT32 periodUs; } SchedParam; typedef struct { UINT16 policy; /* This field must be present for all scheduling policies and must be the first in the structure */ UINT16 basePrio; UINT16 priority; - UINT32 initTimeSlice; - UINT32 priBitmap; /**< Bitmap for recording the change of task priority, the priority can not be greater than 31 */ + UINT32 initTimeSlice; /* cycle */ + UINT32 priBitmap; /* Bitmap for recording the change of task priority, the priority can not be greater than 31 */ } SchedHPF; +#define EDF_UNUSED 0 +#define EDF_NEXT_PERIOD 1 +#define EDF_WAIT_FOREVER 2 +#define EDF_INIT 3 +typedef struct { + UINT16 policy; + UINT16 cpuid; + UINT32 flags; + INT32 runTime; /* cycle */ + UINT64 deadline; /* deadline >> runTime */ + UINT64 period; /* period >= deadline */ + UINT64 finishTime; /* startTime + deadline */ +} SchedEDF; + typedef struct { union { + SchedEDF edf; SchedHPF hpf; - } Policy; + }; } SchedPolicy; typedef struct { @@ -243,6 +276,7 @@ typedef struct { VOID (*enqueue)(SchedRunqueue *rq, LosTaskCB *taskCB); VOID (*start)(SchedRunqueue *rq, LosTaskCB *taskCB); VOID (*exit)(LosTaskCB *taskCB); + UINT64 (*waitTimeGet)(LosTaskCB *taskCB); UINT32 (*wait)(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 timeout); VOID (*wake)(LosTaskCB *taskCB); BOOL (*schedParamModify)(LosTaskCB *taskCB, const SchedParam *param); @@ -463,6 +497,12 @@ STATIC INLINE BOOL OsTaskIsBlocked(const LosTaskCB *taskCB) return ((taskCB->taskStatus & (OS_TASK_STATUS_SUSPENDED | OS_TASK_STATUS_PENDING | OS_TASK_STATUS_DELAY)) != 0); } +STATIC INLINE BOOL OsSchedPolicyIsEDF(const LosTaskCB *taskCB) +{ + const SchedEDF *sched = (const SchedEDF *)&taskCB->sp; + return (sched->policy == LOS_SCHED_DEADLINE); +} + STATIC INLINE LosTaskCB *OsCurrTaskGet(VOID) { return (LosTaskCB *)ArchCurrTaskGet(); @@ -623,6 +663,16 @@ STATIC INLINE VOID SchedTaskUnfreeze(LosTaskCB *taskCB) BOOL OsSchedLimitCheckTime(LosTaskCB *task); #endif +STATIC INLINE LosTaskCB *EDFRunqueueTopTaskGet(EDFRunqueue *rq) +{ + LOS_DL_LIST *root = &rq->root; + if (LOS_ListEmpty(root)) { + return NULL; + } + + return LOS_DL_LIST_ENTRY(LOS_DL_LIST_FIRST(root), LosTaskCB, pendList); +} + STATIC INLINE LosTaskCB *HPFRunqueueTopTaskGet(HPFRunqueue *rq) { LosTaskCB *newTask = NULL; @@ -660,9 +710,16 @@ STATIC INLINE LosTaskCB *HPFRunqueueTopTaskGet(HPFRunqueue *rq) return NULL; } +VOID EDFProcessDefaultSchedParamGet(SchedParam *param); +VOID EDFSchedPolicyInit(SchedRunqueue *rq); +UINT32 EDFTaskSchedParamInit(LosTaskCB *taskCB, UINT16 policy, + const SchedParam *parentParam, + const LosSchedParam *param); + VOID HPFSchedPolicyInit(SchedRunqueue *rq); VOID HPFTaskSchedParamInit(LosTaskCB *taskCB, UINT16 policy, - const SchedParam *parentParam, const TSK_INIT_PARAM_S *param); + const SchedParam *parentParam, + const LosSchedParam *param); VOID HPFProcessDefaultSchedParamGet(SchedParam *param); VOID IdleTaskSchedParamInit(LosTaskCB *taskCB); @@ -670,7 +727,8 @@ VOID IdleTaskSchedParamInit(LosTaskCB *taskCB); INT32 OsSchedParamCompare(const LosTaskCB *task1, const LosTaskCB *task2); VOID OsSchedPriorityInheritance(LosTaskCB *owner, const SchedParam *param); UINT32 OsSchedParamInit(LosTaskCB *taskCB, UINT16 policy, - const SchedParam *parentParam, const TSK_INIT_PARAM_S *param); + const SchedParam *parentParam, + const LosSchedParam *param); VOID OsSchedProcessDefaultSchedParamGet(UINT16 policy, SchedParam *param); VOID OsSchedResponseTimeReset(UINT64 responseTime); diff --git a/kernel/base/include/los_statistics_pri.h b/kernel/base/include/los_statistics_pri.h index 2bfac6042e3ba73b209c27c28223686b3a971618..c1ec0d683f66bc7084ae0a33f7666cbe6b467384 100644 --- a/kernel/base/include/los_statistics_pri.h +++ b/kernel/base/include/los_statistics_pri.h @@ -57,9 +57,11 @@ typedef struct { #ifdef LOSCFG_SCHED_TICK_DEBUG VOID OsSchedDebugRecordData(VOID); UINT32 OsShellShowTickResponse(VOID); -UINT32 OsShellShowSchedStatistics(VOID); UINT32 OsSchedDebugInit(VOID); #endif +UINT32 OsShellShowSchedStatistics(VOID); +UINT32 OsShellShowEdfSchedStatistics(VOID); +VOID EDFDebugRecord(UINTPTR *taskCB, UINT64 oldFinish); #endif #ifdef __cplusplus diff --git a/kernel/base/include/los_sys_pri.h b/kernel/base/include/los_sys_pri.h index e937e3aa886b1045c849fcdfac70483ad458bad6..01a90e8b096d1c59489cea1d0c1603ffca11a9ba 100644 --- a/kernel/base/include/los_sys_pri.h +++ b/kernel/base/include/los_sys_pri.h @@ -101,6 +101,16 @@ extern "C" { */ #define OS_NS_PER_TICK (OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND) +#define OS_US_TO_CYCLE(time, freq) ((((time) / OS_SYS_US_PER_SECOND) * (freq)) + \ + (((time) % OS_SYS_US_PER_SECOND) * (freq) / OS_SYS_US_PER_SECOND)) + +#define OS_SYS_US_TO_CYCLE(time) OS_US_TO_CYCLE((time), OS_SYS_CLOCK) + +#define OS_CYCLE_TO_US(cycle, freq) ((((cycle) / (freq)) * OS_SYS_US_PER_SECOND) + \ + ((cycle) % (freq) * OS_SYS_US_PER_SECOND / (freq))) + +#define OS_SYS_CYCLE_TO_US(cycle) OS_CYCLE_TO_US((cycle), OS_SYS_CLOCK) + /** * @ingroup los_sys * The maximum length of name. diff --git a/kernel/base/misc/task_shellcmd.c b/kernel/base/misc/task_shellcmd.c index 9f8c4a1e88f5dcd3dfca3c47caa90d5fc635b06a..4b78af58e11e65e30fe0580c27bd7a10ba26c4cb 100644 --- a/kernel/base/misc/task_shellcmd.c +++ b/kernel/base/misc/task_shellcmd.c @@ -53,6 +53,9 @@ #include "los_sched_pri.h" #include "los_swtmr_pri.h" #include "los_info_pri.h" +#ifdef LOSCFG_SCHED_DEBUG +#include "los_statistics_pri.h" +#endif #define OS_PROCESS_MEM_INFO 0x2U #undef SHOW @@ -93,6 +96,8 @@ STATIC UINT8 *ConvertSchedPolicyToString(UINT16 policy) return (UINT8 *)"RR"; } else if (policy == LOS_SCHED_FIFO) { return (UINT8 *)"FIFO"; + } else if (policy == LOS_SCHED_DEADLINE) { + return (UINT8 *)"EDF"; } else if (policy == LOS_SCHED_IDLE) { return (UINT8 *)"IDLE"; } @@ -200,12 +205,10 @@ STATIC UINT8 *ConvertTaskStatusToString(UINT16 taskStatus) return (UINT8 *)"Suspended"; } else if (taskStatus & OS_TASK_STATUS_DELAY) { return (UINT8 *)"Delay"; + } else if (taskStatus & OS_TASK_STATUS_PEND_TIME) { + return (UINT8 *)"PendTime"; } else if (taskStatus & OS_TASK_STATUS_PENDING) { - if (taskStatus & OS_TASK_STATUS_PEND_TIME) { - return (UINT8 *)"PendTime"; - } else { - return (UINT8 *)"Pending"; - } + return (UINT8 *)"Pending"; } else if (taskStatus & OS_TASK_STATUS_EXIT) { return (UINT8 *)"Exit"; } @@ -413,11 +416,20 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv) } goto TASK_HELP; #endif +#ifdef LOSCFG_SCHED_HPF_DEBUG } else if (strcmp("-t", argv[0]) == 0) { if (!OsShellShowSchedStatistics()) { return LOS_OK; } goto TASK_HELP; +#endif +#ifdef LOSCFG_SCHED_EDF_DEBUG + } else if (strcmp("-e", argv[0]) == 0) { + if (!OsShellShowEdfSchedStatistics()) { + return LOS_OK; + } + goto TASK_HELP; +#endif #endif } else { goto TASK_HELP; diff --git a/kernel/base/sched/los_deadline.c b/kernel/base/sched/los_deadline.c new file mode 100644 index 0000000000000000000000000000000000000000..ed6d0c20db7c9ac8270991fbcf317d9e454d08c6 --- /dev/null +++ b/kernel/base/sched/los_deadline.c @@ -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; +} diff --git a/kernel/base/sched/los_idle.c b/kernel/base/sched/los_idle.c index d0b3b0edc2a9d2dc3e0503eb19e93fb145fa6e9d..d2538595fc98b1600de8adb1cbc66ae302b185d3 100644 --- a/kernel/base/sched/los_idle.c +++ b/kernel/base/sched/los_idle.c @@ -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, diff --git a/kernel/base/sched/los_priority.c b/kernel/base/sched/los_priority.c index e0db64f27d39b0bec1be4f809c8da0fc5dd89c4f..610ba119b98c23e25304d1b969fbc45102415977 100644 --- a/kernel/base/sched/los_priority.c +++ b/kernel/base/sched/los_priority.c @@ -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; } diff --git a/kernel/base/sched/los_sched.c b/kernel/base/sched/los_sched.c index d5def64756825d5dd4114610765351d1a3713946..10de1b7d54acffedea36bca9bc407d3f8ce9d489 100644 --- a/kernel/base/sched/los_sched.c +++ b/kernel/base/sched/los_sched.c @@ -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); + LosTaskCB *newTask = EDFRunqueueTopTaskGet(rq->edfRunqueue); + if (newTask != NULL) { + goto FIND; + } - if (newTask == NULL) { - newTask = rq->idleTask; + 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; diff --git a/kernel/base/sched/los_statistics.c b/kernel/base/sched/los_statistics.c index 5332fa727b472c950ed4aa51e895405b87f6642e..8494bc6f6367b97d67e0444fb394fd19bab1e9e3 100644 --- a/kernel/base/sched/los_statistics.c +++ b/kernel/base/sched/los_statistics.c @@ -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, ¶m); + 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 diff --git a/kernel/include/los_process.h b/kernel/include/los_process.h index ffb834a4bcf20ad1fd07985a4ec978635c6f17c4..af1a9e2eb9879dce62fb731d5266d071634f86d9 100644 --- a/kernel/include/los_process.h +++ b/kernel/include/los_process.h @@ -47,13 +47,13 @@ extern INT32 LOS_Fork(UINT32 flags, const CHAR *name, const TSK_ENTRY_FUNC entry, UINT32 stackSize); -extern INT32 LOS_SetProcessPriority(INT32 pid, UINT16 prio); +extern INT32 LOS_SetProcessPriority(INT32 pid, INT32 prio); extern INT32 LOS_GetProcessPriority(INT32 pid); -extern INT32 LOS_GetProcessScheduler(INT32 pid); +extern INT32 LOS_GetProcessScheduler(INT32 pid, INT32 *policy, LosSchedParam *schedParam); -extern INT32 LOS_SetProcessScheduler(INT32 pid, UINT16 policy, UINT16 prio); +extern INT32 LOS_SetProcessScheduler(INT32 pid, UINT16 policy, const LosSchedParam *schedParam); extern UINT32 LOS_GetCurrProcessID(VOID); diff --git a/kernel/include/los_task.h b/kernel/include/los_task.h index 4cdda1f1096149d6c0a764a50cf8ee99f418f5fd..73c40eb34e94d5a9bc88984b3e02a220143c3da8 100644 --- a/kernel/include/los_task.h +++ b/kernel/include/los_task.h @@ -514,8 +514,21 @@ typedef struct tagTskInitParam { UINT16 consoleID; /**< The console id of task belongs */ UINTPTR processID; UserTaskParam userParam; + /* edf parameters */ + UINT32 runTimeUs; + UINT64 deadlineUs; + UINT64 periodUs; } TSK_INIT_PARAM_S; +typedef struct { + union { + INT32 priority; + INT32 runTimeUs; + }; + INT32 deadlineUs; + INT32 periodUs; +} LosSchedParam; + /** * @ingroup los_task * Task name length diff --git a/syscall/los_syscall.h b/syscall/los_syscall.h index e45fa9a1fbca06a67f26e9d05d508c3dbafe14ae..e2448a6bb6cc654cc4696ef2f3669e689a59a161 100644 --- a/syscall/los_syscall.h +++ b/syscall/los_syscall.h @@ -72,10 +72,10 @@ extern unsigned int SysGetGroupId(void); extern unsigned int SysGetTid(void); extern void SysSchedYield(int type); extern int SysSchedGetScheduler(int id, int flag); -extern int SysSchedSetScheduler(int id, int policy, int prio, int flag); -extern int SysSchedGetParam(int id, int flag); -extern int SysSchedSetParam(int id, unsigned int prio, int flag); -extern int SysSetProcessPriority(int which, int who, unsigned int prio); +extern int SysSchedSetScheduler(int id, int policy, const LosSchedParam *userParam, int flag); +extern int SysSchedGetParam(int id, LosSchedParam *userParam, int flag); +extern int SysSchedSetParam(int id, const LosSchedParam *userParam, int flag); +extern int SysSetProcessPriority(int which, int who, int prio); extern int SysGetProcessPriority(int which, int who); extern int SysSchedGetPriorityMin(int policy); extern int SysSchedGetPriorityMax(int policy); diff --git a/syscall/process_syscall.c b/syscall/process_syscall.c index 3217b8dd0f3f4b7efc3d11114f5ef087a5afecf7..48c5f81791cfe3f8682a5c2f8ad5d1fddfa6e041 100644 --- a/syscall/process_syscall.c +++ b/syscall/process_syscall.c @@ -60,23 +60,44 @@ static int OsPermissionToCheck(unsigned int pid, unsigned int who) return 0; } -static int OsUserTaskSchedulerSet(unsigned int tid, unsigned short policy, unsigned short priority, bool policyFlag) +static int UserTaskSchedulerCheck(unsigned int tid, int policy, const LosSchedParam *schedParam, bool policyFlag) { int ret; - unsigned int intSave; - bool needSched = false; - SchedParam param = { 0 }; + int processPolicy; if (OS_TID_CHECK_INVALID(tid)) { return EINVAL; } - if (priority > OS_TASK_PRIORITY_LOWEST) { - return EINVAL; + ret = OsSchedulerParamCheck(policy, TRUE, schedParam); + if (ret != 0) { + return ret; } - if ((policy != LOS_SCHED_FIFO) && (policy != LOS_SCHED_RR)) { - return EINVAL; + if (policyFlag) { + ret = LOS_GetProcessScheduler(LOS_GetCurrProcessID(), &processPolicy, NULL); + if (ret < 0) { + return -ret; + } + if ((processPolicy != LOS_SCHED_DEADLINE) && (policy == LOS_SCHED_DEADLINE)) { + return EPERM; + } else if ((processPolicy == LOS_SCHED_DEADLINE) && (policy != LOS_SCHED_DEADLINE)) { + return EPERM; + } + } + return 0; +} + +static int OsUserTaskSchedulerSet(unsigned int tid, int policy, const LosSchedParam *schedParam, bool policyFlag) +{ + int ret; + unsigned int intSave; + bool needSched = false; + SchedParam param = { 0 }; + + ret = UserTaskSchedulerCheck(tid, policy, schedParam, policyFlag); + if (ret != 0) { + return ret; } LosTaskCB *taskCB = OS_TCB_FROM_TID(tid); @@ -88,8 +109,22 @@ static int OsUserTaskSchedulerSet(unsigned int tid, unsigned short policy, unsig } taskCB->ops->schedParamGet(taskCB, ¶m); - param.policy = (policyFlag == true) ? policy : param.policy; - param.priority = priority; + param.policy = (policyFlag == true) ? (UINT16)policy : param.policy; + if ((param.policy == LOS_SCHED_RR) || (param.policy == LOS_SCHED_FIFO)) { + param.priority = schedParam->priority; + } else if (param.policy == LOS_SCHED_DEADLINE) { +#ifdef LOSCFG_SECURITY_CAPABILITY + /* user mode process with privilege of CAP_SCHED_SETPRIORITY can change the priority */ + if (!IsCapPermit(CAP_SCHED_SETPRIORITY)) { + SCHEDULER_UNLOCK(intSave); + return EPERM; + } +#endif + param.runTimeUs = schedParam->runTimeUs; + param.deadlineUs = schedParam->deadlineUs; + param.periodUs = schedParam->periodUs; + } + needSched = taskCB->ops->schedParamModify(taskCB, ¶m); SCHEDULER_UNLOCK(intSave); @@ -113,6 +148,7 @@ int SysSchedGetScheduler(int id, int flag) { unsigned int intSave; SchedParam param = { 0 }; + int policy; int ret; if (flag < 0) { @@ -137,43 +173,57 @@ int SysSchedGetScheduler(int id, int flag) id = (int)LOS_GetCurrProcessID(); } - return LOS_GetProcessScheduler(id); + ret = LOS_GetProcessScheduler(id, &policy, NULL); + if (ret < 0) { + return ret; + } + + return policy; } -int SysSchedSetScheduler(int id, int policy, int prio, int flag) +int SysSchedSetScheduler(int id, int policy, const LosSchedParam *userParam, int flag) { int ret; + LosSchedParam param; + + if (LOS_ArchCopyFromUser(¶m, userParam, sizeof(LosSchedParam)) != 0) { + return -EFAULT; + } if (flag < 0) { - return -OsUserTaskSchedulerSet(id, policy, prio, true); + return -OsUserTaskSchedulerSet(id, policy, ¶m, true); } - if (prio < OS_USER_PROCESS_PRIORITY_HIGHEST) { - return -EINVAL; + if (policy == LOS_SCHED_RR) { +#ifdef LOSCFG_KERNEL_PLIMITS + if (param.priority < OsPidLimitGetPriorityLimit()) { + return -EINVAL; + } +#else + if (param.priority < OS_USER_PROCESS_PRIORITY_HIGHEST) { + return -EINVAL; + } +#endif } if (id == 0) { id = (int)LOS_GetCurrProcessID(); } -#ifdef LOSCFG_KERNEL_PLIMITS - if (prio < OsPidLimitGetPriorityLimit()) { - return -EINVAL; - } -#endif - ret = OsPermissionToCheck(id, LOS_GetCurrProcessID()); if (ret < 0) { return ret; } - return OsSetProcessScheduler(LOS_PRIO_PROCESS, id, prio, policy); + return OsSetProcessScheduler(LOS_PRIO_PROCESS, id, policy, ¶m); } -int SysSchedGetParam(int id, int flag) +int SysSchedGetParam(int id, LosSchedParam *userParam, int flag) { + LosSchedParam schedParam = {0}; SchedParam param = { 0 }; unsigned int intSave; + int ret; if (flag < 0) { if (OS_TID_CHECK_INVALID(id)) { @@ -182,7 +232,7 @@ int SysSchedGetParam(int id, int flag) LosTaskCB *taskCB = OS_TCB_FROM_TID(id); SCHEDULER_LOCK(intSave); - int ret = OsUserTaskOperatePermissionsCheck(taskCB); + ret = OsUserTaskOperatePermissionsCheck(taskCB); if (ret != LOS_OK) { SCHEDULER_UNLOCK(intSave); return -ret; @@ -190,25 +240,39 @@ int SysSchedGetParam(int id, int flag) taskCB->ops->schedParamGet(taskCB, ¶m); SCHEDULER_UNLOCK(intSave); - return (int)param.priority; - } + if (param.policy == LOS_SCHED_DEADLINE) { + schedParam.runTimeUs = param.runTimeUs; + schedParam.deadlineUs = param.deadlineUs; + schedParam.periodUs = param.periodUs; + } else { + schedParam.priority = param.priority; + } + } else { + if (id == 0) { + id = (int)LOS_GetCurrProcessID(); + } - if (id == 0) { - id = (int)LOS_GetCurrProcessID(); - } + if (OS_PID_CHECK_INVALID(id)) { + return -EINVAL; + } - if (OS_PID_CHECK_INVALID(id)) { - return -EINVAL; + ret = LOS_GetProcessScheduler(id, NULL, &schedParam); + if (ret < 0) { + return ret; + } } - return OsGetProcessPriority(LOS_PRIO_PROCESS, id); + if (LOS_ArchCopyToUser(userParam, &schedParam, sizeof(LosSchedParam))) { + return -EFAULT; + } + return 0; } -int SysSetProcessPriority(int which, int who, unsigned int prio) +int SysSetProcessPriority(int which, int who, int prio) { int ret; - if (prio < OS_USER_PROCESS_PRIORITY_HIGHEST) { + if (which != LOS_PRIO_PROCESS) { return -EINVAL; } @@ -220,6 +284,10 @@ int SysSetProcessPriority(int which, int who, unsigned int prio) if (prio < OsPidLimitGetPriorityLimit()) { return -EINVAL; } +#else + if (prio < OS_USER_PROCESS_PRIORITY_HIGHEST) { + return -EINVAL; + } #endif ret = OsPermissionToCheck(who, LOS_GetCurrProcessID()); @@ -227,22 +295,31 @@ int SysSetProcessPriority(int which, int who, unsigned int prio) return ret; } - return OsSetProcessScheduler(which, who, prio, LOS_GetProcessScheduler(who)); + return LOS_SetProcessPriority(who, prio); } -int SysSchedSetParam(int id, unsigned int prio, int flag) +int SysSchedSetParam(int id, const LosSchedParam *userParam, int flag) { + int ret, policy; + LosSchedParam param; + if (flag < 0) { - return -OsUserTaskSchedulerSet(id, LOS_SCHED_RR, prio, false); + if (LOS_ArchCopyFromUser(¶m, userParam, sizeof(LosSchedParam)) != 0) { + return -EFAULT; + } + return -OsUserTaskSchedulerSet(id, LOS_SCHED_RR, ¶m, false); } -#ifdef LOSCFG_KERNEL_PLIMITS - if (prio < OsPidLimitGetPriorityLimit()) { - return -EINVAL; + if (id == 0) { + id = (int)LOS_GetCurrProcessID(); + } + + ret = LOS_GetProcessScheduler(id, &policy, NULL); + if (ret < 0) { + return ret; } -#endif - return SysSetProcessPriority(LOS_PRIO_PROCESS, id, prio); + return SysSchedSetScheduler(id, policy, userParam, flag); } int SysGetProcessPriority(int which, int who) diff --git a/syscall/syscall_lookup.h b/syscall/syscall_lookup.h index 53282ffa95779784a4b180ae52fa3522f8a32fb6..cb9c773c33c8b197de6ce34066c1376801149936 100644 --- a/syscall/syscall_lookup.h +++ b/syscall/syscall_lookup.h @@ -169,7 +169,7 @@ SYSCALL_HAND_DEF(__NR_sethostname, SysSetHostName, int, ARG_NUM_2) SYSCALL_HAND_DEF(__NR_mprotect, SysMprotect, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_getpgid, SysGetProcessGroupID, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_sched_setparam, SysSchedSetParam, int, ARG_NUM_3) -SYSCALL_HAND_DEF(__NR_sched_getparam, SysSchedGetParam, int, ARG_NUM_2) +SYSCALL_HAND_DEF(__NR_sched_getparam, SysSchedGetParam, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_sched_setscheduler, SysSchedSetScheduler, int, ARG_NUM_4) SYSCALL_HAND_DEF(__NR_sched_getscheduler, SysSchedGetScheduler, int, ARG_NUM_2) SYSCALL_HAND_DEF(__NR_sched_yield, SysSchedYield, void, ARG_NUM_1) diff --git a/testsuites/unittest/net/socket/smoke/net_socket_test_011.cpp b/testsuites/unittest/net/socket/smoke/net_socket_test_011.cpp index a6e428756b06d5eee4732920723ea3bfc890b1e7..0cceb863add7fb5c5f35660d31acc1b2b839f2f3 100644 --- a/testsuites/unittest/net/socket/smoke/net_socket_test_011.cpp +++ b/testsuites/unittest/net/socket/smoke/net_socket_test_011.cpp @@ -181,6 +181,9 @@ static int StartClients(pthread_t *cli, int cliNum) for (int i = 0; i < cliNum; ++i) { ret = pthread_attr_init(&attr); param.sched_priority = param.sched_priority + 1; + if (param.sched_priority > 31) { /* 31: prio */ + param.sched_priority = 31; /* 31: prio */ + } pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); pthread_attr_setschedparam(&attr, ¶m); diff --git a/testsuites/unittest/process/basic/process/smoke/process_test_001.cpp b/testsuites/unittest/process/basic/process/smoke/process_test_001.cpp index 2900a1e10d9da966025d9c12889d16e73f1be5a6..104257079cacdea777e2b146974c6ce12bcbef5d 100644 --- a/testsuites/unittest/process/basic/process/smoke/process_test_001.cpp +++ b/testsuites/unittest/process/basic/process/smoke/process_test_001.cpp @@ -30,7 +30,7 @@ */ #include "it_test_process.h" - + static const int PROCESS_PRIORITY_MAX = 10; static const int PROCESS_PRIORITY_MIN = 31; static const int PROCESS_SCHED_RR_INTERVAL = 20000000; diff --git a/testsuites/unittest/process/basic/process/smoke/process_test_008.cpp b/testsuites/unittest/process/basic/process/smoke/process_test_008.cpp index 6ba8beaafc2cdd55f259397e0eb8c329027f5947..8dc7b18bcc838b4e697693ed2072197cbcfbad21 100644 --- a/testsuites/unittest/process/basic/process/smoke/process_test_008.cpp +++ b/testsuites/unittest/process/basic/process/smoke/process_test_008.cpp @@ -66,7 +66,7 @@ static int ProcessTest001(void) ICUNIT_ASSERT_EQUAL(ret, 0, ret); ret = pthread_attr_init(&a); - param.sched_priority += 1; + param.sched_priority = 26; /* 26: prio */ pthread_attr_setschedparam(&a, ¶m); pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED); ret = pthread_create(&newPthread, &a, ThreadFunc3, &data); diff --git a/testsuites/unittest/process/basic/pthread/config.gni b/testsuites/unittest/process/basic/pthread/config.gni index 1dbba3ebb7fce2930433fbd0dd1ea78c4c795d7e..6b3265654b0eabdda7f4c894e67c189488e327e8 100644 --- a/testsuites/unittest/process/basic/pthread/config.gni +++ b/testsuites/unittest/process/basic/pthread/config.gni @@ -55,6 +55,14 @@ pthread_sources_smoke = [ "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_017.cpp", "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_018.cpp", "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_019.cpp", + "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_020.cpp", + "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_021.cpp", + "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_022.cpp", + "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_023.cpp", + "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_024.cpp", + "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_025.cpp", + "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_026.cpp", + "$TEST_UNITTEST_DIR/process/basic/pthread/smoke/pthread_test_027.cpp", ] pthread_sources_full = [ diff --git a/testsuites/unittest/process/basic/pthread/it_pthread_test.h b/testsuites/unittest/process/basic/pthread/it_pthread_test.h index 4b4391664baf65240090de9ab99d5cf5a263e95b..afcef819e96d00ad3a9ca7196f3840a5e11aea45 100644 --- a/testsuites/unittest/process/basic/pthread/it_pthread_test.h +++ b/testsuites/unittest/process/basic/pthread/it_pthread_test.h @@ -74,6 +74,14 @@ extern void ItTestPthread016(void); extern void ItTestPthread017(void); extern void ItTestPthread018(void); extern void ItTestPthread019(void); +extern void ItTestPthread020(void); +extern void ItTestPthread021(void); +extern void ItTestPthread022(void); +extern void ItTestPthread023(void); +extern void ItTestPthread024(void); +extern void ItTestPthread025(void); +extern void ItTestPthread026(void); +extern void ItTestPthread027(void); extern void ItTestPthreadAtfork001(void); extern void ItTestPthreadAtfork002(void); extern void ItTestPthreadOnce001(void); diff --git a/testsuites/unittest/process/basic/pthread/process_pthread_test.cpp b/testsuites/unittest/process/basic/pthread/process_pthread_test.cpp index 700bcbac7d8533a21bab8155003533931d284ffd..3c2187c355854d9016338512907ee6412b483200 100644 --- a/testsuites/unittest/process/basic/pthread/process_pthread_test.cpp +++ b/testsuites/unittest/process/basic/pthread/process_pthread_test.cpp @@ -186,6 +186,104 @@ HWTEST_F(ProcessPthreadTest, ItTestPthread019, TestSize.Level0) ItTestPthread019(); } +/* * + * @tc.name: it_test_pthread_020 + * @tc.desc: function for ProcessPthreadTest + * @tc.type: FUNC + * @tc.require: issueI6T3P3 + * @tc.author: + */ +HWTEST_F(ProcessPthreadTest, ItTestPthread020, TestSize.Level0) +{ + ItTestPthread020(); +} + +/* * + * @tc.name: it_test_pthread_021 + * @tc.desc: function for ProcessPthreadTest + * @tc.type: FUNC + * @tc.require: issueI6T3P3 + * @tc.author: + */ +HWTEST_F(ProcessPthreadTest, ItTestPthread021, TestSize.Level0) +{ + ItTestPthread021(); +} + +/* * + * @tc.name: it_test_pthread_022 + * @tc.desc: function for ProcessPthreadTest + * @tc.type: FUNC + * @tc.require: issueI6T3P3 + * @tc.author: + */ +HWTEST_F(ProcessPthreadTest, ItTestPthread022, TestSize.Level0) +{ + ItTestPthread022(); +} + +/* * + * @tc.name: it_test_pthread_024 + * @tc.desc: function for ProcessPthreadTest + * @tc.type: FUNC + * @tc.require: issueI6T3P3 + * @tc.author: + */ +HWTEST_F(ProcessPthreadTest, ItTestPthread024, TestSize.Level0) +{ + ItTestPthread024(); +} + +/* * + * @tc.name: it_test_pthread_026 + * @tc.desc: function for ProcessPthreadTest + * @tc.type: FUNC + * @tc.require: issueI6T3P3 + * @tc.author: + */ +HWTEST_F(ProcessPthreadTest, ItTestPthread026, TestSize.Level0) +{ + ItTestPthread026(); +} + +/* * + * @tc.name: it_test_pthread_027 + * @tc.desc: function for ProcessPthreadTest + * @tc.type: FUNC + * @tc.require: issueI6T3P3 + * @tc.author: + */ +HWTEST_F(ProcessPthreadTest, ItTestPthread027, TestSize.Level0) +{ + ItTestPthread027(); +} + + +/* * + * @tc.name: it_test_pthread_023 + * @tc.desc: function for ProcessPthreadTest + * @tc.type: FUNC + * @tc.require: issueI6T3P3 + * @tc.author: + */ +HWTEST_F(ProcessPthreadTest, ItTestPthread023, TestSize.Level0) +{ + ItTestPthread023(); +} + + +/* * + * @tc.name: it_test_pthread_025 + * @tc.desc: function for ProcessPthreadTest + * @tc.type: FUNC + * @tc.require: issueI6T3P3 + * @tc.author: + */ +HWTEST_F(ProcessPthreadTest, ItTestPthread025, TestSize.Level0) +{ + ItTestPthread025(); +} + /* * * @tc.name: it_test_pthread_017 * @tc.desc: function for ProcessPthreadTest diff --git a/testsuites/unittest/process/basic/pthread/smoke/pthread_test_020.cpp b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_020.cpp new file mode 100644 index 0000000000000000000000000000000000000000..904d64f6865373618a8200138738c2d2da2ea583 --- /dev/null +++ b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_020.cpp @@ -0,0 +1,105 @@ +/* + * 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 "it_pthread_test.h" + +static int ChildProcess(void) +{ + int ret, currPolicy = 0; + volatile unsigned int count = 0; + struct sched_param currSchedParam = { 0 }; + struct sched_param param = { + .sched_deadline = 4000000, /* 4000000, 4s */ + .sched_runtime = 200000, /* 200000, 200ms */ + .sched_period = 5000000, /* 5000000, 5s */ + }; + + ret = sched_getparam(getpid(), &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + currPolicy = sched_getscheduler(getpid()); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_RR, LOS_NOK); + currSchedParam.sched_runtime = 0; + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 0, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 0, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 0, LOS_NOK); + + ret = sched_setscheduler(getpid(), SCHED_DEADLINE, ¶m); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + currPolicy = sched_getscheduler(getpid()); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_DEADLINE, LOS_NOK); + + ret = sched_getparam(getpid(), &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 4000000, LOS_NOK); /* 4000000, 4s */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 200000, LOS_NOK); /* 200000, 200ms */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 5000000, LOS_NOK); /* 5000000, 5s */ + + printf("--- 1 edf thread start ---\n\r"); + do { + for (volatile int i = 0; i < 100000; i++) { /* 100000, no special meaning */ + for (volatile int j = 0; j < 10; j++) { /* 10, no special meaning */ + int tmp = i - j; + } + } + if (count % 20 == 0) { /* 20, no special meaning */ + printf("--- 2 edf thread running ---\n\r"); + } + count++; + } while (count <= 100); /* 100, no special meaning */ + printf("--- 3 edf thread end ---\n\r"); + + return 0; +} + +static int TestCase(void) +{ + int ret, pid, status; + + pid = fork(); + if (pid == 0) { + ret = ChildProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +void ItTestPthread020(void) +{ + TEST_ADD_CASE("IT_POSIX_PTHREAD_020", TestCase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); +} diff --git a/testsuites/unittest/process/basic/pthread/smoke/pthread_test_021.cpp b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_021.cpp new file mode 100644 index 0000000000000000000000000000000000000000..063168f30cd557d94f43458e563d6daed25c02de --- /dev/null +++ b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_021.cpp @@ -0,0 +1,139 @@ +/* + * 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 "it_pthread_test.h" + +static void *ThreadFuncTest(void *args) +{ + int pt = (int)args; + int ret, currPolicy; + struct sched_param currSchedParam; + volatile unsigned int count = 0; + int currTID = Syscall(SYS_gettid, 0, 0, 0, 0); + + ret = pthread_getschedparam(pthread_self(), & currPolicy, &currSchedParam); + ICUNIT_GOTO_EQUAL(ret, 0, LOS_NOK, EXIT); + ICUNIT_GOTO_EQUAL( currPolicy, SCHED_DEADLINE, LOS_NOK, EXIT); + ICUNIT_GOTO_EQUAL(currSchedParam.sched_deadline, 3000000, LOS_NOK, EXIT); /* 3000000, 3s */ + ICUNIT_GOTO_EQUAL(currSchedParam.sched_runtime, 200000, LOS_NOK, EXIT); /* 200000, 200ms */ + ICUNIT_GOTO_EQUAL(currSchedParam.sched_period, 5000000, LOS_NOK, EXIT); /* 5000000, 5s */ + + printf("--- 1 edf Tid[%d] PTid[%d] thread start ---\n\r", currTID, pt); + do { + for (volatile int i = 0; i < 100000; i++) { /* 100000, no special meaning */ + for (volatile int j = 0; j < 5; j++) { /* 5, no special meaning */ + volatile int tmp = i - j; + } + } + if (count % 20 == 0) { /* 20, no special meaning */ + printf("--- 2 edf Tid[%d] PTid[%d] thread running ---\n\r", currTID, pt); + } + count++; + } while (count <= 100); /* 100, no special meaning */ + printf("--- 3 edf Tid[%d] PTid[%d] thread end ---\n\r", currTID, pt); + + ret = LOS_OK; + return (void *)(&ret); +EXIT: + ret = LOS_NOK; + return (void *)(&ret); +} + +static int ChildProcess(void) +{ + int *childThreadRetval = nullptr; + pthread_t newUserThread; + int ret, currPolicy = 0; + volatile unsigned int count = 0; + struct sched_param currSchedParam = { 0 }; + int currTID = Syscall(SYS_gettid, 0, 0, 0, 0); + struct sched_param param = { + .sched_deadline = 3000000, /* 3000000, 3s */ + .sched_runtime = 200000, /* 200000, 200ms */ + .sched_period = 5000000, /* 5000000, 5s */ + }; + + ret = sched_setscheduler(getpid(), SCHED_DEADLINE, ¶m); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_getschedparam(pthread_self(), & currPolicy, &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_DEADLINE, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 3000000, LOS_NOK); /* 3000000, 3s */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 200000, LOS_NOK); /* 200000, 200ms */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 5000000, LOS_NOK); /* 5000000, 5s */ + + ret = pthread_create(&newUserThread, NULL, ThreadFuncTest, (void *)currTID); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + printf("--- 1 edf Tid[%d] thread start ---\n\r", currTID); + do { + for (volatile int i = 0; i < 100000; i++) { /* 100000, no special meaning */ + for (volatile int j = 0; j < 5; j++) { /* 5, no special meaning */ + int tmp = i - j; + } + } + if (count % 20 == 0) { /* 20, no special meaning */ + printf("--- 2 edf Tid[%d] thread running ---\n\r", currTID); + } + count++; + } while (count <= 100); /* 100, no special meaning */ + printf("--- 3 edf Tid[%d] thread end ---\n\r", currTID); + + ret = pthread_join(newUserThread, (void **)&childThreadRetval); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(*childThreadRetval, 0, *childThreadRetval); + + return 0; +} + +static int TestCase(void) +{ + int ret, pid, status; + + pid = fork(); + if (pid == 0) { + ret = ChildProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +void ItTestPthread021(void) +{ + TEST_ADD_CASE("IT_POSIX_PTHREAD_021", TestCase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); +} diff --git a/testsuites/unittest/process/basic/pthread/smoke/pthread_test_022.cpp b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_022.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90624467658bfa46bf888217443cc84495303891 --- /dev/null +++ b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_022.cpp @@ -0,0 +1,139 @@ +/* + * 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 "it_pthread_test.h" + +static int EdfProcess(void) +{ + int ret; + int currPolicy = 0; + struct sched_param currSchedParam = { 0 }; + volatile unsigned int count = 0; + int currTID = Syscall(SYS_gettid, 0, 0, 0, 0); + + ret = pthread_getschedparam(pthread_self(), &currPolicy, &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_DEADLINE, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 3000000, LOS_NOK); /* 3000000, 3s */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 200000, LOS_NOK); /* 200000, 200ms */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 5000000, LOS_NOK); /* 5000000, 5s */ + + printf("--- edf2 -- 1 -- Tid[%d] thread start ---\n\r", currTID); + do { + for (volatile int i = 0; i < 100000; i++) { /* 100000, no special meaning */ + for (volatile int j = 0; j < 5; j++) { /* 5, no special meaning */ + int tmp = i - j; + } + } + if (count % 20 == 0) { /* 20, no special meaning */ + printf("--- edf2 -- 2 -- Tid[%d] thread running ---\n\r", currTID); + } + count++; + } while (count <= 100); /* 100, no special meaning */ + printf("--- edf2 -- 3 -- Tid[%d] thread end ---\n\r", currTID); + + return 0; +} + +static int ChildProcess(void) +{ + int *childThreadRetval = nullptr; + pthread_t newUserThread; + int pid, status, ret; + int currPolicy = 0; + volatile unsigned int count = 0; + struct sched_param currSchedParam = { 0 }; + int currTID = Syscall(SYS_gettid, 0, 0, 0, 0); + struct sched_param param = { + .sched_deadline = 3000000, /* 3000000, 3s */ + .sched_runtime = 200000, /* 200000, 200ms */ + .sched_period = 5000000, /* 5000000, 5s */ + }; + + ret = sched_setscheduler(getpid(), SCHED_DEADLINE, ¶m); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_getschedparam(pthread_self(), &currPolicy, &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_DEADLINE, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 3000000, LOS_NOK); /* 3000000, 3s */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 200000, LOS_NOK); /* 200000, 200ms */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 5000000, LOS_NOK); /* 5000000, 5s */ + + pid = fork(); + if (pid == 0) { + ret = EdfProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + printf("--- edf1 -- 1 -- Tid[%d] thread start ---\n\r", currTID); + do { + for (volatile int i = 0; i < 500000; i++) { /* 500000, no special meaning */ + int tmp = i + 1; + } + if (count % 20 == 0) { /* 20, no special meaning */ + printf("--- edf1 -- 2 -- Tid[%d] thread running ---\n\r", currTID); + } + count++; + } while (count <= 100); /* 100, no special meaning */ + printf("--- edf1 -- 3 -- Tid[%d] thread end ---\n\r", currTID); + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +static int TestCase(void) +{ + int ret, pid, status; + + pid = fork(); + if (pid == 0) { + ret = ChildProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +void ItTestPthread022(void) +{ + TEST_ADD_CASE("IT_POSIX_PTHREAD_022", TestCase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); +} diff --git a/testsuites/unittest/process/basic/pthread/smoke/pthread_test_023.cpp b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_023.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b6572d61dae42fda455d5b77951ce8f0e81d6e4 --- /dev/null +++ b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_023.cpp @@ -0,0 +1,101 @@ +/* + * 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 "it_pthread_test.h" + +static void *ThreadFuncTest(void *args) +{ + return (void *)NULL; +} + +static int ChildProcess(void) +{ + int ret; + int currPolicy = 0; + int oldPolicy; + pthread_t newUserThread; + pthread_attr_t a = { 0 }; + struct sched_param hpfparam = { 0 }; + volatile unsigned int count = 0; + struct sched_param currSchedParam = { 0 }; + int currTID = Syscall(SYS_gettid, 0, 0, 0, 0); + struct sched_param param = { + .sched_deadline = 3000000, /* 3000000, 3s */ + .sched_runtime = 200000, /* 200000, 200ms */ + .sched_period = 5000000, /* 5000000, 5s */ + }; + + ret = pthread_getschedparam(pthread_self(), &oldPolicy, &hpfparam); + ICUNIT_ASSERT_EQUAL(ret, 0, -ret); + + ret = sched_setscheduler(getpid(), SCHED_DEADLINE, ¶m); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_getschedparam(pthread_self(), &currPolicy, &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_DEADLINE, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 3000000, LOS_NOK); /* 3000000, 3s */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 200000, LOS_NOK); /* 200000, 200ms */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 5000000, LOS_NOK); /* 5000000, 5s */ + + ret = pthread_attr_init(&a); + pthread_attr_setschedpolicy(&a, SCHED_RR); + pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED); + ret = pthread_create(&newUserThread, &a, ThreadFuncTest, NULL); + ICUNIT_ASSERT_NOT_EQUAL(ret, 0, ret); + + printf("--- edf2 -- 1 -- Tid[%d] thread end ---\n\r", currTID); + + return 0; +} + +static int TestCase(void) +{ + int ret, pid, status; + + pid = fork(); + if (pid == 0) { + ret = ChildProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +void ItTestPthread023(void) +{ + TEST_ADD_CASE("IT_POSIX_PTHREAD_023", TestCase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); +} diff --git a/testsuites/unittest/process/basic/pthread/smoke/pthread_test_024.cpp b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_024.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9665294e0c3750b3fdf79d9a83fa47fce640575e --- /dev/null +++ b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_024.cpp @@ -0,0 +1,90 @@ +/* + * 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 "it_pthread_test.h" + +static void *ThreadFuncTest(void *args) +{ + (void)args; + printf("hpf thread run...\r\n"); + return NULL; +} + +static int ChildProcess(void) +{ + int ret, currThreadPolicy; + pthread_attr_t a = { 0 }; + struct sched_param hpfparam = { 0 }; + pthread_t newUserThread; + volatile unsigned int count = 0; + int currTID = Syscall(SYS_gettid, 0, 0, 0, 0); + struct sched_param param = { + .sched_deadline = 3000000, /* 3000000, 3s */ + .sched_runtime = 200000, /* 200000, 200ms */ + .sched_period = 5000000, /* 5000000, 5s */ + }; + + ret = pthread_getschedparam(pthread_self(), &currThreadPolicy, &hpfparam); + ICUNIT_ASSERT_EQUAL(ret, 0, -ret); + ret = pthread_attr_init(&a); + hpfparam.sched_priority = hpfparam.sched_priority - 1; + pthread_attr_setschedparam(&a, &hpfparam); + ret = pthread_create(&newUserThread, &a, ThreadFuncTest, (void *)currTID); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = sched_setscheduler(getpid(), SCHED_DEADLINE, ¶m); + ICUNIT_ASSERT_EQUAL(ret, -1, ret); + + return 0; +} + +static int TestCase(void) +{ + int ret, pid, status; + + pid = fork(); + if (pid == 0) { + ret = ChildProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +void ItTestPthread024(void) +{ + TEST_ADD_CASE("IT_POSIX_PTHREAD_024", TestCase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); +} diff --git a/testsuites/unittest/process/basic/pthread/smoke/pthread_test_025.cpp b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_025.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c339b7887226a2ac5cc58ec802308359cd9d2e0 --- /dev/null +++ b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_025.cpp @@ -0,0 +1,97 @@ +/* + * 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 "it_pthread_test.h" + +static void *ThreadFuncTest(void *args) +{ + (void)args; + printf("hpf thread run...\r\n"); + return NULL; +} + +static int ChildProcess(void) +{ + int currThreadPolicy; + pthread_attr_t a = { 0 }; + struct sched_param hpfparam = { 0 }; + int *childThreadRetval = nullptr; + pthread_t newUserThread; + int ret; + int currPolicy = 0; + volatile unsigned int count = 0; + struct sched_param currSchedParam = { 0 }; + int currTID = Syscall(SYS_gettid, 0, 0, 0, 0); + struct sched_param param = { + .sched_deadline = 3000000, /* 3000000, 3s */ + .sched_runtime = 200000, /* 200000, 200ms */ + .sched_period = 5000000, /* 5000000, 5s */ + }; + + ret = pthread_getschedparam(pthread_self(), &currThreadPolicy, &hpfparam); + ICUNIT_ASSERT_EQUAL(ret, 0, -ret); + ret = pthread_attr_init(&a); + hpfparam.sched_priority = hpfparam.sched_priority - 1; + pthread_attr_setschedparam(&a, &hpfparam); + ret = pthread_create(&newUserThread, &a, ThreadFuncTest, (void *)currTID); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_join(newUserThread, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = sched_setscheduler(getpid(), SCHED_DEADLINE, ¶m); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + return 0; +} + +static int TestCase(void) +{ + int ret, pid, status; + + pid = fork(); + if (pid == 0) { + ret = ChildProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +void ItTestPthread025(void) +{ + TEST_ADD_CASE("IT_POSIX_PTHREAD_025", TestCase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); +} diff --git a/testsuites/unittest/process/basic/pthread/smoke/pthread_test_026.cpp b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_026.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b733d86c4d587166a93f95bfb17facaa0a7ec149 --- /dev/null +++ b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_026.cpp @@ -0,0 +1,106 @@ +/* + * 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 "it_pthread_test.h" + +static int ChildProcess(void) +{ + int ret; + int currPolicy = 0; + volatile unsigned int count = 0; + struct sched_param currSchedParam = { 0 }; + struct sched_param param = { + .sched_deadline = 4000000, /* 4000000, 4s */ + .sched_runtime = 200000, /* 200000, 200ms */ + .sched_period = 5000000, /* 5000000, 5s */ + }; + + ret = sched_getparam(getpid(), &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + currPolicy = sched_getscheduler(getpid()); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_RR, LOS_NOK); + currSchedParam.sched_runtime = 0; + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 0, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 0, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 0, LOS_NOK); + + ret = sched_setscheduler(getpid(), SCHED_DEADLINE, ¶m); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + currPolicy = sched_getscheduler(getpid()); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_DEADLINE, LOS_NOK); + + ret = sched_getparam(getpid(), &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 4000000, LOS_NOK); /* 4000000, 4s */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 200000, LOS_NOK); /* 200000, 200ms */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 5000000, LOS_NOK); /* 5000000, 5s */ + + printf("--- 1 edf thread start ---\n\r"); + do { + for (volatile int i = 0; i < 100000; i++) { /* 100000, no special meaning */ + for (volatile int j = 0; j < 10; j++) { /* 10, no special meaning */ + int tmp = i - j; + } + } + if (count % 20 == 0) { /* 20, no special meaning */ + printf("--- 2 edf thread running ---\n\r"); + } + count++; + } while (count <= 100); /* 100, no special meaning */ + printf("--- 3 edf thread end ---\n\r"); + + return 0; +} + +static int TestCase(void) +{ + int ret, pid, status; + + pid = fork(); + if (pid == 0) { + ret = ChildProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +void ItTestPthread026(void) +{ + TEST_ADD_CASE("IT_POSIX_PTHREAD_026", TestCase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); +} diff --git a/testsuites/unittest/process/basic/pthread/smoke/pthread_test_027.cpp b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_027.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49ca891c11601dd0389c376f3923822173f0a738 --- /dev/null +++ b/testsuites/unittest/process/basic/pthread/smoke/pthread_test_027.cpp @@ -0,0 +1,91 @@ +/* + * 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 "it_pthread_test.h" + +static int ChildProcess(void) +{ + int ret; + int currPolicy = 0; + volatile unsigned int count = 0; + struct sched_param currSchedParam = { 0 }; + struct sched_param param = { + .sched_deadline = 4000000, /* 4000000, 4s */ + .sched_runtime = 200000, /* 200000, 200ms */ + .sched_period = 5000000, /* 5000000, 5s */ + }; + + ret = sched_getparam(getpid(), &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + currPolicy = sched_getscheduler(getpid()); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_RR, LOS_NOK); + currSchedParam.sched_runtime = 0; + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 0, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 0, LOS_NOK); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 0, LOS_NOK); + + ret = sched_setscheduler(getpid(), SCHED_DEADLINE, ¶m); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + currPolicy = sched_getscheduler(getpid()); + ICUNIT_ASSERT_EQUAL(currPolicy, SCHED_DEADLINE, LOS_NOK); + + ret = sched_getparam(getpid(), &currSchedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_deadline, 4000000, LOS_NOK); /* 4000000, 4s */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_runtime, 200000, LOS_NOK); /* 200000, 200ms */ + ICUNIT_ASSERT_EQUAL(currSchedParam.sched_period, 5000000, LOS_NOK); /* 5000000, 5s */ + return 0; +} + +static int TestCase(void) +{ + int ret, pid, status; + + pid = fork(); + if (pid == 0) { + ret = ChildProcess(); + if (ret != 0) { + exit(-1); + } + exit(0); + } else if (pid > 0) { + waitpid(pid, &status, 0); + } else { + exit(__LINE__); + } + + return WEXITSTATUS(status) == 0 ? 0 : -1; +} + +void ItTestPthread027(void) +{ + TEST_ADD_CASE("IT_POSIX_PTHREAD_027", TestCase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); +}