diff --git a/kernel/syscall.c b/kernel/syscall.c index 8ad87e0..c724ae9 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -278,8 +278,8 @@ int sys_task_spawn(void *task, int stack_size) static int _tcancel(int id) { - if (unlikely(id <= 0)) - return -EINVAL; + if (id <= 0 || (uint16_t) id != mo_task_id()) + return -EPERM; return mo_task_cancel(id); } @@ -316,8 +316,8 @@ int sys_tdelay(int ticks) static int _tsuspend(int id) { - if (unlikely(id <= 0)) - return -EINVAL; + if (id <= 0 || (uint16_t) id != mo_task_id()) + return -EPERM; return mo_task_suspend(id); } @@ -329,10 +329,9 @@ int sys_tsuspend(int id) static int _tresume(int id) { - if (unlikely(id <= 0)) - return -EINVAL; - - return mo_task_resume(id); + (void) id; + /* U-mode cannot resume any task; suspended task cannot call syscall */ + return -EPERM; } int sys_tresume(int id) @@ -342,8 +341,8 @@ int sys_tresume(int id) static int _tpriority(int id, int priority) { - if (unlikely(id <= 0)) - return -EINVAL; + if (id <= 0 || (uint16_t) id != mo_task_id()) + return -EPERM; return mo_task_priority(id, priority); } diff --git a/kernel/task.c b/kernel/task.c index 286e83e..e6f694d 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -992,9 +992,20 @@ int32_t mo_task_spawn_user(void *task_entry, uint16_t stack_size) int32_t mo_task_cancel(uint16_t id) { - if (id == 0 || id == mo_task_id()) + if (id == 0) return ERR_TASK_CANT_REMOVE; + /* Self-termination marks the task as zombie and yields to the scheduler. + * The dispatcher will reclaim resources after context switch completes. + */ + if (id == mo_task_id()) { + tcb_t *self = kcb->task_current->data; + self->state = TASK_ZOMBIE; + _yield(); + while (1) + ; + } + CRITICAL_ENTER(); list_node_t *node = find_task_node_by_id(id); if (!node) {