From 0dedbcd4aea446d46b527ef8a9b6ef7baa469d97 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Fri, 10 Nov 2023 12:56:10 +0200 Subject: [PATCH] task/pthread_cancelpt: Move cancel point handling to libc, data to TLS This moves task / thread cancel point logic from the NuttX kernel into libc, while the data needed by the cancel point logic is moved to TLS. The change is an enabler to move user-space APIs to libc as well, for a coherent user/kernel separation. --- fs/procfs/fs_procfsproc.c | 4 +- include/nuttx/cancelpt.h | 8 + include/nuttx/sched.h | 25 +- include/nuttx/tls.h | 27 +- include/sys/syscall_lookup.h | 7 - libs/libc/sched/CMakeLists.txt | 10 +- libs/libc/sched/Make.defs | 6 +- libs/libc/sched/task_cancelpt.c | 258 ++++++++++++++++++ .../libc/sched}/task_setcancelstate.c | 44 ++- libs/libc/sched/task_setcanceltype.c | 63 ++++- libs/libc/sched/task_testcancel.c | 9 + libs/libc/tls/tls_getinfo.c | 8 +- sched/group/group_killchildren.c | 14 +- sched/init/nx_start.c | 7 +- sched/misc/assert.c | 4 +- sched/pthread/pthread_create.c | 6 - sched/task/CMakeLists.txt | 5 - sched/task/Make.defs | 8 +- sched/task/task_cancelpt.c | 248 +---------------- sched/task/task_exithook.c | 11 - sched/task/task_setcanceltype.c | 128 --------- sched/task/task_setup.c | 6 - sched/task/task_testcancel.c | 52 ---- syscall/syscall.csv | 3 - 24 files changed, 414 insertions(+), 547 deletions(-) create mode 100644 libs/libc/sched/task_cancelpt.c rename {sched/task => libs/libc/sched}/task_setcancelstate.c (79%) delete mode 100644 sched/task/task_setcanceltype.c delete mode 100644 sched/task/task_testcancel.c diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index 04c83d53f7c..c0289f64361 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -578,9 +578,7 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile, /* Show task flags */ linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, - "%-12s%c%c%c\n", "Flags:", - tcb->flags & TCB_FLAG_NONCANCELABLE ? 'N' : '-', - tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : '-', + "%-12s%c\n", "Flags:", tcb->flags & TCB_FLAG_EXIT_PROCESSING ? 'P' : '-'); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, diff --git a/include/nuttx/cancelpt.h b/include/nuttx/cancelpt.h index f76be1885e5..014fb77cc88 100644 --- a/include/nuttx/cancelpt.h +++ b/include/nuttx/cancelpt.h @@ -58,6 +58,14 @@ #include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CANCEL_FLAG_NONCANCELABLE (1 << 0) /* Pthread is non-cancelable */ +#define CANCEL_FLAG_CANCEL_ASYNC (1 << 1) /* Async (vs deferred) cancellation type */ +#define CANCEL_FLAG_CANCEL_PENDING (1 << 2) /* Pthread cancel is pending */ + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 6e44489b6df..c9581456ed2 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -89,22 +89,20 @@ # define TCB_FLAG_TTYPE_TASK (0 << TCB_FLAG_TTYPE_SHIFT) /* Normal user task */ # define TCB_FLAG_TTYPE_PTHREAD (1 << TCB_FLAG_TTYPE_SHIFT) /* User pthread */ # define TCB_FLAG_TTYPE_KERNEL (2 << TCB_FLAG_TTYPE_SHIFT) /* Kernel thread */ -#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */ -#define TCB_FLAG_CANCEL_DEFERRED (1 << 3) /* Bit 3: Deferred (vs asynch) cancellation type */ -#define TCB_FLAG_CANCEL_PENDING (1 << 4) /* Bit 4: Pthread cancel is pending */ -#define TCB_FLAG_POLICY_SHIFT (5) /* Bit 5-6: Scheduling policy */ +#define TCB_FLAG_POLICY_SHIFT (3) /* Bit 3-4: Scheduling policy */ #define TCB_FLAG_POLICY_MASK (3 << TCB_FLAG_POLICY_SHIFT) # define TCB_FLAG_SCHED_FIFO (0 << TCB_FLAG_POLICY_SHIFT) /* FIFO scheding policy */ # define TCB_FLAG_SCHED_RR (1 << TCB_FLAG_POLICY_SHIFT) /* Round robin scheding policy */ # define TCB_FLAG_SCHED_SPORADIC (2 << TCB_FLAG_POLICY_SHIFT) /* Sporadic scheding policy */ -#define TCB_FLAG_CPU_LOCKED (1 << 8) /* Bit 7: Locked to this CPU */ -#define TCB_FLAG_SIGNAL_ACTION (1 << 9) /* Bit 8: In a signal handler */ -#define TCB_FLAG_SYSCALL (1 << 10) /* Bit 9: In a system call */ -#define TCB_FLAG_EXIT_PROCESSING (1 << 11) /* Bit 10: Exitting */ -#define TCB_FLAG_FREE_STACK (1 << 12) /* Bit 12: Free stack after exit */ -#define TCB_FLAG_HEAP_CHECK (1 << 13) /* Bit 13: Heap check */ -#define TCB_FLAG_HEAP_DUMP (1 << 14) /* Bit 14: Heap dump */ -#define TCB_FLAG_DETACHED (1 << 15) /* Bit 15: Pthread detached */ +#define TCB_FLAG_CPU_LOCKED (1 << 5) /* Bit 5: Locked to this CPU */ +#define TCB_FLAG_SIGNAL_ACTION (1 << 6) /* Bit 6: In a signal handler */ +#define TCB_FLAG_SYSCALL (1 << 7) /* Bit 7: In a system call */ +#define TCB_FLAG_EXIT_PROCESSING (1 << 8) /* Bit 8: Exitting */ +#define TCB_FLAG_FREE_STACK (1 << 9) /* Bit 9: Free stack after exit */ +#define TCB_FLAG_HEAP_CHECK (1 << 10) /* Bit 10: Heap check */ +#define TCB_FLAG_HEAP_DUMP (1 << 11) /* Bit 11: Heap dump */ +#define TCB_FLAG_DETACHED (1 << 12) /* Bit 12: Pthread detached */ +#define TCB_FLAG_FORCED_CANCEL (1 << 13) /* Bit 13: Pthread cancel is forced */ /* Values for struct task_group tg_flags */ @@ -572,9 +570,6 @@ struct tcb_s int16_t lockcount; /* 0=preemptible (not-locked) */ #ifdef CONFIG_IRQCOUNT int16_t irqcount; /* 0=Not in critical section */ -#endif -#ifdef CONFIG_CANCELLATION_POINTS - int16_t cpcount; /* Nested cancellation point count */ #endif int16_t errcode; /* Used to pass error information */ diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h index cfdf063fecb..967c6194bbc 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -206,6 +206,12 @@ struct tls_info_s struct pthread_cleanup_s tl_stack[CONFIG_PTHREAD_CLEANUP_STACKSIZE]; #endif + uint8_t tl_cpstate; /* Cancellation state */ + +#ifdef CONFIG_CANCELLATION_POINTS + int16_t tl_cpcount; /* Nested cancellation point count */ +#endif + int tl_errno; /* Per-thread error number */ }; @@ -310,9 +316,28 @@ uintptr_t task_tls_get_value(int tlsindex); #elif defined(CONFIG_TLS_ALIGNED) && !defined(__KERNEL__) # define tls_get_info() TLS_INFO(up_getsp()) #else -FAR struct tls_info_s *tls_get_info(void); +# define tls_get_info() tls_get_info_pid(0) #endif +/**************************************************************************** + * Name: tls_get_info_pid + * + * Description: + * Return a reference to the tls_info_s structure. This is used as part + * of the internal implementation of tls_get/set_elem() and ONLY for the + * where CONFIG_TLS_ALIGNED is *not* defined or __KERNEL__ is defined. + * + * Input Parameters: + * pid - Thread ID to query, set to 0 to query own + * + * Returned Value: + * A reference to the thread-specific tls_info_s structure is return on + * success. NULL would be returned in the event of any failure. + * + ****************************************************************************/ + +FAR struct tls_info_s *tls_get_info_pid(pid_t pid); + /**************************************************************************** * Name: tls_destruct * diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index ffc0efbfbe1..e624362175a 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -105,13 +105,6 @@ SYSCALL_LOOKUP(sem_wait, 1) SYSCALL_LOOKUP(pgalloc, 2) #endif -SYSCALL_LOOKUP(task_setcancelstate, 2) - -#ifdef CONFIG_CANCELLATION_POINTS - SYSCALL_LOOKUP(task_setcanceltype, 2) - SYSCALL_LOOKUP(task_testcancel, 0) -#endif - /* The following can be individually enabled */ #ifdef CONFIG_ARCH_HAVE_FORK diff --git a/libs/libc/sched/CMakeLists.txt b/libs/libc/sched/CMakeLists.txt index fd4630c2a8c..7436860ce68 100644 --- a/libs/libc/sched/CMakeLists.txt +++ b/libs/libc/sched/CMakeLists.txt @@ -26,11 +26,11 @@ set(SRCS clock_timespec_add.c clock_timespec_subtract.c clock_getcpuclockid.c - clock_getres.c) - -if(NOT CONFIG_CANCELLATION_POINTS) - list(APPEND SRCS task_setcanceltype.c task_testcancel.c) -endif() + clock_getres.c + task_cancelpt.c + task_setcancelstate.c + task_setcanceltype.c + task_testcancel.c) if(CONFIG_SMP) list(APPEND SRCS sched_cpucount.c) diff --git a/libs/libc/sched/Make.defs b/libs/libc/sched/Make.defs index e62603aa7cd..123151b16f9 100644 --- a/libs/libc/sched/Make.defs +++ b/libs/libc/sched/Make.defs @@ -24,10 +24,8 @@ CSRCS += sched_getprioritymax.c sched_getprioritymin.c CSRCS += clock_ticks2time.c clock_time2ticks.c CSRCS += clock_timespec_add.c clock_timespec_subtract.c CSRCS += clock_getcpuclockid.c clock_getres.c - -ifneq ($(CONFIG_CANCELLATION_POINTS),y) -CSRCS += task_setcanceltype.c task_testcancel.c -endif +CSRCS += task_cancelpt.c task_setcancelstate.c task_setcanceltype.c +CSRCS += task_testcancel.c ifeq ($(CONFIG_SMP),y) CSRCS += sched_cpucount.c diff --git a/libs/libc/sched/task_cancelpt.c b/libs/libc/sched/task_cancelpt.c new file mode 100644 index 00000000000..b15cd807f29 --- /dev/null +++ b/libs/libc/sched/task_cancelpt.c @@ -0,0 +1,258 @@ +/**************************************************************************** + * libs/libc/sched/task_cancelpt.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Cancellation Points. + * + * Cancellation points shall occur when a thread is executing the following + * functions: + * + * accept() mq_timedsend() putpmsg() sigtimedwait() + * aio_suspend() msgrcv() pwrite() sigwait() + * clock_nanosleep() msgsnd() read() sigwaitinfo() + * close() msync() readv() sleep() + * connect() nanosleep() recv() system() + * creat() open() recvfrom() tcdrain() + * fcntl() pause() recvmsg() usleep() + * fdatasync() poll() select() wait() + * fsync() pread() sem_timedwait() waitid() + * getmsg() pselect() sem_wait() waitpid() + * getpmsg() pthread_cond_timedwait() send() write() + * lockf() pthread_cond_wait() sendmsg() writev() + * mq_receive() pthread_join() sendto() + * mq_send() pthread_testcancel() sigpause() + * mq_timedreceive() putmsg() sigsuspend() + * + * Each of the above function must call enter_cancellation_point() on entry + * in order to establish the cancellation point and + * leave_cancellation_point() on exit. These functions are described below. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_CANCELLATION_POINTS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: enter_cancellation_point + * + * Description: + * Called at the beginning of the cancellation point to establish the + * cancellation point. This function does the following: + * + * 1. If deferred cancellation does not apply to this thread, nothing is + * done, otherwise, it + * 2. Sets state information in the caller's TCB and increments a nesting + * count. + * 3. If this is the outermost nesting level, it checks if there is a + * pending cancellation and, if so, calls either exit() or + * pthread_exit(), depending upon the type of the thread. + * + * Input Parameters: + * None + * + * Returned Value: + * true is returned if a cancellation is pending but cannot be performed + * now due to the nesting level. + * + ****************************************************************************/ + +bool enter_cancellation_point(void) +{ + FAR struct tls_info_s *tls = tls_get_info(); + bool ret = false; + + /* If cancellation is disabled on this thread or if this thread is using + * asynchronous cancellation, then do nothing. + * + * Special case: if the cpcount count is greater than zero, then we are + * nested and the above condition was certainly true at the outermost + * nesting level. + */ + + if (((tls->tl_cpstate & CANCEL_FLAG_NONCANCELABLE) == 0 && + (tls->tl_cpstate & CANCEL_FLAG_CANCEL_ASYNC) == 0) || + tls->tl_cpcount > 0) + { + /* Check if there is a pending cancellation */ + + if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_PENDING) != 0) + { + /* Yes... return true (if we don't exit here) */ + + ret = true; + + /* If there is a pending cancellation and we are at the outermost + * nesting level of cancellation function calls, then exit + * according to the type of the thread. + */ + + if (tls->tl_cpcount == 0) + { +#ifndef CONFIG_DISABLE_PTHREAD + pthread_exit(PTHREAD_CANCELED); +#else + exit(EXIT_FAILURE); +#endif + } + } + + /* Otherwise, indicate that we are at a cancellation point by + * incrementing the nesting level of the cancellation point + * functions. + */ + + DEBUGASSERT(tls->tl_cpcount < INT16_MAX); + tls->tl_cpcount++; + } + + return ret; +} + +/**************************************************************************** + * Name: leave_cancellation_point + * + * Description: + * Called at the end of the cancellation point. This function does the + * following: + * + * 1. If deferred cancellation does not apply to this thread, nothing is + * done, otherwise, it + * 2. Clears state information in the caller's TCB and decrements a + * nesting count. + * 3. If this is the outermost nesting level, it checks if there is a + * pending cancellation and, if so, calls either exit() or + * pthread_exit(), depending upon the type of the thread. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void leave_cancellation_point(void) +{ + FAR struct tls_info_s *tls = tls_get_info(); + + /* If cancellation is disabled on this thread or if this thread is using + * asynchronous cancellation, then do nothing. Here we check only the + * nesting level: if the cpcount count is greater than zero, then the + * required condition was certainly true at the outermost nesting level. + */ + + if (tls->tl_cpcount > 0) + { + /* Decrement the nesting level. If if would decrement to zero, then + * we are at the outermost nesting level and may need to do more. + */ + + if (tls->tl_cpcount == 1) + { + /* We are no longer at the cancellation point */ + + tls->tl_cpcount = 0; + + /* If there is a pending cancellation then just exit according to + * the type of the thread. + */ + + if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_PENDING) != 0) + { +#ifndef CONFIG_DISABLE_PTHREAD + pthread_exit(PTHREAD_CANCELED); +#else + exit(EXIT_FAILURE); +#endif + } + } + else + { + /* We are not at the outermost nesting level. Just decrment the + * nesting level count. + */ + + tls->tl_cpcount--; + } + } +} + +/**************************************************************************** + * Name: check_cancellation_point + * + * Description: + * Returns true if: + * + * 1. Deferred cancellation does applies to this thread, + * 2. We are within a cancellation point (i.e., the nesting level in the + * TCB is greater than zero). + * + * Input Parameters: + * None + * + * Returned Value: + * true is returned if a cancellation is pending but cannot be performed + * now due to the nesting level. + * + ****************************************************************************/ + +bool check_cancellation_point(void) +{ + FAR struct tls_info_s *tls = tls_get_info(); + bool ret = false; + + /* If cancellation is disabled on this thread or if this thread is using + * asynchronous cancellation, then return false. + * + * If the cpcount count is greater than zero, then we within a + * cancellation and will true if there is a pending cancellation. + */ + + if (((tls->tl_cpstate & CANCEL_FLAG_NONCANCELABLE) == 0 && + (tls->tl_cpstate & CANCEL_FLAG_CANCEL_ASYNC) == 0) || + tls->tl_cpcount > 0) + { + /* Check if there is a pending cancellation. If so, return true. */ + + ret = ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_PENDING) != 0); + } + + return ret; +} + +#endif /* CONFIG_CANCELLATION_POINTS */ diff --git a/sched/task/task_setcancelstate.c b/libs/libc/sched/task_setcancelstate.c similarity index 79% rename from sched/task/task_setcancelstate.c rename to libs/libc/sched/task_setcancelstate.c index 2d384eac14d..e329dc69206 100644 --- a/sched/task/task_setcancelstate.c +++ b/libs/libc/sched/task_setcancelstate.c @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/task/task_setcancelstate.c + * libs/libc/sched/task_setcancelstate.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -24,13 +24,14 @@ #include -#include -#include #include +#include #include +#include +#include -#include "sched/sched.h" -#include "task/task.h" +#include +#include /**************************************************************************** * Public Functions @@ -61,20 +62,14 @@ int task_setcancelstate(int state, FAR int *oldstate) { - FAR struct tcb_s *tcb = this_task(); + FAR struct tls_info_s *tls = tls_get_info(); int ret = OK; - /* Suppress context changes for a bit so that the flags are stable. (the - * flags should not change in interrupt handling). - */ - - sched_lock(); - /* Return the current state if so requested */ if (oldstate != NULL) { - if ((tcb->flags & TCB_FLAG_NONCANCELABLE) != 0) + if ((tls->tl_cpstate & CANCEL_FLAG_NONCANCELABLE) != 0) { *oldstate = TASK_CANCEL_DISABLE; } @@ -90,35 +85,29 @@ int task_setcancelstate(int state, FAR int *oldstate) { /* Clear the non-cancelable flag */ - tcb->flags &= ~TCB_FLAG_NONCANCELABLE; + tls->tl_cpstate &= ~CANCEL_FLAG_NONCANCELABLE; /* Check if a cancellation was pending */ - if ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0) + if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_PENDING) != 0) { #ifdef CONFIG_CANCELLATION_POINTS /* If we are using deferred cancellation? */ - if ((tcb->flags & TCB_FLAG_CANCEL_DEFERRED) == 0) + if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_ASYNC) != 0) #endif { /* No.. We are using asynchronous cancellation. If the * cancellation was pending in this case, then just exit. */ - tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; + tls->tl_cpstate &= ~CANCEL_FLAG_CANCEL_PENDING; #ifndef CONFIG_DISABLE_PTHREAD - if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == - TCB_FLAG_TTYPE_PTHREAD) - { - pthread_exit(PTHREAD_CANCELED); - } - else + pthread_exit(PTHREAD_CANCELED); +#else + exit(EXIT_FAILURE); #endif - { - _exit(EXIT_FAILURE); - } } } } @@ -126,7 +115,7 @@ int task_setcancelstate(int state, FAR int *oldstate) { /* Set the non-cancelable state */ - tcb->flags |= TCB_FLAG_NONCANCELABLE; + tls->tl_cpstate |= CANCEL_FLAG_NONCANCELABLE; } else { @@ -134,6 +123,5 @@ int task_setcancelstate(int state, FAR int *oldstate) ret = ERROR; } - sched_unlock(); return ret; } diff --git a/libs/libc/sched/task_setcanceltype.c b/libs/libc/sched/task_setcanceltype.c index 0130d07e04a..dcad4e4e87d 100644 --- a/libs/libc/sched/task_setcanceltype.c +++ b/libs/libc/sched/task_setcanceltype.c @@ -22,8 +22,16 @@ * Included Files ****************************************************************************/ +#include + #include +#include #include +#include +#include + +#include +#include /**************************************************************************** * Public Functions @@ -46,14 +54,63 @@ int task_setcanceltype(int type, FAR int *oldtype) { + FAR struct tls_info_s *tls = tls_get_info(); + int ret = OK; + /* Return the current type if so requested */ if (oldtype != NULL) { - *oldtype = TASK_CANCEL_ASYNCHRONOUS; + if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_ASYNC) != 0) + { + *oldtype = TASK_CANCEL_ASYNCHRONOUS; + } + else + { + *oldtype = TASK_CANCEL_DEFERRED; + } } - /* Check the requested cancellation type */ + /* Set the new cancellation type */ - return (type == TASK_CANCEL_ASYNCHRONOUS) ? OK : EINVAL; + if (type == TASK_CANCEL_ASYNCHRONOUS) + { + /* Set the asynchronous cancellation bit */ + + tls->tl_cpstate |= CANCEL_FLAG_CANCEL_ASYNC; + +#ifdef CONFIG_CANCELLATION_POINTS + /* If we just switched from deferred to asynchronous type and if a + * cancellation is pending, then exit now. + */ + + if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_PENDING) != 0 && + (tls->tl_cpstate & CANCEL_FLAG_NONCANCELABLE) == 0) + { + tls->tl_cpstate &= ~CANCEL_FLAG_CANCEL_PENDING; + + /* Exit according to the type of the thread */ + +#ifndef CONFIG_DISABLE_PTHREAD + pthread_exit(PTHREAD_CANCELED); +#else + exit(EXIT_FAILURE); +#endif + } +#endif + } +#ifdef CONFIG_CANCELLATION_POINTS + else if (type == TASK_CANCEL_DEFERRED) + { + /* Set the deferred cancellation type */ + + tls->tl_cpstate &= ~CANCEL_FLAG_CANCEL_ASYNC; + } +#endif + else + { + ret = EINVAL; + } + + return ret; } diff --git a/libs/libc/sched/task_testcancel.c b/libs/libc/sched/task_testcancel.c index 6f3dfe6d959..6173cbcd5c3 100644 --- a/libs/libc/sched/task_testcancel.c +++ b/libs/libc/sched/task_testcancel.c @@ -22,7 +22,12 @@ * Included Files ****************************************************************************/ +#include + #include +#include + +#include /**************************************************************************** * Public Functions @@ -40,4 +45,8 @@ void task_testcancel(void) { +#ifdef CONFIG_CANCELLATION_POINTS + enter_cancellation_point(); + leave_cancellation_point(); +#endif } diff --git a/libs/libc/tls/tls_getinfo.c b/libs/libc/tls/tls_getinfo.c index faeb3da96b0..f613ea85a4c 100644 --- a/libs/libc/tls/tls_getinfo.c +++ b/libs/libc/tls/tls_getinfo.c @@ -36,7 +36,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: tls_get_info + * Name: tls_get_info_pid * * Description: * Return a reference to the tls_info_s structure. This is used as part @@ -44,7 +44,7 @@ * where CONFIG_TLS_ALIGNED is *not* defined or __KERNEL__ is defined. * * Input Parameters: - * None + * pid - Thread ID to query, set to 0 to query own * * Returned Value: * A reference to the thread-specific tls_info_s structure is return on @@ -52,13 +52,13 @@ * ****************************************************************************/ -FAR struct tls_info_s *tls_get_info(void) +FAR struct tls_info_s *tls_get_info_pid(pid_t pid) { FAR struct tls_info_s *info = NULL; struct stackinfo_s stackinfo; int ret; - ret = nxsched_get_stackinfo(0, &stackinfo); + ret = nxsched_get_stackinfo(pid, &stackinfo); if (ret >= 0) { /* The TLS data lies at the lowest address of the stack allocation. diff --git a/sched/group/group_killchildren.c b/sched/group/group_killchildren.c index 06c300e91e4..bafe7340719 100644 --- a/sched/group/group_killchildren.c +++ b/sched/group/group_killchildren.c @@ -97,22 +97,12 @@ static int group_cancel_children_handler(pid_t pid, FAR void *arg) if (pid != (pid_t)((uintptr_t)arg)) { - /* Cancel this thread. This is a forced cancellation. Make sure that - * cancellation is not disabled by the task/thread. That bit will - * prevent pthread_cancel() or nxtask_delete() from doing what they - * need to do. - */ - rtcb = nxsched_get_tcb(pid); if (rtcb != NULL) { - /* This is a forced cancellation. Make sure that cancellation is - * not disabled by the task/thread. That bit would prevent - * pthread_cancel() or task_delete() from doing what they need - * to do. - */ + /* Cancel this thread. This is a forced cancellation. */ - rtcb->flags &= ~TCB_FLAG_NONCANCELABLE; + rtcb->flags |= TCB_FLAG_FORCED_CANCEL; /* 'pid' could refer to the main task of the thread. That pid * will appear in the group member list as well! diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index 21da0583f1e..9398a417aa6 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -367,9 +367,7 @@ void nx_start(void) */ #ifdef CONFIG_SMP - g_idletcb[i].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | - TCB_FLAG_NONCANCELABLE | - TCB_FLAG_CPU_LOCKED); + g_idletcb[i].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CPU_LOCKED); g_idletcb[i].cmn.cpu = i; /* Set the affinity mask to allow the thread to run on all CPUs. No, @@ -383,8 +381,7 @@ void nx_start(void) g_idletcb[i].cmn.affinity = (cpu_set_t)(CONFIG_SMP_DEFAULT_CPUSET & SCHED_ALL_CPUS); #else - g_idletcb[i].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | - TCB_FLAG_NONCANCELABLE); + g_idletcb[i].cmn.flags = TCB_FLAG_TTYPE_KERNEL; #endif #if CONFIG_TASK_NAME_SIZE > 0 diff --git a/sched/misc/assert.c b/sched/misc/assert.c index 14dfa749537..a4e4f1bd14e 100644 --- a/sched/misc/assert.c +++ b/sched/misc/assert.c @@ -341,7 +341,7 @@ static void dump_task(FAR struct tcb_s *tcb, FAR void *arg) #ifdef CONFIG_SMP " %4d" #endif - " %3d %-8s %-7s %c%c%c" + " %3d %-8s %-7s %c" " %-18s" " " SIGSET_FMT " %p" @@ -363,8 +363,6 @@ static void dump_task(FAR struct tcb_s *tcb, FAR void *arg) TCB_FLAG_POLICY_SHIFT] , g_ttypenames[(tcb->flags & TCB_FLAG_TTYPE_MASK) >> TCB_FLAG_TTYPE_SHIFT] - , tcb->flags & TCB_FLAG_NONCANCELABLE ? 'N' : '-' - , tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : '-' , tcb->flags & TCB_FLAG_EXIT_PROCESSING ? 'P' : '-' , state , SIGSET_ELEM(&tcb->sigprocmask) diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index 65b172dec42..87452cdc3af 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -448,12 +448,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, #endif } -#ifdef CONFIG_CANCELLATION_POINTS - /* Set the deferred cancellation type */ - - ptcb->cmn.flags |= TCB_FLAG_CANCEL_DEFERRED; -#endif - /* Get the assigned pid before we start the task (who knows what * could happen to ptcb after this!). */ diff --git a/sched/task/CMakeLists.txt b/sched/task/CMakeLists.txt index 061a8c90cc2..9e0f98ac544 100644 --- a/sched/task/CMakeLists.txt +++ b/sched/task/CMakeLists.txt @@ -33,7 +33,6 @@ set(SRCS task_recover.c task_restart.c task_spawnparms.c - task_setcancelstate.c task_cancelpt.c task_terminate.c task_gettid.c @@ -51,10 +50,6 @@ if(NOT CONFIG_BUILD_KERNEL) list(APPEND SRCS task_spawn.c) endif() -if(CONFIG_CANCELLATION_POINTS) - list(APPEND SRCS task_setcanceltype.c task_testcancel.c) -endif() - if(NOT CONFIG_BINFMT_DISABLE) if(CONFIG_LIBC_EXECFUNCS) list(APPEND SRCS task_execve.c task_posixspawn.c) diff --git a/sched/task/Make.defs b/sched/task/Make.defs index 41124aff07c..1db20a6a054 100644 --- a/sched/task/Make.defs +++ b/sched/task/Make.defs @@ -21,8 +21,8 @@ CSRCS += task_create.c task_init.c task_setup.c task_activate.c CSRCS += task_start.c task_delete.c task_exit.c task_exithook.c CSRCS += task_getgroup.c task_getpid.c task_prctl.c task_recover.c -CSRCS += task_restart.c task_spawnparms.c task_setcancelstate.c -CSRCS += task_cancelpt.c task_terminate.c task_gettid.c exit.c +CSRCS += task_restart.c task_spawnparms.c task_cancelpt.c task_terminate.c +CSRCS += task_gettid.c exit.c ifeq ($(CONFIG_SCHED_HAVE_PARENT),y) CSRCS += task_getppid.c task_reparent.c @@ -36,10 +36,6 @@ ifneq ($(CONFIG_BUILD_KERNEL),y) CSRCS += task_spawn.c endif -ifeq ($(CONFIG_CANCELLATION_POINTS),y) -CSRCS += task_setcanceltype.c task_testcancel.c -endif - ifneq ($(CONFIG_BINFMT_DISABLE),y) ifeq ($(CONFIG_LIBC_EXECFUNCS),y) CSRCS += task_execve.c task_posixspawn.c diff --git a/sched/task/task_cancelpt.c b/sched/task/task_cancelpt.c index 815d356cc68..4001152d181 100644 --- a/sched/task/task_cancelpt.c +++ b/sched/task/task_cancelpt.c @@ -58,6 +58,7 @@ #include #include +#include #include "sched/sched.h" #include "semaphore/semaphore.h" @@ -65,245 +66,10 @@ #include "mqueue/mqueue.h" #include "task/task.h" -#ifdef CONFIG_CANCELLATION_POINTS - /**************************************************************************** * Public Functions ****************************************************************************/ -/**************************************************************************** - * Name: enter_cancellation_point - * - * Description: - * Called at the beginning of the cancellation point to establish the - * cancellation point. This function does the following: - * - * 1. If deferred cancellation does not apply to this thread, nothing is - * done, otherwise, it - * 2. Sets state information in the caller's TCB and increments a nesting - * count. - * 3. If this is the outermost nesting level, it checks if there is a - * pending cancellation and, if so, calls either exit() or - * pthread_exit(), depending upon the type of the thread. - * - * Input Parameters: - * None - * - * Returned Value: - * true is returned if a cancellation is pending but cannot be performed - * now due to the nesting level. - * - ****************************************************************************/ - -bool enter_cancellation_point(void) -{ - FAR struct tcb_s *tcb = this_task(); - bool ret = false; - - /* Disabling pre-emption should provide sufficient protection. We only - * need the TCB to be stationary (no interrupt level modification is - * anticipated). - * - * REVISIT: is locking the scheduler sufficient in SMP mode? - */ - - sched_lock(); - - /* If cancellation is disabled on this thread or if this thread is using - * asynchronous cancellation, then do nothing. - * - * Special case: if the cpcount count is greater than zero, then we are - * nested and the above condition was certainly true at the outermost - * nesting level. - */ - - if (((tcb->flags & TCB_FLAG_NONCANCELABLE) == 0 && - (tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0) || - tcb->cpcount > 0) - { - /* Check if there is a pending cancellation */ - - if ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0) - { - /* Yes... return true (if we don't exit here) */ - - ret = true; - - /* If there is a pending cancellation and we are at the outermost - * nesting level of cancellation function calls, then exit - * according to the type of the thread. - */ - - if (tcb->cpcount == 0) - { -#ifndef CONFIG_DISABLE_PTHREAD - if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == - TCB_FLAG_TTYPE_PTHREAD) - { - pthread_exit(PTHREAD_CANCELED); - } - else -#endif - { - _exit(EXIT_FAILURE); - } - } - } - - /* Otherwise, indicate that we are at a cancellation point by - * incrementing the nesting level of the cancellation point - * functions. - */ - - DEBUGASSERT(tcb->cpcount < INT16_MAX); - tcb->cpcount++; - } - - sched_unlock(); - return ret; -} - -/**************************************************************************** - * Name: leave_cancellation_point - * - * Description: - * Called at the end of the cancellation point. This function does the - * following: - * - * 1. If deferred cancellation does not apply to this thread, nothing is - * done, otherwise, it - * 2. Clears state information in the caller's TCB and decrements a - * nesting count. - * 3. If this is the outermost nesting level, it checks if there is a - * pending cancellation and, if so, calls either exit() or - * pthread_exit(), depending upon the type of the thread. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void leave_cancellation_point(void) -{ - FAR struct tcb_s *tcb = this_task(); - - /* Disabling pre-emption should provide sufficient protection. We only - * need the TCB to be stationary (no interrupt level modification is - * anticipated). - * - * REVISIT: is locking the scheduler sufficient in SMP mode? - */ - - sched_lock(); - - /* If cancellation is disabled on this thread or if this thread is using - * asynchronous cancellation, then do nothing. Here we check only the - * nesting level: if the cpcount count is greater than zero, then the - * required condition was certainly true at the outermost nesting level. - */ - - if (tcb->cpcount > 0) - { - /* Decrement the nesting level. If if would decrement to zero, then - * we are at the outermost nesting level and may need to do more. - */ - - if (tcb->cpcount == 1) - { - /* We are no longer at the cancellation point */ - - tcb->cpcount = 0; - - /* If there is a pending cancellation then just exit according to - * the type of the thread. - */ - - if ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0) - { -#ifndef CONFIG_DISABLE_PTHREAD - if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == - TCB_FLAG_TTYPE_PTHREAD) - { - pthread_exit(PTHREAD_CANCELED); - } - else -#endif - { - _exit(EXIT_FAILURE); - } - } - } - else - { - /* We are not at the outermost nesting level. Just decrment the - * nesting level count. - */ - - tcb->cpcount--; - } - } - - sched_unlock(); -} - -/**************************************************************************** - * Name: check_cancellation_point - * - * Description: - * Returns true if: - * - * 1. Deferred cancellation does applies to this thread, - * 2. We are within a cancellation point (i.e., the nesting level in the - * TCB is greater than zero). - * - * Input Parameters: - * None - * - * Returned Value: - * true is returned if a cancellation is pending but cannot be performed - * now due to the nesting level. - * - ****************************************************************************/ - -bool check_cancellation_point(void) -{ - FAR struct tcb_s *tcb = this_task(); - bool ret = false; - - /* Disabling pre-emption should provide sufficient protection. We only - * need the TCB to be stationary (no interrupt level modification is - * anticipated). - * - * REVISIT: is locking the scheduler sufficient in SMP mode? - */ - - sched_lock(); - - /* If cancellation is disabled on this thread or if this thread is using - * asynchronous cancellation, then return false. - * - * If the cpcount count is greater than zero, then we within a - * cancellation and will true if there is a pending cancellation. - */ - - if (((tcb->flags & TCB_FLAG_NONCANCELABLE) == 0 && - (tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0) || - tcb->cpcount > 0) - { - /* Check if there is a pending cancellation. If so, return true. */ - - ret = ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0); - } - - sched_unlock(); - return ret; -} - -#endif /* CONFIG_CANCELLATION_POINTS */ - /**************************************************************************** * Name: nxnotify_cancellation * @@ -322,6 +88,7 @@ bool check_cancellation_point(void) bool nxnotify_cancellation(FAR struct tcb_s *tcb) { + FAR struct tls_info_s *tls = tls_get_info_pid(tcb->pid); irqstate_t flags; bool ret = false; @@ -338,7 +105,8 @@ bool nxnotify_cancellation(FAR struct tcb_s *tcb) /* Check to see if this task has the non-cancelable bit set. */ - if ((tcb->flags & TCB_FLAG_NONCANCELABLE) != 0) + if ((tcb->flags & TCB_FLAG_FORCED_CANCEL) == 0 && + (tls->tl_cpstate & CANCEL_FLAG_NONCANCELABLE) != 0) { /* Then we cannot cancel the thread now. Here is how this is * supposed to work: @@ -353,7 +121,7 @@ bool nxnotify_cancellation(FAR struct tcb_s *tcb) * immediately, interrupting the thread with its processing." */ - tcb->flags |= TCB_FLAG_CANCEL_PENDING; + tls->tl_cpstate |= CANCEL_FLAG_CANCEL_PENDING; leave_critical_section(flags); return true; } @@ -361,7 +129,7 @@ bool nxnotify_cancellation(FAR struct tcb_s *tcb) #ifdef CONFIG_CANCELLATION_POINTS /* Check if this task supports deferred cancellation */ - if ((tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0) + if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_ASYNC) == 0) { /* Then we cannot cancel the task asynchronously. */ @@ -369,13 +137,13 @@ bool nxnotify_cancellation(FAR struct tcb_s *tcb) /* Mark the cancellation as pending. */ - tcb->flags |= TCB_FLAG_CANCEL_PENDING; + tls->tl_cpstate |= CANCEL_FLAG_CANCEL_PENDING; /* If the task is waiting at a cancellation point, then notify of the * cancellation thereby waking the task up with an ECANCELED error. */ - if (tcb->cpcount > 0) + if (tls->tl_cpcount > 0) { /* If the thread is blocked waiting for a semaphore, then the * thread must be unblocked to handle the cancellation. diff --git a/sched/task/task_exithook.c b/sched/task/task_exithook.c index ae6dcc76cd6..ca1a7ef2daa 100644 --- a/sched/task/task_exithook.c +++ b/sched/task/task_exithook.c @@ -430,17 +430,6 @@ void nxtask_exithook(FAR struct tcb_s *tcb, int status) return; } -#ifdef CONFIG_CANCELLATION_POINTS - /* Mark the task as non-cancelable to avoid additional calls to exit() - * due to any cancellation point logic that might get kicked off by - * actions taken during exit processing. - */ - - tcb->flags |= TCB_FLAG_NONCANCELABLE; - tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; - tcb->cpcount = 0; -#endif - /* If the task was terminated by another task, it may be in an unknown * state. Make some feeble effort to recover the state. */ diff --git a/sched/task/task_setcanceltype.c b/sched/task/task_setcanceltype.c deleted file mode 100644 index cf4f7bcd389..00000000000 --- a/sched/task/task_setcanceltype.c +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** - * sched/task/task_setcanceltype.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include -#include - -#include "sched/sched.h" -#include "task/task.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: task_setcanceltype - * - * Description: - * The task_setcanceltype() function atomically both sets the calling - * thread's cancellability type to the indicated type and returns the - * previous cancellability type at the location referenced by oldtype - * Legal values for type are TASK_CANCEL_DEFERRED and - * TASK_CANCEL_ASYNCHRONOUS. - * - * The cancellability state and type of any newly created threads, - * including the thread in which main() was first invoked, are - * TASK_CANCEL_ENABLE and TASK_CANCEL_DEFERRED respectively. - * - ****************************************************************************/ - -int task_setcanceltype(int type, FAR int *oldtype) -{ - FAR struct tcb_s *tcb = this_task(); - int ret = OK; - - /* Suppress context changes for a bit so that the flags are stable. (the - * flags should not change in interrupt handling). - */ - - sched_lock(); - - /* Return the current type if so requested */ - - if (oldtype != NULL) - { - if ((tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0) - { - *oldtype = TASK_CANCEL_DEFERRED; - } - else - { - *oldtype = TASK_CANCEL_ASYNCHRONOUS; - } - } - - /* Set the new cancellation type */ - - if (type == TASK_CANCEL_ASYNCHRONOUS) - { - /* Clear the deferred cancellation bit */ - - tcb->flags &= ~TCB_FLAG_CANCEL_DEFERRED; - -#ifdef CONFIG_CANCELLATION_POINTS - /* If we just switched from deferred to asynchronous type and if a - * cancellation is pending, then exit now. - */ - - if ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0 && - (tcb->flags & TCB_FLAG_NONCANCELABLE) == 0) - { - tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; - - /* Exit according to the type of the thread */ - -#ifndef CONFIG_DISABLE_PTHREAD - if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) - { - pthread_exit(PTHREAD_CANCELED); - } - else -#endif - { - _exit(EXIT_FAILURE); - } - } -#endif - } -#ifdef CONFIG_CANCELLATION_POINTS - else if (type == TASK_CANCEL_DEFERRED) - { - /* Set the deferred cancellation type */ - - tcb->flags |= TCB_FLAG_CANCEL_DEFERRED; - } -#endif - else - { - ret = EINVAL; - } - - sched_unlock(); - return ret; -} diff --git a/sched/task/task_setup.c b/sched/task/task_setup.c index 3adf7df2577..b41a37899c3 100644 --- a/sched/task/task_setup.c +++ b/sched/task/task_setup.c @@ -409,12 +409,6 @@ static int nxthread_setup_scheduler(FAR struct tcb_s *tcb, int priority, tcb->flags |= TCB_FLAG_SCHED_FIFO; #endif -#ifdef CONFIG_CANCELLATION_POINTS - /* Set the deferred cancellation type */ - - tcb->flags |= TCB_FLAG_CANCEL_DEFERRED; -#endif - /* Save the task ID of the parent task in the TCB and allocate * a child status structure. */ diff --git a/sched/task/task_testcancel.c b/sched/task/task_testcancel.c deleted file mode 100644 index c2c1a45ea99..00000000000 --- a/sched/task/task_testcancel.c +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** - * sched/task/task_testcancel.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include - -#include - -#include "task/task.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: task_testcancel - * - * Description: - * The task_testcancel() function creates a cancellation point in the - * calling thread. The task_testcancel() function has no effect if - * cancellability is disabled - * - ****************************************************************************/ - -void task_testcancel(void) -{ - enter_cancellation_point(); - leave_cancellation_point(); -} diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 687e856cf1f..92b1532e206 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -184,10 +184,7 @@ "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","!defined(CONFIG_BUILD_KERNEL)","int","pid_t" "task_restart","sched.h","!defined(CONFIG_BUILD_KERNEL)","int","pid_t" -"task_setcancelstate","sched.h","","int","int","FAR int *" -"task_setcanceltype","sched.h","defined(CONFIG_CANCELLATION_POINTS)","int","int","FAR int *" "task_spawn","nuttx/spawn.h","!defined(CONFIG_BUILD_KERNEL)","int","FAR const char *","main_t","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char * const []|FAR char * const *","FAR char * const []|FAR char * const *" -"task_testcancel","sched.h","defined(CONFIG_CANCELLATION_POINTS)","void" "tgkill","signal.h","","int","pid_t","pid_t","int" "time","time.h","","time_t","FAR time_t *" "timer_create","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","clockid_t","FAR struct sigevent *","FAR timer_t *"