feat: support EDF

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

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

Close:#I6T3P3

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

View File

@ -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

View File

@ -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",

View File

@ -939,7 +939,37 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSystemProcessCreate(VOID)
return LOS_OK;
}
STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 prio, UINT16 policy)
INT32 OsSchedulerParamCheck(UINT16 policy, BOOL isThread, const LosSchedParam *param)
{
if (param == NULL) {
return LOS_EINVAL;
}
if ((policy == LOS_SCHED_RR) || (isThread && (policy == LOS_SCHED_FIFO))) {
if ((param->priority < OS_PROCESS_PRIORITY_HIGHEST) ||
(param->priority > OS_PROCESS_PRIORITY_LOWEST)) {
return LOS_EINVAL;
}
return LOS_OK;
}
if (policy == LOS_SCHED_DEADLINE) {
if ((param->runTimeUs < OS_SCHED_EDF_MIN_RUNTIME) || (param->runTimeUs >= param->deadlineUs)) {
return LOS_EINVAL;
}
if ((param->deadlineUs < OS_SCHED_EDF_MIN_DEADLINE) || (param->deadlineUs > OS_SCHED_EDF_MAX_DEADLINE)) {
return LOS_EINVAL;
}
if (param->periodUs < param->deadlineUs) {
return LOS_EINVAL;
}
return LOS_OK;
}
return LOS_EINVAL;
}
STATIC INLINE INT32 ProcessSchedulerParamCheck(INT32 which, INT32 pid, UINT16 policy, const LosSchedParam *param)
{
if (OS_PID_CHECK_INVALID(pid)) {
return LOS_EINVAL;
@ -949,19 +979,11 @@ STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 p
return LOS_EINVAL;
}
if (prio > OS_PROCESS_PRIORITY_LOWEST) {
return LOS_EINVAL;
}
if (policy != LOS_SCHED_RR) {
return LOS_EINVAL;
}
return LOS_OK;
return OsSchedulerParamCheck(policy, FALSE, param);
}
#ifdef LOSCFG_SECURITY_CAPABILITY
STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedParam *param, UINT16 prio)
STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedParam *param, UINT16 policy, UINT16 prio)
{
LosProcessCB *runProcess = OsCurrProcessGet();
@ -971,7 +993,7 @@ STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedPa
}
/* user mode process can reduce the priority of itself */
if ((runProcess->processID == processCB->processID) && (prio > param->basePrio)) {
if ((runProcess->processID == processCB->processID) && (policy == LOS_SCHED_RR) && (prio > param->basePrio)) {
return TRUE;
}
@ -983,12 +1005,13 @@ STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, const SchedPa
}
#endif
LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy)
LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 policy, const LosSchedParam *schedParam)
{
SchedParam param = { 0 };
BOOL needSched = FALSE;
UINT32 intSave;
INT32 ret = OsProcessSchedlerParamCheck(which, pid, prio, policy);
INT32 ret = ProcessSchedulerParamCheck(which, pid, policy, schedParam);
if (ret != LOS_OK) {
return -ret;
}
@ -996,22 +1019,45 @@ LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio
LosProcessCB *processCB = OS_PCB_FROM_PID(pid);
SCHEDULER_LOCK(intSave);
if (OsProcessIsInactive(processCB)) {
ret = LOS_ESRCH;
goto EXIT;
SCHEDULER_UNLOCK(intSave);
return -LOS_ESRCH;
}
#ifdef LOSCFG_SECURITY_CAPABILITY
if (!OsProcessCapPermitCheck(processCB, &param, prio)) {
ret = LOS_EPERM;
goto EXIT;
}
#endif
LosTaskCB *taskCB = processCB->threadGroup;
taskCB->ops->schedParamGet(taskCB, &param);
param.basePrio = prio;
BOOL needSched = taskCB->ops->schedParamModify(taskCB, &param);
#ifdef LOSCFG_SECURITY_CAPABILITY
if (!OsProcessCapPermitCheck(processCB, &param, policy, schedParam->priority)) {
SCHEDULER_UNLOCK(intSave);
return -LOS_EPERM;
}
#endif
if (param.policy != policy) {
if (policy == LOS_SCHED_DEADLINE) { /* HPF -> EDF */
if (processCB->threadNumber > 1) {
SCHEDULER_UNLOCK(intSave);
return -LOS_EPERM;
}
OsSchedParamInit(taskCB, policy, NULL, schedParam);
needSched = TRUE;
goto TO_SCHED;
} else if (param.policy == LOS_SCHED_DEADLINE) { /* EDF -> HPF */
SCHEDULER_UNLOCK(intSave);
return -LOS_EPERM;
}
}
if (policy == LOS_SCHED_DEADLINE) {
param.runTimeUs = schedParam->runTimeUs;
param.deadlineUs = schedParam->deadlineUs;
param.periodUs = schedParam->periodUs;
} else {
param.basePrio = schedParam->priority;
}
needSched = taskCB->ops->schedParamModify(taskCB, &param);
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, &param);
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, &param);
}
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, &param);
if (param.policy == LOS_SCHED_DEADLINE) {
SCHEDULER_UNLOCK(intSave);
return -LOS_EINVAL;
}
SCHEDULER_UNLOCK(intSave);
return param.basePrio;
}
@ -1850,6 +1936,38 @@ STATIC UINT32 OsCopyUser(LosProcessCB *childCB, LosProcessCB *parentCB)
return LOS_OK;
}
STATIC VOID GetCopyTaskParam(LosProcessCB *childProcessCB, UINTPTR entry, UINT32 size,
TSK_INIT_PARAM_S *taskParam, SchedParam *param)
{
UINT32 intSave;
LosTaskCB *runTask = OsCurrTaskGet();
SCHEDULER_LOCK(intSave);
if (OsProcessIsUserMode(childProcessCB)) {
taskParam->pfnTaskEntry = runTask->taskEntry;
taskParam->uwStackSize = runTask->stackSize;
taskParam->userParam.userArea = runTask->userArea;
taskParam->userParam.userMapBase = runTask->userMapBase;
taskParam->userParam.userMapSize = runTask->userMapSize;
} else {
taskParam->pfnTaskEntry = (TSK_ENTRY_FUNC)entry;
taskParam->uwStackSize = size;
}
if (runTask->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
taskParam->uwResved = LOS_TASK_ATTR_JOINABLE;
}
runTask->ops->schedParamGet(runTask, param);
SCHEDULER_UNLOCK(intSave);
taskParam->policy = param->policy;
taskParam->runTimeUs = param->runTimeUs;
taskParam->deadlineUs = param->deadlineUs;
taskParam->periodUs = param->periodUs;
taskParam->usTaskPrio = param->priority;
taskParam->processID = (UINTPTR)childProcessCB;
}
STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size)
{
LosTaskCB *runTask = OsCurrTaskGet();
@ -1857,28 +1975,8 @@ STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR
UINT32 ret, taskID, intSave;
SchedParam param = { 0 };
SCHEDULER_LOCK(intSave);
if (OsProcessIsUserMode(childProcessCB)) {
taskParam.pfnTaskEntry = runTask->taskEntry;
taskParam.uwStackSize = runTask->stackSize;
taskParam.userParam.userArea = runTask->userArea;
taskParam.userParam.userMapBase = runTask->userMapBase;
taskParam.userParam.userMapSize = runTask->userMapSize;
} else {
taskParam.pfnTaskEntry = (TSK_ENTRY_FUNC)entry;
taskParam.uwStackSize = size;
}
if (runTask->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
taskParam.uwResved = LOS_TASK_ATTR_JOINABLE;
}
runTask->ops->schedParamGet(runTask, &param);
SCHEDULER_UNLOCK(intSave);
taskParam.pcName = (CHAR *)name;
taskParam.policy = param.policy;
taskParam.usTaskPrio = param.priority;
taskParam.processID = (UINTPTR)childProcessCB;
GetCopyTaskParam(childProcessCB, entry, size, &taskParam, &param);
ret = LOS_TaskCreateOnly(&taskID, &taskParam);
if (ret != LOS_OK) {

View File

@ -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, &param);
initParam->runTimeUs = param.runTimeUs;
initParam->deadlineUs = param.deadlineUs;
initParam->periodUs = param.periodUs;
}
} else {
initParam->policy = LOS_SCHED_RR;
initParam->processID = processID;
initParam->consoleID = 0;
}

