From b1d92159fadfaed2127d2de00beec70feb08e261 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 11 May 2022 09:03:04 +0300 Subject: [PATCH] sched: Remove task_delete in case of CONFIG_BUILD_KERNEL Deleting a task from another task's context will not do, so shut this gate down for BUILD_KERNEL. In this case if a task wants another task to terminate, it must ask the other task to politely kill itself. Note: kthreads still need this, also, the kernel can delete a task without asking. --- include/nuttx/kthread.h | 9 +- include/sys/syscall_lookup.h | 3 +- sched/task/task_delete.c | 189 ++++++++++++++++++++--------------- syscall/syscall.csv | 2 +- 4 files changed, 117 insertions(+), 86 deletions(-) diff --git a/include/nuttx/kthread.h b/include/nuttx/kthread.h index a1d9a91656..7107996f2a 100644 --- a/include/nuttx/kthread.h +++ b/include/nuttx/kthread.h @@ -154,20 +154,19 @@ int kthread_create(FAR const char *name, int priority, int stack_size, * function is equivalent to task_delete.c; the following definition * simply reserves the name in the name space. * - * Refer to comments with task_delete() for a more detailed description of - * the operation of this function. + * Refer to comments with nxtask_delete() for a more detailed description + * of the operation of this function. * * Input Parameters: * pid - The task ID of the task to delete. A pid of zero * signifies the calling task. * * Returned Value: - * OK on success; or ERROR on failure with the errno variable set - * appropriately. + * OK on success; or negated errno on failure. * ****************************************************************************/ -#define kthread_delete(p) task_delete(p) +#define kthread_delete(p) nxtask_delete(p) #undef EXTERN #ifdef __cplusplus diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 201ea50846..6af2547def 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -92,10 +92,11 @@ SYSCALL_LOOKUP(sem_wait, 1) #ifndef CONFIG_BUILD_KERNEL SYSCALL_LOOKUP(task_create, 5) SYSCALL_LOOKUP(task_spawn, 6) + SYSCALL_LOOKUP(task_delete, 1) #else SYSCALL_LOOKUP(pgalloc, 2) #endif -SYSCALL_LOOKUP(task_delete, 1) + SYSCALL_LOOKUP(task_restart, 1) SYSCALL_LOOKUP(task_setcancelstate, 2) SYSCALL_LOOKUP(up_assert, 2) diff --git a/sched/task/task_delete.c b/sched/task/task_delete.c index 39608eb033..1234cec19b 100644 --- a/sched/task/task_delete.c +++ b/sched/task/task_delete.c @@ -37,6 +37,110 @@ * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: nxtask_delete + * + * Description: + * This function causes a specified task to cease to exist. Its stack and + * TCB will be deallocated. + * + * The logic in this function only deletes non-running tasks. If the + * 'pid' parameter refers to the currently running task, then processing + * is redirected to exit(). This can only happen if a task calls + * nxtask_delete() in order to delete itself. + * + * This function obeys the semantics of pthread cancellation: task + * deletion is deferred if cancellation is disabled or if deferred + * cancellation is supported (with cancellation points enabled). + * + * Input Parameters: + * pid - The task ID of the task to delete. A pid of zero + * signifies the calling task. + * + * Returned Value: + * OK on success; or negated errno on failure + * + ****************************************************************************/ + +int nxtask_delete(pid_t pid) +{ + FAR struct tcb_s *dtcb; + FAR struct tcb_s *rtcb; + int ret; + + /* Check if the task to delete is the calling task: PID=0 means to delete + * the calling task. In this case, task_delete() is much like exit() + * except that it obeys the cancellation semantics. + */ + + rtcb = this_task(); + if (pid == 0) + { + pid = rtcb->pid; + } + + /* Get the TCB of the task to be deleted */ + + dtcb = (FAR struct tcb_s *)nxsched_get_tcb(pid); + if (dtcb == NULL) + { + /* The pid does not correspond to any known thread. The task + * has probably already exited. + */ + + return -ESRCH; + } + + /* Only tasks and kernel threads can be deleted with this interface + * (The semantics of the call should be sufficient to prohibit this). + */ + + DEBUGASSERT((dtcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD); + + /* Non-privileged tasks and pthreads may not delete privileged kernel + * threads. + * + * REVISIT: We will need to look at this again in the future if/when + * permissions are supported and a user task might also be privileged. + */ + + if (((rtcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) && + ((dtcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL)) + { + return -EACCES; + } + + /* Check if the task to delete is the calling task */ + + if (pid == rtcb->pid) + { + /* If it is, then what we really wanted to do was exit. Note that we + * don't bother to unlock the TCB since it will be going away. + */ + + exit(EXIT_SUCCESS); + } + + /* Notify the target if the non-cancelable or deferred cancellation set */ + + if (nxnotify_cancellation(dtcb)) + { + return OK; + } + + /* Otherwise, perform the asynchronous cancellation, letting + * nxtask_terminate() do all of the heavy lifting. + */ + + ret = nxtask_terminate(pid, false); + if (ret < 0) + { + return ret; + } + + return OK; +} + /**************************************************************************** * Name: task_delete * @@ -66,89 +170,16 @@ * ****************************************************************************/ +#ifndef CONFIG_BUILD_KERNEL int task_delete(pid_t pid) { - FAR struct tcb_s *dtcb; - FAR struct tcb_s *rtcb; - int errcode; - int ret; - - /* Check if the task to delete is the calling task: PID=0 means to delete - * the calling task. In this case, task_delete() is much like exit() - * except that it obeys the cancellation semantics. - */ - - rtcb = this_task(); - if (pid == 0) - { - pid = rtcb->pid; - } - - /* Get the TCB of the task to be deleted */ - - dtcb = (FAR struct tcb_s *)nxsched_get_tcb(pid); - if (dtcb == NULL) - { - /* The pid does not correspond to any known thread. The task - * has probably already exited. - */ - - errcode = ESRCH; - goto errout; - } - - /* Only tasks and kernel threads can be deleted with this interface - * (The semantics of the call should be sufficient to prohibit this). - */ - - DEBUGASSERT((dtcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD); - - /* Non-privileged tasks and pthreads may not delete privileged kernel - * threads. - * - * REVISIT: We will need to look at this again in the future if/when - * permissions are supported and a user task might also be privileged. - */ - - if (((rtcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) && - ((dtcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL)) - { - errcode = EACCES; - goto errout; - } - - /* Check if the task to delete is the calling task */ - - if (pid == rtcb->pid) - { - /* If it is, then what we really wanted to do was exit. Note that we - * don't bother to unlock the TCB since it will be going away. - */ - - exit(EXIT_SUCCESS); - } - - /* Notify the target if the non-cancelable or deferred cancellation set */ - - if (nxnotify_cancellation(dtcb)) - { - return OK; - } - - /* Otherwise, perform the asynchronous cancellation, letting - * nxtask_terminate() do all of the heavy lifting. - */ - - ret = nxtask_terminate(pid, false); + int ret = nxtask_delete(pid); if (ret < 0) { - errcode = -ret; - goto errout; + set_errno(-ret); + ret = ERROR; } - return OK; - -errout: - set_errno(errcode); - return ERROR; + return ret; } +#endif diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 448cd3a0d8..ede18e7113 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -172,7 +172,7 @@ "symlink","unistd.h","defined(CONFIG_PSEUDOFS_SOFTLINKS)","int","FAR const char *","FAR const char *" "sysinfo","sys/sysinfo.h","","int","FAR struct sysinfo *" "task_create","sched.h","!defined(CONFIG_BUILD_KERNEL)", "int","FAR const char *","int","int","main_t","FAR char * const []|FAR char * const *" -"task_delete","sched.h","","int","pid_t" +"task_delete","sched.h","!defined(CONFIG_BUILD_KERNEL)","int","pid_t" "task_restart","sched.h","","int","pid_t" "task_setcancelstate","sched.h","","int","int","FAR int *" "task_setcanceltype","sched.h","defined(CONFIG_CANCELLATION_POINTS)","int","int","FAR int *"