/* * Copyright (c) 2020 AIIT XUOS Lab * XiUOS is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * http://license.coscl.org.cn/MulanPSL2 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ /** * @file: ktask.c * @brief: ktask file * @version: 1.0 * @author: AIIT XUOS Lab * @date: 2020/3/15 * */ #include #include #include #include #include #include #ifdef TASK_ISOLATION #include #endif static volatile int __exstatus; extern DoubleLinklistType KTaskZombie; extern int32 zombie_recycle; extern uint8 KTaskStackSetup(struct TaskDescriptor *task); extern int JudgeZombieKTaskIsNotEmpty(void); DoubleLinklistType xiaoshan_task_head ={&xiaoshan_task_head, &xiaoshan_task_head}; ///< global task manage list #if KTASK_PRIORITY_MAX > 32 #define BITMAP_CACULATE_COLUMN_OFFSET(offset,n) (offset = n / 8) #endif #define BITMAP_SETCOLUMN(column,offset) (column = (1 << offset)) #define BITMAP_SETROW(row,offset) (row = (1 << offset)) #define BITLOWMASK_3BIT (0x7) DECLARE_ID_MANAGER(k_task_id_manager, ID_NUM_MAX); void KTaskIdDelete(int32 id) { IdRemoveObj(&k_task_id_manager, id); } inline struct TaskDescriptor *GetTaskWithIdnodeInfo(int32 id) { struct TaskDescriptor *task = NONE; struct IdNode *idnode = NONE; x_base lock = 0; if (id < 0) return NONE; lock = CriticalAreaLock(); idnode = IdGetObj(&k_task_id_manager, id); if (idnode == NONE){ CriticalAreaUnLock(lock); return NONE; } task =CONTAINER_OF(idnode, struct TaskDescriptor, id); CriticalAreaUnLock(lock); return task; } static inline void __BitmapSiteMask(struct TaskDescriptor *task) { NULL_PARAM_CHECK(task); #if KTASK_PRIORITY_MAX > 32 BITMAP_CACULATE_COLUMN_OFFSET(task->task_dync_sched_member.bitmap_offset,task->task_dync_sched_member.cur_prio); BITMAP_SETCOLUMN(task->task_dync_sched_member.bitmap_column,task->task_dync_sched_member.bitmap_offset); BITMAP_SETROW(task->task_dync_sched_member.bitmap_row,(task->task_dync_sched_member.cur_prio & BITLOWMASK_3BIT)); #else BITMAP_SETCOLUMN(task->task_dync_sched_member.bitmap_column,task->task_dync_sched_member.cur_prio); #endif } static inline void _KTaskResourceDelete(struct TaskDescriptor *task) { NULL_PARAM_CHECK(task); #ifdef ARCH_SMP HwLockSpinlock(&AssignSpinLock); #endif Assign.ready_vector_done->remove(task); #ifdef ARCH_SMP HwUnlockSpinlock(&AssignSpinLock); #endif KTaskStatSetAsClose(task); return; } static inline x_err_t __JudgeKTaskIsIdleOrZombierecycle(KTaskDescriptorType task) { NULL_PARAM_CHECK(task); if(0 == strncmp(task->task_base_info.name,"ktaskidle0",strlen("ktaskidle0")) || 0 == strncmp(task->task_base_info.name,"ktaskidle1",strlen("ktaskidle1")) || 0 == strncmp(task->task_base_info.name,"ZombieRecycleKTask",strlen("ZombieRecycleKTask")) ) { return RET_TRUE; } return EOK; } /** * find a task in manage list. * * @param name task name * * @note in interrupt status,this function is not permitted to call. */ KTaskDescriptorType KTaskSearch(char *name) { x_base lock = 0; KTaskDescriptorType temp_task = NONE; struct SysDoubleLinklistNode *node = NONE; lock = CriticalAreaLock(); DOUBLE_LINKLIST_FOR_EACH(node,&xiaoshan_task_head) { temp_task = SYS_DOUBLE_LINKLIST_ENTRY(node, struct TaskDescriptor, link); if (0 == strncmp(temp_task->task_base_info.name, name, NAME_NUM_MAX)) { CriticalAreaUnLock(lock); return temp_task; } } CriticalAreaUnLock(lock); return NONE; } /** * This function will get a task descriptor * */ KTaskDescriptorType GetKTaskDescriptor(void) { x_base lock = 0; KTaskDescriptorType task = NONE; lock = CriticalAreaLock(); #ifdef ARCH_SMP HwLockSpinlock(&AssignSpinLock); if(Assign.smp_os_running_task[GetCpuId()] != NONE){ task = Assign.smp_os_running_task[GetCpuId()]; } HwUnlockSpinlock(&AssignSpinLock); #else if(Assign.os_running_task != NONE){ task = Assign.os_running_task; } #endif CriticalAreaUnLock(lock); return task; } /** * This function will delay current task running with some ticks. * * @param tick delay ticks * */ x_err_t _DelayKTask(KTaskDescriptorType task, x_ticks_t ticks) { x_base lock = 0; NULL_PARAM_CHECK(task); if (ticks == 0) { KPrintf("Timeout ticks must be setted more than 0.\n"); return -EINVALED; } lock = CriticalAreaLock(); SuspendKTask(task->id.id); KTaskSetDelay(task,ticks); CriticalAreaUnLock(lock); DO_KTASK_ASSIGN; if (task->exstatus == -ETIMEOUT) task->exstatus = EOK; return EOK; } /** * This function will delay current task wite milliseconds. * * @param ms milliseconds of delay time * */ x_err_t _MdelayKTask(KTaskDescriptorType task, uint32 ms) { x_ticks_t ticks = 0; NULL_PARAM_CHECK(task); if (0 == ms) { return -EINVALED; } ticks = CalculteTickFromTimeMs(ms); return _DelayKTask(task, ticks); } /** * This function sets the task's priority. * * @param id task id * @param prio priority value * * @return EOK */ x_err_t _KTaskPrioSet(KTaskDescriptorType task, uint8 prio) { x_base lock = 0; int ret = EOK; uint8 task_stat = 0; NULL_PARAM_CHECK(task); lock = CriticalAreaLock(); if (0 == strncmp("ktaskidle",task->task_base_info.name, strlen("ktaskidle"))) { KPrintf("IDLE task [%s] is forbidden to change priority.\n",task->task_base_info.name); CriticalAreaUnLock(lock); return -ERROR; } task_stat = KTaskStatGet(task); switch(task_stat) { case KTASK_READY: #ifdef ARCH_SMP HwLockSpinlock(&AssignSpinLock); #endif task->task_dync_sched_member.cur_prio = prio; Assign.ready_vector_done->remove(task); __BitmapSiteMask(task); Assign.ready_vector_done->insert(task); #ifdef ARCH_SMP HwUnlockSpinlock(&AssignSpinLock); #endif break; case KTASK_INIT: case KTASK_SUSPEND: case KTASK_RUNNING: task->task_dync_sched_member.cur_prio = prio; __BitmapSiteMask(task); break; case KTASK_CLOSE: KPrintf("the close stat task is forbidden to change priority.\n"); ret = -ERROR; break; default: KPrintf("invalid stat task is forbidden to change priority.\n"); ret = -EINVALED; break; } CriticalAreaUnLock(lock); return ret; } #ifdef ARCH_SMP /** * This function binds a task to cpu core. * * @param id task id * @param coreid cpu core id * * @return EOK */ x_err_t _KTaskCoreCombine(KTaskDescriptorType task, uint8 coreid) { x_base lock = 0; int ret = EOK; uint8 task_stat = 0; NULL_PARAM_CHECK(task); lock = CriticalAreaLock(); task_stat = KTaskStatGet(task); switch(task_stat) { case KTASK_READY: HwLockSpinlock(&AssignSpinLock); Assign.ready_vector_done->remove(task); task->task_smp_info.combined_coreid = coreid > CPU_NUMBERS ? UNCOMBINE_CPU_CORE : coreid; Assign.ready_vector_done->insert(task); HwUnlockSpinlock(&AssignSpinLock); break; case KTASK_INIT: case KTASK_SUSPEND: task->task_smp_info.combined_coreid = coreid > CPU_NUMBERS ? UNCOMBINE_CPU_CORE : coreid; break; case KTASK_CLOSE: case KTASK_RUNNING: KPrintf("the CLOSE and RUNNING stat of task is forbidden to change cpu core.\n"); ret = -ERROR; break; default: KPrintf("%s invalid task stat.\n",__func__); ret = -EINVALED; break; } CriticalAreaUnLock(lock); return ret; } /** * This function unbinds a task with cpu core. * * @param id task id * * @return EOK */ x_err_t _KTaskCoreUnCombine(KTaskDescriptorType task) { x_base lock = 0; int ret = EOK; uint8 task_stat = 0; NULL_PARAM_CHECK(task); lock = CriticalAreaLock(); if (0 == strncmp("ktaskidle",task->task_base_info.name, strlen("ktaskidle"))) { KPrintf("IDLE task is forbidden to uncombine cpu.\n"); CriticalAreaUnLock(lock); return -ERROR; } task_stat = KTaskStatGet(task); switch(task_stat) { case KTASK_READY: HwLockSpinlock(&AssignSpinLock); Assign.ready_vector_done->remove(task); task->task_smp_info.combined_coreid = UNCOMBINE_CPU_CORE; Assign.ready_vector_done->insert(task); HwUnlockSpinlock(&AssignSpinLock); break; case KTASK_INIT: case KTASK_SUSPEND: task->task_smp_info.combined_coreid = UNCOMBINE_CPU_CORE; break; case KTASK_CLOSE: case KTASK_RUNNING: KPrintf("the CLOSE and RUNNING stat of task is forbidden to change cpu core.\n"); ret = -ERROR; break; default: KPrintf("%s invalid task stat.\n",__func__); ret = -EINVALED; break; } CriticalAreaUnLock(lock); return ret; } #endif /** * timeout function of task timer,this function removes the suspend task and add to ready queue * then start a new schedule * * @param parameter arg for task timeout function */ void KTaskTimeout(void *parameter) { x_base lock = 0; struct TaskDescriptor *task = NONE; NULL_PARAM_CHECK(parameter); lock = CriticalAreaLock(); task = (struct TaskDescriptor *)parameter; if(RET_TRUE == JudgeKTaskStatIsSuspend(task)) { task->exstatus = -ETIMEOUT; DoubleLinkListRmNode(&(task->task_dync_sched_member.sched_link)); #ifdef ARCH_SMP HwLockSpinlock(&AssignSpinLock); #endif Assign.ready_vector_done->insert(task); #ifdef ARCH_SMP HwUnlockSpinlock(&AssignSpinLock); #endif CriticalAreaUnLock(lock); DO_KTASK_ASSIGN; } else { CriticalAreaUnLock(lock); } } /* * update the exception status * */ void KUpdateExstatus(x_err_t status) { if (status < EOK || status >= INVALID_TASK_ERROR) { KPrintf("Illegal status code %d\n", status); return; } if (isrManager.done->getCounter() == 0) { KTaskDescriptorType CurrentTask; CurrentTask = GetKTaskDescriptor(); if (CurrentTask != NONE) { CurrentTask->exstatus = -status; } else { __exstatus = -status; return; } } else { __exstatus = -status; return; } } /** * obtain current exception status * */ int *KObtainExstatus(void) { if (isrManager.done->getCounter() == 0) { KTaskDescriptorType CurrentTask; CurrentTask = GetKTaskDescriptor(); if (CurrentTask != NONE) { return (int *) & (CurrentTask->exstatus); } else { return (int *)&__exstatus; } } else { return (int *)&__exstatus; } } /** * This function will resume a task. * * @param id task id * */ x_err_t _KTaskWakeup(KTaskDescriptorType task) { x_base lock = 0; NULL_PARAM_CHECK(task); if (RET_TRUE != JudgeKTaskStatIsSuspend(task)) { SYS_KDEBUG_LOG(KDBG_KTASK, ("task stat must be suspend error stat is , %d\n", KTaskStatGet(task))); return -ERROR; } SYS_KDEBUG_LOG(KDBG_KTASK, ("wakeup task name: %s\n", task->task_base_info.name)); lock = CriticalAreaLock(); DoubleLinkListRmNode(&(task->task_dync_sched_member.sched_link)); KTaskUnSetDelay(task); #ifdef ARCH_SMP HwLockSpinlock(&AssignSpinLock); #endif Assign.ready_vector_done->insert(task); #ifdef ARCH_SMP HwUnlockSpinlock(&AssignSpinLock); #endif CriticalAreaUnLock(lock); HOOK(hook.task.hook_TaskResume,(task)); return EOK; } /** * This function will suspend a task. * * @param id task id * */ x_err_t _SuspendKTask(KTaskDescriptorType task) { x_base lock = 0; NULL_PARAM_CHECK(task); if (task != GetKTaskDescriptor()) { SYS_KDEBUG_LOG(KDBG_KTASK, ("running task is forbidden to suspend the others.\n")); return -ERROR; } if(RET_TRUE != JudgeKTaskStatIsReady(task) && RET_TRUE != JudgeKTaskStatIsRunning(task)) { SYS_KDEBUG_LOG(KDBG_KTASK, ("task stat 0x%2x is forbidden to suspend.\n", KTaskStatGet(task))); return -ERROR; } if(RET_TRUE == JudgeKTaskStatIsSuspend(task)) { SYS_KDEBUG_LOG(KDBG_KTASK, ("task stat is already suspend.\n")); return -ERROR; } SYS_KDEBUG_LOG(KDBG_KTASK, ("suspend task name: %s\n", task->task_base_info.name)); lock = CriticalAreaLock(); #ifdef ARCH_SMP HwLockSpinlock(&AssignSpinLock); #endif Assign.ready_vector_done->remove(task); #ifdef ARCH_SMP HwUnlockSpinlock(&AssignSpinLock); #endif KTaskStateSet(task, KTASK_SUSPEND); KTaskUnSetDelay(task); CriticalAreaUnLock(lock); HOOK(hook.task.hook_TaskSuspend,(task)); return EOK; } /** * * kernel task exit function,inster the task to defuction task. * */ void KTaskQuit(void) { x_base lock = 0; struct TaskDescriptor *task = NONE; lock = CriticalAreaLock(); task = GetKTaskDescriptor(); if(NONE != task) { _KTaskResourceDelete(task); DoubleLinkListInsertNodeAfter(&KTaskZombie, &(task->task_dync_sched_member.sched_link)); if (JudgeZombieKTaskIsNotEmpty()) { KTaskWakeup(zombie_recycle); } } CriticalAreaUnLock(lock); DO_KTASK_ASSIGN; } /** * This function will insert task to ready queue then schedule * * @param id task id * */ x_err_t _StartupKTask(KTaskDescriptorType task) { x_base lock = 0; lock = CriticalAreaLock(); NULL_PARAM_CHECK(task); if(JudgeKTaskStatIsInit(task) != RET_TRUE) { SYS_KDEBUG_LOG(KDBG_KTASK, ("task [%s] stat [%d] is not init\n", task->task_base_info.name, task->task_dync_sched_member.stat)); CriticalAreaUnLock(lock); return -ERROR; } task->task_dync_sched_member.cur_prio = task->task_base_info.origin_prio; __BitmapSiteMask(task); DoubleLinkListRmNode(&(task->task_dync_sched_member.sched_link)); KTaskUnSetDelay(task); #ifdef ARCH_SMP HwLockSpinlock(&AssignSpinLock); #endif Assign.ready_vector_done->insert(task); #ifdef ARCH_SMP HwUnlockSpinlock(&AssignSpinLock); #endif CriticalAreaUnLock(lock); SYS_KDEBUG_LOG(KDBG_KTASK, ("task [%s] is ready to run,the priority is [%d]\n", task->task_base_info.name, task->task_base_info.origin_prio)); if (GetKTaskDescriptor() != NONE) { DO_KTASK_ASSIGN; } return EOK; } /** * This function will remove a dynamic task out of the task manage list. * * @param id task id * */ x_err_t _DeleteKTask(KTaskDescriptorType task) { x_base lock = 0; NULL_PARAM_CHECK(task); if(RET_TRUE == __JudgeKTaskIsIdleOrZombierecycle(task)) { KPrintf("idle or zombierecycle is not permitted to delete.\n"); return -EINVALED; } lock = CriticalAreaLock(); _KTaskResourceDelete(task); DoubleLinkListInsertNodeAfter(&KTaskZombie, &(task->task_dync_sched_member.sched_link)); if (JudgeZombieKTaskIsNotEmpty()) { KTaskWakeup(zombie_recycle); } CriticalAreaUnLock(lock); DO_KTASK_ASSIGN; return EOK; } /** * * This function will init a kernel task's base info . * * @param task kernel task descripter * @param name task name * @param entry task process function * @param parameter task arg * @param stack_size task stack size * @param priority task priority * */ static x_err_t _KTaskBaseInfoParse(KTaskDescriptorType task, const char *name, void (*entry)(void *parameter), void *parameter, uint32 stack_depth, uint8 priority) { NULL_PARAM_CHECK(task); NULL_PARAM_CHECK(name); NULL_PARAM_CHECK(entry); if (priority >= KTASK_PRIORITY_MAX) { KPrintf("%s %d Invalid task priority[%d] set.\n",__func__,__LINE__,priority); return -EINVALED; } #ifdef SEPARATE_COMPILE if(1 == task->task_dync_sched_member.isolation_flag ) { task->task_base_info.stack_start = (void *)x_umalloc(stack_depth); } else #endif { task->task_base_info.stack_start = (void *)KERNEL_MALLOC(stack_depth); } if (task->task_base_info.stack_start == NONE) { KPrintf("%s %d malloc task %s stack depth %d failed.\n",__func__,__LINE__,name,stack_depth); return -ENOMEMORY; } task->task_base_info.stack_depth = stack_depth; memset(task->task_base_info.stack_start, '#', task->task_base_info.stack_depth); strncpy(task->task_base_info.name, name, NAME_NUM_MAX); task->task_base_info.func_entry = (void *)entry; task->task_base_info.func_param = parameter; task->task_base_info.origin_prio = priority; KTaskStackSetup(task); return EOK; } /** * * This function will init a kernel task's dynamic member . * * @param task task descriptor * @param tick task time slice */ static void _KTaskDyncMemberInit(KTaskDescriptorType task) { NULL_PARAM_CHECK(task); InitDoubleLinkList(&(task->task_dync_sched_member.sched_link)); task->task_dync_sched_member.cur_prio = task->task_base_info.origin_prio; task->task_dync_sched_member.bitmap_column = 0; #if KTASK_PRIORITY_MAX > 32 task->task_dync_sched_member.bitmap_offset = 0; task->task_dync_sched_member.bitmap_row = 0; #endif #if defined(SCHED_POLICY_FIFO) FifoTaskTimesliceInit(task); #elif defined (SCHED_POLICY_RR) RoundRobinTaskTimesliceInit(task); #elif defined (SCHED_POLICY_RR_REMAINSLICE) RoundRobinRemainTaskTimesliceInit(task); #endif task->task_dync_sched_member.advance_cnt = 0; task->exstatus = EOK; KTaskStatSetAsInit(task); } #ifdef ARCH_SMP /** * * This function will init a kernel task's smp info . * * @param task task descriptor */ static void _KTaskSmpInfoInit(KTaskDescriptorType task) { NULL_PARAM_CHECK(task); task->task_smp_info.combined_coreid = UNCOMBINE_CPU_CORE; task->task_smp_info.runing_coreid = UNCOMBINE_CPU_CORE; task->task_smp_info.critical_lock_cnt = 0; } #endif /** * * This function init a kernel task in dynamic way . * * @param name task name * @param parameter task process function * @param parameter task arg * @param stack_size task stack size * @param priority task priority * @param tick task time slice */ int32 _InitKTask(KTaskDescriptorType task, const char *name, void (*entry)(void *parameter), void *parameter, uint32 stack_depth, uint8 priority) { int32 ret = 0; NULL_PARAM_CHECK(task); ret = _KTaskBaseInfoParse(task, name, entry, parameter, stack_depth, priority); if (ret < 0) { KPrintf("%s %d task %s baseinfo parse failed.\n",__func__,__LINE__,name); return -ERROR; } _KTaskDyncMemberInit(task); #ifdef ARCH_SMP _KTaskSmpInfoInit(task); #endif return EOK; } static struct KTaskDone Done = { .init = _InitKTask, .start = _StartupKTask, .Delete = _DeleteKTask, .delay = _DelayKTask, .mdelay = _MdelayKTask, .prioset = _KTaskPrioSet, #ifdef ARCH_SMP .combine = _KTaskCoreCombine, .uncombine = _KTaskCoreUnCombine, #endif .suspend = _SuspendKTask, .wake = _KTaskWakeup }; /** * * This function init a kernel task in dynamic way . * * @param name task name * @param parameter task process function * @param parameter task arg * @param stack_size task stack size * @param priority task priority * @param tick task time slice * * @return EOK on success; ERROR/ENOMEMORY on failure */ int32 KTaskCreate(const char *name, void (*entry)(void *parameter), void *parameter, uint32 stack_depth, uint8 priority) { struct TaskDescriptor *task = NONE; int32 id = 0; x_base lock = 0; KDEBUG_NOT_IN_INTERRUPT; task = (struct TaskDescriptor *)KERNEL_MALLOC(sizeof(struct TaskDescriptor)); if (task == NONE) { KPrintf("%s %d TaskDescriptor %s malloc failed.\n",__func__,__LINE__,name); return -ENOMEMORY; } memset(task, 0x0, sizeof(struct TaskDescriptor)); lock = CriticalAreaLock(); id = IdInsertObj(&k_task_id_manager, &task->id); if (id < 0) { KPrintf("%s %d task id malloc failed.\n",__func__,__LINE__); CriticalAreaUnLock(lock); KERNEL_FREE(task); return -ENOMEMORY; } DoubleLinkListInsertNodeAfter(&xiaoshan_task_head, &(task->link)); task->Done = &Done; CriticalAreaUnLock(lock); if( task->Done->init(task, name, entry, parameter, stack_depth, priority) == EOK ) { HOOK(hook.task.hook_TaskCreate, (task)); return id; } else { KPrintf("%s %d task init failed.\n",__func__,__LINE__); lock = CriticalAreaLock(); IdRemoveObj(&k_task_id_manager, id); CriticalAreaUnLock(lock); KERNEL_FREE(task); return -ERROR; } } /** * This function will insert task to ready queue then schedule * * @param id task id * * @return EOK on success; EINVALED on failure */ x_err_t StartupKTask(int32 id) { struct TaskDescriptor *task = NONE; if(id < 0) { return -EINVALED; } task = GetTaskWithIdnodeInfo(id); NULL_PARAM_CHECK(task); return task->Done->start(task); } /** * This function will remove a dynamic task out of the task manage list. * * @param id task id * * @return EOK on success; EINVALED on failure */ x_err_t KTaskDelete(int32 id) { struct TaskDescriptor *task = NONE; if(id < 0) { return -EINVALED; } task = GetTaskWithIdnodeInfo(id); NULL_PARAM_CHECK(task); return task->Done->Delete(task); } /** * This function will delay current task running with some ticks. * * @param tick delay ticks * @return EOK on success; EINVALED/EEMPTY on failure */ x_err_t DelayKTask(x_ticks_t ticks) { KTaskDescriptorType task = NONE; if (ticks == 0) { KPrintf("Timeout ticks must be setted more than 0.\n"); return -EINVALED; } task = GetKTaskDescriptor(); if (task == NONE) { return -EEMPTY; } return task->Done->delay(task, ticks); } /** * This function will delay current task wite milliseconds. * * @param ms milliseconds of delay time * * @return EOK on success; EINVALED/EEMPTY on failure * */ x_err_t MdelayKTask(uint32 ms) { KTaskDescriptorType task = NONE; if (0 == ms) { return -EINVALED; } task = GetKTaskDescriptor(); if (task == NONE) { return -EEMPTY; } return task->Done->mdelay(task, ms); } /** * This function sets the task's priority. * * @param id task id * @param prio priority value * * @return EOK */ x_err_t KTaskPrioSet(int32 id, uint8 prio) { struct TaskDescriptor *task = NONE; task = GetTaskWithIdnodeInfo(id); NULL_PARAM_CHECK(task); return task->Done->prioset(task, prio); } #ifdef ARCH_SMP /** * This function binds a task to cpu core. * * @param id task id * @param coreid cpu core id * * @return EOK */ x_err_t KTaskCoreCombine(int32 id, uint8 coreid) { struct TaskDescriptor *task = NONE; task = GetTaskWithIdnodeInfo(id); NULL_PARAM_CHECK(task); return task->Done->combine(task,coreid); } /** * This function unbinds a task with cpu core. * * @param id task id * * @return EOK */ x_err_t KTaskCoreUnCombine(int32 id) { struct TaskDescriptor *task = NONE; task = GetTaskWithIdnodeInfo(id); NULL_PARAM_CHECK(task); return task->Done->uncombine(task); } #endif /** * This function will suspend a task. * * @param id task id * * @return EOK */ x_err_t SuspendKTask(int32 id) { struct TaskDescriptor *task = NONE; task = GetTaskWithIdnodeInfo(id); NULL_PARAM_CHECK(task); return task->Done->suspend(task); } /** * This function will resume a task. * * @param id task id * * @return EOK */ x_err_t KTaskWakeup(int32 id) { x_base lock = 0; struct TaskDescriptor *task = NONE; task = GetTaskWithIdnodeInfo(id); NULL_PARAM_CHECK(task); return task->Done->wake(task); } #ifdef SEPARATE_COMPILE /** * * This function init a user task in dynamic way . * * @param name task name * @param parameter task process function * @param parameter task arg * @param stack_size task stack size * @param priority task priority * @param tick task time slice * * @return EOK on success; ENOMEMORY/EEMPTY on failure */ int32 UTaskCreate(const char *name, void (*entry)(void *parameter), void *parameter, uint32 stack_depth, uint8 priority) { struct TaskDescriptor *task = NONE; int32 id = 0; x_base lock = 0; KDEBUG_NOT_IN_INTERRUPT; KPrintf("create user task.\n"); task = (struct TaskDescriptor *)KERNEL_MALLOC(sizeof(struct TaskDescriptor)); if (task == NONE) { KPrintf("%s %d TaskDescriptor malloc failed.\n",__func__,__LINE__); return -ENOMEMORY; } memset(task, 0x0, sizeof(struct TaskDescriptor)); task->task_dync_sched_member.isolation_flag = 1; task->task_dync_sched_member.isolation_status = 0; lock = CriticalAreaLock(); id = IdInsertObj(&k_task_id_manager, &task->id); if (id < 0) { KPrintf("%s %d task id malloc failed.\n",__func__,__LINE__); CriticalAreaUnLock(lock); KERNEL_FREE(task); return -ENOMEMORY; } DoubleLinkListInsertNodeAfter(&xiaoshan_task_head, &(task->link)); task->Done = &Done; CriticalAreaUnLock(lock); if( task->Done->init(task, name, entry, parameter, stack_depth, priority) == EOK ) { HOOK(hook.task.hook_TaskCreate, (task)); #ifdef MOMERY_PROTECT_ENABLE //setup pmp if( mem_access.InitIsolation != NONE) { mem_access.InitIsolation(&task->task_dync_sched_member.isolation, (x_ubase)task->task_base_info.stack_start , task->task_base_info.stack_depth); } #endif return id; } else { KPrintf("%s %d task init failed.\n",__func__,__LINE__); lock = CriticalAreaLock(); IdRemoveObj(&k_task_id_manager, id); CriticalAreaUnLock(lock); KERNEL_FREE(task); return -ERROR; } } #endif