View File

@ -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
}

View File

@ -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);

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;
int processPolicy;
if (OS_TID_CHECK_INVALID(tid)) {
return EINVAL;
}
ret = OsSchedulerParamCheck(policy, TRUE, schedParam);
if (ret != 0) {
return ret;
}
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 };
if (OS_TID_CHECK_INVALID(tid)) {
return EINVAL;
}
if (priority > OS_TASK_PRIORITY_LOWEST) {
return EINVAL;
}
if ((policy != LOS_SCHED_FIFO) && (policy != LOS_SCHED_RR)) {
return EINVAL;
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, &param);
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, &param);
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);
}
int SysSchedSetScheduler(int id, int policy, int prio, int flag)
{
int ret;
if (flag < 0) {
return -OsUserTaskSchedulerSet(id, policy, prio, true);
ret = LOS_GetProcessScheduler(id, &policy, NULL);
if (ret < 0) {
return ret;
}
if (prio < OS_USER_PROCESS_PRIORITY_HIGHEST) {
return -EINVAL;
return policy;
}
int SysSchedSetScheduler(int id, int policy, const LosSchedParam *userParam, int flag)
{
int ret;
LosSchedParam param;
if (LOS_ArchCopyFromUser(&param, userParam, sizeof(LosSchedParam)) != 0) {
return -EFAULT;
}
if (flag < 0) {
return -OsUserTaskSchedulerSet(id, policy, &param, true);
}
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, &param);
}
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, &param);
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 (OS_PID_CHECK_INVALID(id)) {
return -EINVAL;
}
ret = LOS_GetProcessScheduler(id, NULL, &schedParam);
if (ret < 0) {
return ret;
}
}
if (id == 0) {
id = (int)LOS_GetCurrProcessID();
if (LOS_ArchCopyToUser(userParam, &schedParam, sizeof(LosSchedParam))) {
return -EFAULT;
}
if (OS_PID_CHECK_INVALID(id)) {
return -EINVAL;
}
return OsGetProcessPriority(LOS_PRIO_PROCESS, id);
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(&param, userParam, sizeof(LosSchedParam)) != 0) {
return -EFAULT;
}
return -OsUserTaskSchedulerSet(id, LOS_SCHED_RR, &param, false);
}
#ifdef LOSCFG_KERNEL_PLIMITS
if (prio < OsPidLimitGetPriorityLimit()) {
return -EINVAL;
if (id == 0) {
id = (int)LOS_GetCurrProcessID();
}
#endif
return SysSetProcessPriority(LOS_PRIO_PROCESS, id, prio);
ret = LOS_GetProcessScheduler(id, &policy, NULL);
if (ret < 0) {
return ret;
}
return SysSchedSetScheduler(id, policy, userParam, flag);
}
int SysGetProcessPriority(int which, int who)

View File

@ -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)

View File

@ -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, &param);

View File

@ -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;

View File

@ -65,7 +65,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, &param);
pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
ret = pthread_create(&newPthread, &a, ThreadFunc3, &data);

View File

@ -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 = [

View File

@ -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);

View File

@ -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

View File

@ -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, &param);
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);
}

View File

@ -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, &param);
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);
}

View File

@ -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, &param);
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);
}

View File

@ -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, &param);
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);
}

View File

@ -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, &param);
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);
}

View File

@ -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, &param);
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);
}

View File

@ -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, &param);
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);
}

View File

@ -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, &param);
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);
}