diff --git a/Documentation/guides/pysimcoder.rst b/Documentation/guides/pysimcoder.rst index f202b1a162a..a117fbafa4d 100644 --- a/Documentation/guides/pysimcoder.rst +++ b/Documentation/guides/pysimcoder.rst @@ -51,7 +51,7 @@ with NuttX. The list is the following: ``CONFIG_BOARDCTL_OS_SYMTAB=y`` ``CONFIG_NSH_READLINE=y`` ``CONFIG_BUILTIN=y`` ``CONFIG_ETC_ROMFS=y`` ``CONFIG_ELF=y`` ``CONFIG_PSEUDOTERM=y`` -``CONFIG_FS_BINFS=y`` ``CONFIG_PTHREAD_CLEANUP_STACKSIZE=1`` +``CONFIG_FS_BINFS=y`` ``CONFIG_TLS_NCLEANUP=1`` ``CONFIG_FS_PROCFS=y`` ``CONFIG_PTHREAD_MUTEX_TYPES=y`` ``CONFIG_FS_PROCFS_REGISTER=y`` ``CONFIG_PTHREAD_STACK_MIN=1024`` ``CONFIG_FS_ROMFS=y`` ``CONFIG_LIBM=y`` diff --git a/boards/arm/imxrt/teensy-4.x/configs/pikron-bb/defconfig b/boards/arm/imxrt/teensy-4.x/configs/pikron-bb/defconfig index 7220e745c25..77b1df3b68f 100644 --- a/boards/arm/imxrt/teensy-4.x/configs/pikron-bb/defconfig +++ b/boards/arm/imxrt/teensy-4.x/configs/pikron-bb/defconfig @@ -131,7 +131,6 @@ CONFIG_NXFONTS_DISABLE_8BPP=y CONFIG_PRIORITY_INHERITANCE=y CONFIG_PSEUDOTERM=y CONFIG_PTABLE_PARTITION=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=1 CONFIG_PTHREAD_MUTEX_DEFAULT_PRIO_INHERIT=y CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_STACK_MIN=1024 @@ -160,4 +159,5 @@ CONFIG_SYSTEM_PING=y CONFIG_SYSTEM_TEE=y CONFIG_TEENSY_41=y CONFIG_TEENSY_41_PIKRON_BB=y +CONFIG_TLS_NCLEANUP=1 CONFIG_TLS_NELEM=4 diff --git a/boards/arm/lpc17xx_40xx/lx_cpu/configs/nsh/defconfig b/boards/arm/lpc17xx_40xx/lx_cpu/configs/nsh/defconfig index f31a7dbeb62..af2de216ee9 100644 --- a/boards/arm/lpc17xx_40xx/lx_cpu/configs/nsh/defconfig +++ b/boards/arm/lpc17xx_40xx/lx_cpu/configs/nsh/defconfig @@ -130,7 +130,6 @@ CONFIG_PREALLOC_TIMERS=4 CONFIG_PRIORITY_INHERITANCE=y CONFIG_PSEUDOTERM=y CONFIG_PTABLE_PARTITION=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=1 CONFIG_PTHREAD_MUTEX_DEFAULT_PRIO_INHERIT=y CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_STACK_MIN=1024 @@ -163,6 +162,7 @@ CONFIG_SYSTEM_SYSTEM=y CONFIG_SYSTEM_TEE=y CONFIG_SYSTEM_TELNET_CLIENT=y CONFIG_TESTING_RAMTEST=y +CONFIG_TLS_NCLEANUP=1 CONFIG_TLS_NELEM=4 CONFIG_UART0_SERIAL_CONSOLE=y CONFIG_USBDEV_COMPOSITE=y diff --git a/boards/arm/samv7/same70-xplained/configs/pysim/defconfig b/boards/arm/samv7/same70-xplained/configs/pysim/defconfig index cfabe0b358d..d31d78a94b7 100644 --- a/boards/arm/samv7/same70-xplained/configs/pysim/defconfig +++ b/boards/arm/samv7/same70-xplained/configs/pysim/defconfig @@ -99,7 +99,6 @@ CONFIG_NSH_READLINE=y CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048 CONFIG_PREALLOC_TIMERS=4 CONFIG_PSEUDOTERM=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=1 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_STACK_DEFAULT=2048 CONFIG_PTHREAD_STACK_MIN=1024 @@ -152,5 +151,6 @@ CONFIG_SYSTEM_PING=y CONFIG_SYSTEM_PING_STACKSIZE=2048 CONFIG_SYSTEM_TELNETD_SESSION_STACKSIZE=2048 CONFIG_SYSTEM_TELNETD_STACKSIZE=2048 +CONFIG_TLS_NCLEANUP=1 CONFIG_USART1_SERIAL_CONSOLE=y CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm/stm32f7/nucleo-144/configs/f746-pysim/defconfig b/boards/arm/stm32f7/nucleo-144/configs/f746-pysim/defconfig index 91c62c486c5..2c53d80fc48 100644 --- a/boards/arm/stm32f7/nucleo-144/configs/f746-pysim/defconfig +++ b/boards/arm/stm32f7/nucleo-144/configs/f746-pysim/defconfig @@ -72,7 +72,6 @@ CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=4098 CONFIG_PREALLOC_TIMERS=4 CONFIG_PRIORITY_INHERITANCE=y CONFIG_PSEUDOTERM=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=1 CONFIG_PTHREAD_MUTEX_DEFAULT_PRIO_INHERIT=y CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_STACK_DEFAULT=2048 @@ -143,6 +142,7 @@ CONFIG_SYSTEM_PING_STACKSIZE=2048 CONFIG_SYSTEM_TELNETD_SESSION_STACKSIZE=2048 CONFIG_SYSTEM_TELNETD_STACKSIZE=2048 CONFIG_TASK_NAME_SIZE=0 +CONFIG_TLS_NCLEANUP=1 CONFIG_USART3_SERIAL_CONSOLE=y CONFIG_USEC_PER_TICK=1000 CONFIG_WQUEUE_NOTIFIER=y diff --git a/boards/arm/stm32h7/nucleo-h743zi2/configs/pysim/defconfig b/boards/arm/stm32h7/nucleo-h743zi2/configs/pysim/defconfig index 7cb75448c2b..1096c9861d6 100644 --- a/boards/arm/stm32h7/nucleo-h743zi2/configs/pysim/defconfig +++ b/boards/arm/stm32h7/nucleo-h743zi2/configs/pysim/defconfig @@ -70,7 +70,6 @@ CONFIG_NSH_READLINE=y CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048 CONFIG_PREALLOC_TIMERS=4 CONFIG_PRIORITY_INHERITANCE=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=1 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_STACK_DEFAULT=2048 CONFIG_PTHREAD_STACK_MIN=1024 @@ -125,6 +124,7 @@ CONFIG_SYSTEM_PING_STACKSIZE=2048 CONFIG_SYSTEM_TELNETD_SESSION_STACKSIZE=2048 CONFIG_SYSTEM_TELNETD_STACKSIZE=2048 CONFIG_TASK_NAME_SIZE=0 +CONFIG_TLS_NCLEANUP=1 CONFIG_USART3_SERIAL_CONSOLE=y CONFIG_USBHOST=y CONFIG_USBHOST_MSC=y diff --git a/boards/arm/stm32h7/nucleo-h745zi/configs/pysim_cm7/defconfig b/boards/arm/stm32h7/nucleo-h745zi/configs/pysim_cm7/defconfig index 837eeac950a..78424e9f7a2 100644 --- a/boards/arm/stm32h7/nucleo-h745zi/configs/pysim_cm7/defconfig +++ b/boards/arm/stm32h7/nucleo-h745zi/configs/pysim_cm7/defconfig @@ -70,7 +70,6 @@ CONFIG_NSH_READLINE=y CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048 CONFIG_PREALLOC_TIMERS=4 CONFIG_PRIORITY_INHERITANCE=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=1 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_STACK_DEFAULT=2048 CONFIG_PTHREAD_STACK_MIN=1024 @@ -125,6 +124,7 @@ CONFIG_SYSTEM_PING_STACKSIZE=2048 CONFIG_SYSTEM_TELNETD_SESSION_STACKSIZE=2048 CONFIG_SYSTEM_TELNETD_STACKSIZE=2048 CONFIG_TASK_NAME_SIZE=0 +CONFIG_TLS_NCLEANUP=1 CONFIG_USART3_SERIAL_CONSOLE=y CONFIG_USBHOST=y CONFIG_USBHOST_MSC=y diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/citest/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/citest/defconfig index e636bd36cfa..59aa56f5fd1 100644 --- a/boards/risc-v/qemu-rv/rv-virt/configs/citest/defconfig +++ b/boards/risc-v/qemu-rv/rv-virt/configs/citest/defconfig @@ -96,7 +96,6 @@ CONFIG_NSH_READLINE=y CONFIG_PATH_INITIAL="/system/bin" CONFIG_PREALLOC_TIMERS=0 CONFIG_PSEUDOFS_SOFTLINKS=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=4 CONFIG_PTHREAD_SPINLOCKS=y CONFIG_PTHREAD_STACK_MIN=2048 CONFIG_RAM_SIZE=33554432 @@ -132,5 +131,6 @@ CONFIG_TESTING_OPEN_MEMSTREAM=y CONFIG_TESTING_OSTEST=y CONFIG_TESTING_SCANFTEST=y CONFIG_TESTS_TESTSUITES=y +CONFIG_TLS_NCLEANUP=4 CONFIG_TLS_NELEM=8 CONFIG_USEC_PER_TICK=1000 diff --git a/boards/sim/sim/sim/configs/asan/defconfig b/boards/sim/sim/sim/configs/asan/defconfig index 9dbff23ed79..47c61084e39 100644 --- a/boards/sim/sim/sim/configs/asan/defconfig +++ b/boards/sim/sim/sim/configs/asan/defconfig @@ -30,7 +30,6 @@ CONFIG_MM_CUSTOMIZE_MANAGER=y CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_READLINE=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=1 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_MUTEX_UNSAFE=y CONFIG_READLINE_TABCOMPLETION=y @@ -45,3 +44,4 @@ CONFIG_SIM_UBSAN=y CONFIG_SYSTEM_NSH=y CONFIG_TESTING_OSTEST=y CONFIG_TESTING_OSTEST_AIO=y +CONFIG_TLS_NCLEANUP=1 diff --git a/boards/sim/sim/sim/configs/citest/defconfig b/boards/sim/sim/sim/configs/citest/defconfig index d33bb102b35..b11a76b7e84 100644 --- a/boards/sim/sim/sim/configs/citest/defconfig +++ b/boards/sim/sim/sim/configs/citest/defconfig @@ -105,7 +105,6 @@ CONFIG_PM=y CONFIG_PM_RUNTIME=y CONFIG_PSEUDOFS_ATTRIBUTES=y CONFIG_PSEUDOFS_SOFTLINKS=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=4 CONFIG_PTHREAD_SPINLOCKS=y CONFIG_PTHREAD_STACK_MIN=2048 CONFIG_READLINE_TABCOMPLETION=y @@ -146,5 +145,6 @@ CONFIG_TESTING_OSTEST=y CONFIG_TESTING_SCANFTEST=y CONFIG_TESTING_SCANFTEST_FNAME="/tmp/test.txt" CONFIG_TESTS_TESTSUITES=y +CONFIG_TLS_NCLEANUP=4 CONFIG_TLS_NELEM=16 CONFIG_TLS_TASK_NELEM=8 diff --git a/boards/sim/sim/sim/configs/kasan/defconfig b/boards/sim/sim/sim/configs/kasan/defconfig index ffbcc91e541..ea9b2555179 100644 --- a/boards/sim/sim/sim/configs/kasan/defconfig +++ b/boards/sim/sim/sim/configs/kasan/defconfig @@ -35,7 +35,6 @@ CONFIG_MM_UBSAN=y CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_READLINE=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=1 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_MUTEX_UNSAFE=y CONFIG_READLINE_TABCOMPLETION=y @@ -49,3 +48,4 @@ CONFIG_SYSTEM_GCOV=y CONFIG_SYSTEM_NSH=y CONFIG_TESTING_OSTEST=y CONFIG_TESTING_OSTEST_AIO=y +CONFIG_TLS_NCLEANUP=1 diff --git a/boards/sim/sim/sim/configs/ostest/defconfig b/boards/sim/sim/sim/configs/ostest/defconfig index ec08aee426d..c2b14602678 100644 --- a/boards/sim/sim/sim/configs/ostest/defconfig +++ b/boards/sim/sim/sim/configs/ostest/defconfig @@ -24,7 +24,6 @@ CONFIG_MM_KASAN=y CONFIG_MM_UBSAN=y CONFIG_MM_UBSAN_TRAP_ON_ERROR=y CONFIG_PRIORITY_INHERITANCE=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=3 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_RAM_START=0x00000000 CONFIG_SCHED_HAVE_PARENT=y @@ -36,3 +35,4 @@ CONFIG_START_YEAR=2007 CONFIG_TESTING_OSTEST=y CONFIG_TESTING_OSTEST_LOOPS=5 CONFIG_TESTING_OSTEST_POWEROFF=y +CONFIG_TLS_NCLEANUP=3 diff --git a/boards/sim/sim/sim/configs/ostest_oneholder/defconfig b/boards/sim/sim/sim/configs/ostest_oneholder/defconfig index 59b02e56477..f1fbe748026 100644 --- a/boards/sim/sim/sim/configs/ostest_oneholder/defconfig +++ b/boards/sim/sim/sim/configs/ostest_oneholder/defconfig @@ -24,7 +24,6 @@ CONFIG_MM_KASAN=y CONFIG_MM_UBSAN=y CONFIG_MM_UBSAN_TRAP_ON_ERROR=y CONFIG_PRIORITY_INHERITANCE=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=3 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_RAM_START=0x00000000 CONFIG_SCHED_HAVE_PARENT=y @@ -37,3 +36,4 @@ CONFIG_START_YEAR=2007 CONFIG_TESTING_OSTEST=y CONFIG_TESTING_OSTEST_LOOPS=5 CONFIG_TESTING_OSTEST_POWEROFF=y +CONFIG_TLS_NCLEANUP=3 diff --git a/boards/sim/sim/sim/configs/posix_test/defconfig b/boards/sim/sim/sim/configs/posix_test/defconfig index c18d7842a3e..d2c94f2aea2 100644 --- a/boards/sim/sim/sim/configs/posix_test/defconfig +++ b/boards/sim/sim/sim/configs/posix_test/defconfig @@ -70,7 +70,6 @@ CONFIG_PATH_INITIAL="/bin" CONFIG_PIPES=y CONFIG_PSEUDOFS_ATTRIBUTES=y CONFIG_PSEUDOFS_SOFTLINKS=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=4 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_SPINLOCKS=y CONFIG_READLINE_TABCOMPLETION=y @@ -94,4 +93,5 @@ CONFIG_START_YEAR=2008 CONFIG_SYSTEM_DUMPSTACK=y CONFIG_SYSTEM_NSH=y CONFIG_TESTING_LTP=y +CONFIG_TLS_NCLEANUP=4 CONFIG_TLS_NELEM=16 diff --git a/boards/sim/sim/sim/configs/rtptools/defconfig b/boards/sim/sim/sim/configs/rtptools/defconfig index 9e75809ab42..ae772a7866e 100644 --- a/boards/sim/sim/sim/configs/rtptools/defconfig +++ b/boards/sim/sim/sim/configs/rtptools/defconfig @@ -84,7 +84,6 @@ CONFIG_NSH_READLINE=y CONFIG_PREALLOC_TIMERS=4 CONFIG_PSEUDOFS_SOFTLINKS=y CONFIG_PSEUDOTERM=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=2 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_RAMMTD=y CONFIG_READLINE_CMD_HISTORY=y @@ -110,6 +109,7 @@ CONFIG_SYSTEM_TELNET_CLIENT=y CONFIG_SYSTEM_TIME64=y CONFIG_TASK_NAME_SIZE=32 CONFIG_TELNET_TXBUFFER_SIZE=64 +CONFIG_TLS_NCLEANUP=2 CONFIG_TTY_SIGINT=y CONFIG_TTY_SIGINT_CHAR=0x3 CONFIG_TTY_SIGTSTP=y diff --git a/boards/sim/sim/sim/configs/tcpblaster/defconfig b/boards/sim/sim/sim/configs/tcpblaster/defconfig index 32dfb1f0af0..f197330015e 100644 --- a/boards/sim/sim/sim/configs/tcpblaster/defconfig +++ b/boards/sim/sim/sim/configs/tcpblaster/defconfig @@ -83,7 +83,6 @@ CONFIG_NSH_READLINE=y CONFIG_PREALLOC_TIMERS=4 CONFIG_PSEUDOFS_SOFTLINKS=y CONFIG_PSEUDOTERM=y -CONFIG_PTHREAD_CLEANUP_STACKSIZE=2 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_RAMMTD=y CONFIG_READLINE_CMD_HISTORY=y @@ -109,6 +108,7 @@ CONFIG_SYSTEM_TELNET_CLIENT=y CONFIG_SYSTEM_TIME64=y CONFIG_TASK_NAME_SIZE=32 CONFIG_TELNET_TXBUFFER_SIZE=64 +CONFIG_TLS_NCLEANUP=2 CONFIG_TTY_SIGINT=y CONFIG_TTY_SIGINT_CHAR=0x3 CONFIG_TTY_SIGTSTP=y diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h index 6dcc74e2150..f482e3ba472 100644 --- a/include/nuttx/pthread.h +++ b/include/nuttx/pthread.h @@ -163,27 +163,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, void nx_pthread_exit(FAR void *exit_value) noreturn_function; -/**************************************************************************** - * Name: pthread_cleanup_popall - * - * Description: - * The pthread_cleanup_popall() is an internal function that will pop and - * execute all clean-up functions. This function is only called from - * within the pthread_exit() and pthread_cancellation() logic - * - * Input Parameters: - * tls - The local storage info of the exiting thread - * - * Returned Value: - * None - * - ****************************************************************************/ - -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 -struct tls_info_s; -void pthread_cleanup_popall(FAR struct tls_info_s *tls); -#endif - #undef EXTERN #ifdef __cplusplus } diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h index 5529b09d84b..ca8b80a0cd8 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -40,7 +40,6 @@ #include #include -#include /**************************************************************************** * Pre-processor Definitions @@ -147,17 +146,17 @@ struct task_info_s #endif }; -/* struct pthread_cleanup_s *************************************************/ +/* struct tls_cleanup_s *****************************************************/ /* This structure describes one element of the pthread cleanup stack */ -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 -struct pthread_cleanup_s +typedef CODE void (*tls_cleanup_t)(FAR void *arg); + +struct tls_cleanup_s { - pthread_cleanup_t pc_cleaner; /* Cleanup callback address */ - FAR void *pc_arg; /* Argument that accompanies the callback */ + tls_cleanup_t tc_cleaner; /* Cleanup callback address */ + FAR void *tc_arg; /* Argument that accompanies the callback */ }; -#endif /* When TLS is enabled, up_createstack() will align allocated stacks to the * TLS_STACK_ALIGN value. An instance of the following structure will be @@ -201,14 +200,14 @@ struct tls_info_s uintptr_t tl_elem[CONFIG_TLS_NELEM]; /* TLS elements */ #endif -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 /* tl_tos - The index to the next available entry at the top of the * stack. * tl_stack - The pre-allocated clean-up stack memory. */ +#if CONFIG_TLS_NCLEANUP > 0 uint8_t tl_tos; - struct pthread_cleanup_s tl_stack[CONFIG_PTHREAD_CLEANUP_STACKSIZE]; + struct tls_cleanup_s tl_stack[CONFIG_TLS_NCLEANUP]; #endif uint8_t tl_cpstate; /* Cancellation state */ @@ -360,6 +359,65 @@ void tls_destruct(void); FAR struct task_info_s *task_get_info(void); +#if CONFIG_TLS_NCLEANUP > 0 +/**************************************************************************** + * Name: tls_cleanup_push + * + * Description: + * Push a new entry onto the cleanup stack + * + * Input Parameters: + * tls - The TLS data structure + * routine - The cleanup routine to be called + * arg - An argument that will be passed to the cleanup routine + * + * Returned Value: + * None + * + ****************************************************************************/ + +void tls_cleanup_push(FAR struct tls_info_s *tls, + tls_cleanup_t routine, FAR void *arg); + +/**************************************************************************** + * Name: tls_cleanup_pop + * + * Description: + * Pop the top entry from the cleanup stack and execute the cleanup + * + * Input Parameters: + * tls - The TLS data structure + * execute - Execute the cleanup routine (true) or just remove the + * + * Returned Value: + * None + * + ****************************************************************************/ + +void tls_cleanup_pop(FAR struct tls_info_s *tls, int execute); + +/**************************************************************************** + * Name: tls_cleanup_popall + * + * Description: + * Pop and execute all cleanup stack entries + * + * Input Parameters: + * tls - The TLS data structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +void tls_cleanup_popall(FAR struct tls_info_s *tls); + +#else +# define tls_cleanup_push(tls, routine, arg) ((void)(tls), (void)(routine), (void)(arg)) +# define tls_cleanup_pop(tls, execute) ((void)(tls), (void)(execute)) +# define tls_cleanup_popall(tls) ((void)(tls)) +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/include/pthread.h b/include/pthread.h index e996975c4ae..fd16979e7f9 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -429,11 +429,9 @@ typedef FAR struct pthread_spinlock_s pthread_spinlock_t; # endif #endif /* CONFIG_PTHREAD_SPINLOCKS */ -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 /* This type describes the pthread cleanup callback (non-standard) */ typedef CODE void (*pthread_cleanup_t)(FAR void *arg); -#endif /* Forward references */ @@ -545,9 +543,12 @@ void pthread_testcancel(void); * is canceled. */ -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 +#if CONFIG_TLS_NCLEANUP > 0 void pthread_cleanup_pop(int execute); void pthread_cleanup_push(pthread_cleanup_t routine, FAR void *arg); +#else +# define pthread_cleanup_pop(execute) ((void)(execute)) +# define pthread_cleanup_push(routine,arg) ((void)(routine), (void)(arg)) #endif /* A thread can await termination of another thread and retrieve the return diff --git a/libs/libc/pthread/CMakeLists.txt b/libs/libc/pthread/CMakeLists.txt index 2055fcb067c..167bc00d3d9 100644 --- a/libs/libc/pthread/CMakeLists.txt +++ b/libs/libc/pthread/CMakeLists.txt @@ -109,7 +109,7 @@ if(NOT CONFIG_DISABLE_PTHREAD) list(APPEND SRCS pthread_spinlock.c) endif() - if(NOT CONFIG_PTHREAD_CLEANUP_STACKSIZE EQUAL 0) + if(NOT CONFIG_TLS_NCLEANUP EQUAL 0) list(APPEND SRCS pthread_cleanup.c) endif() endif() diff --git a/libs/libc/pthread/Make.defs b/libs/libc/pthread/Make.defs index 51b9992ccd8..d0b5e7a8476 100644 --- a/libs/libc/pthread/Make.defs +++ b/libs/libc/pthread/Make.defs @@ -70,7 +70,7 @@ ifeq ($(CONFIG_PTHREAD_SPINLOCKS),y) CSRCS += pthread_spinlock.c endif -ifneq ($(CONFIG_PTHREAD_CLEANUP_STACKSIZE),0) +ifneq ($(CONFIG_TLS_NCLEANUP),0) CSRCS += pthread_cleanup.c endif diff --git a/libs/libc/pthread/pthread_cleanup.c b/libs/libc/pthread/pthread_cleanup.c index 9c1aec1f179..2687c75d533 100644 --- a/libs/libc/pthread/pthread_cleanup.c +++ b/libs/libc/pthread/pthread_cleanup.c @@ -23,77 +23,21 @@ ****************************************************************************/ #include +#include +#include #include #include #include -#include -#include -#include - -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: pthread_cleanup_pop_tls - * - * Description: - * The pthread_cleanup_pop_tcb() function will remove the routine at the - * top of the calling thread's cancellation cleanup stack and optionally - * invoke it (if 'execute' is non-zero). - * - * Input Parameters: - * tcb - The TCB of the pthread that is exiting or being canceled. - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void pthread_cleanup_pop_tls(FAR struct tls_info_s *tls, int execute) -{ - if (tls->tl_tos > 0) - { - unsigned int ndx; - - /* Get the index to the last cleaner function pushed onto the stack */ - - ndx = tls->tl_tos - 1; - DEBUGASSERT(ndx >= 0 && ndx < CONFIG_PTHREAD_CLEANUP_STACKSIZE); - - /* Should we execute the cleanup routine at the top of the stack? */ - - if (execute != 0) - { - FAR struct pthread_cleanup_s *cb; - - /* Yes.. Execute the clean-up routine. */ - - cb = &tls->tl_stack[ndx]; - cb->pc_cleaner(cb->pc_arg); - } - - tls->tl_tos = ndx; - } -} - /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: pthread_cleanup_push - * pthread_cleanup_pop * * Description: - * The pthread_cleanup_pop() function will remove the routine at the top - * of the calling thread's cancellation cleanup stack and optionally - * invoke it (if 'execute' is non-zero). - * * The pthread_cleanup_push() function will push the specified cancellation * cleanup handler routine onto the calling thread's cancellation cleanup * stack. The cancellation cleanup handler will be popped from the @@ -106,6 +50,30 @@ static void pthread_cleanup_pop_tls(FAR struct tls_info_s *tls, int execute) * Input Parameters: * routine - The cleanup routine to be pushed on the cleanup stack. * arg - An argument that will accompany the callback. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void pthread_cleanup_push(pthread_cleanup_t routine, FAR void *arg) +{ + tls_cleanup_push(tls_get_info(), routine, arg); +} + +/**************************************************************************** + * Name: pthread_cleanup_pop + * + * Description: + * The pthread_cleanup_pop() function will remove the routine at the top + * of the calling thread's cancellation cleanup stack and optionally + * invoke it (if 'execute' is non-zero). + * + * - The thread exits (that is, calls pthread_exit()). + * - The thread acts upon a cancellation request. + * - The thread calls pthread_cleanup_pop() with non-zero execute argument. + * + * Input Parameters: * execute - Execute the popped cleanup function immediately. * * Returned Value: @@ -115,54 +83,5 @@ static void pthread_cleanup_pop_tls(FAR struct tls_info_s *tls, int execute) void pthread_cleanup_pop(int execute) { - FAR struct tls_info_s *tls = tls_get_info(); - - DEBUGASSERT(tls != NULL); - - pthread_cleanup_pop_tls(tls, execute); + tls_cleanup_pop(tls_get_info(), execute); } - -void pthread_cleanup_push(pthread_cleanup_t routine, FAR void *arg) -{ - FAR struct tls_info_s *tls = tls_get_info(); - - DEBUGASSERT(tls != NULL); - DEBUGASSERT(tls->tl_tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE); - - if (tls->tl_tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE) - { - unsigned int ndx = tls->tl_tos; - - tls->tl_tos++; - tls->tl_stack[ndx].pc_cleaner = routine; - tls->tl_stack[ndx].pc_arg = arg; - } -} - -/**************************************************************************** - * Name: pthread_cleanup_popall - * - * Description: - * The pthread_cleanup_popall() is an internal function that will pop and - * execute all clean-up functions. This function is only called from - * within the pthread_exit() and pthread_cancellation() logic - * - * Input Parameters: - * tls - The local storage info of the exiting thread - * - * Returned Value: - * None - * - ****************************************************************************/ - -void pthread_cleanup_popall(FAR struct tls_info_s *tls) -{ - DEBUGASSERT(tls != NULL); - - while (tls->tl_tos > 0) - { - pthread_cleanup_pop_tls(tls, 1); - } -} - -#endif /* defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 */ diff --git a/libs/libc/pthread/pthread_exit.c b/libs/libc/pthread/pthread_exit.c index b18953c198b..25b430650f8 100644 --- a/libs/libc/pthread/pthread_exit.c +++ b/libs/libc/pthread/pthread_exit.c @@ -60,9 +60,7 @@ void pthread_exit(FAR void *exit_value) task_setcancelstate(TASK_CANCEL_DISABLE, NULL); -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 - pthread_cleanup_popall(tls_get_info()); -#endif + tls_cleanup_popall(tls_get_info()); #if defined(CONFIG_TLS_NELEM) && CONFIG_TLS_NELEM > 0 tls_destruct(); diff --git a/libs/libc/pthread/pthread_rwlock_rdlock.c b/libs/libc/pthread/pthread_rwlock_rdlock.c index 1a9b72ce975..46e7b85c0fc 100644 --- a/libs/libc/pthread/pthread_rwlock_rdlock.c +++ b/libs/libc/pthread/pthread_rwlock_rdlock.c @@ -33,14 +33,12 @@ * Private Functions ****************************************************************************/ -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 static void rdlock_cleanup(FAR void *arg) { FAR pthread_rwlock_t *rw_lock = (FAR pthread_rwlock_t *)arg; pthread_mutex_unlock(&rw_lock->lock); } -#endif static int tryrdlock(FAR pthread_rwlock_t *rw_lock) { @@ -109,9 +107,7 @@ int pthread_rwlock_clockrdlock(FAR pthread_rwlock_t *rw_lock, return err; } -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 pthread_cleanup_push(&rdlock_cleanup, rw_lock); -#endif while ((err = tryrdlock(rw_lock)) == EBUSY) { if (ts != NULL) @@ -130,9 +126,7 @@ int pthread_rwlock_clockrdlock(FAR pthread_rwlock_t *rw_lock, } } -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 pthread_cleanup_pop(0); -#endif pthread_mutex_unlock(&rw_lock->lock); return err; diff --git a/libs/libc/pthread/pthread_rwlock_wrlock.c b/libs/libc/pthread/pthread_rwlock_wrlock.c index 9a06807d48a..6260a5fcae5 100644 --- a/libs/libc/pthread/pthread_rwlock_wrlock.c +++ b/libs/libc/pthread/pthread_rwlock_wrlock.c @@ -33,7 +33,6 @@ * Private Functions ****************************************************************************/ -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 static void wrlock_cleanup(FAR void *arg) { FAR pthread_rwlock_t *rw_lock = (FAR pthread_rwlock_t *)arg; @@ -41,7 +40,6 @@ static void wrlock_cleanup(FAR void *arg) rw_lock->num_writers--; pthread_mutex_unlock(&rw_lock->lock); } -#endif /**************************************************************************** * Public Functions @@ -104,9 +102,7 @@ int pthread_rwlock_clockwrlock(FAR pthread_rwlock_t *rw_lock, rw_lock->num_writers++; -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 pthread_cleanup_push(&wrlock_cleanup, rw_lock); -#endif while (rw_lock->write_in_progress || rw_lock->num_readers > 0) { if (ts != NULL) @@ -125,9 +121,7 @@ int pthread_rwlock_clockwrlock(FAR pthread_rwlock_t *rw_lock, } } -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 pthread_cleanup_pop(0); -#endif if (err == 0) { diff --git a/libs/libc/stdlib/lib_exit.c b/libs/libc/stdlib/lib_exit.c index 3dc35bfb69e..e45438b301c 100644 --- a/libs/libc/stdlib/lib_exit.c +++ b/libs/libc/stdlib/lib_exit.c @@ -99,9 +99,7 @@ void exit(int status) task_setcancelstate(TASK_CANCEL_DISABLE, NULL); -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 - pthread_cleanup_popall(tls_get_info()); -#endif + tls_cleanup_popall(tls_get_info()); #if defined(CONFIG_TLS_NELEM) && CONFIG_TLS_NELEM > 0 tls_destruct(); @@ -152,9 +150,7 @@ void quick_exit(int status) task_setcancelstate(TASK_CANCEL_DISABLE, NULL); -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 - pthread_cleanup_popall(tls_get_info()); -#endif + tls_cleanup_popall(tls_get_info()); #if defined(CONFIG_TLS_NELEM) && CONFIG_TLS_NELEM > 0 tls_destruct(); diff --git a/libs/libc/tls/CMakeLists.txt b/libs/libc/tls/CMakeLists.txt index 6943471948d..c882c4cb05f 100644 --- a/libs/libc/tls/CMakeLists.txt +++ b/libs/libc/tls/CMakeLists.txt @@ -28,4 +28,8 @@ if(NOT CONFIG_TLS_NELEM EQUAL 0) list(APPEND SRCS tls_destruct.c) endif() +if(NOT CONFIG_TLS_NCLEANUP EQUAL 0) + list(APPEND SRCS tls_cleanup.c) +endif() + target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/tls/Kconfig b/libs/libc/tls/Kconfig index aaa38ffa5e4..65627e2d49b 100644 --- a/libs/libc/tls/Kconfig +++ b/libs/libc/tls/Kconfig @@ -67,4 +67,14 @@ config TLS_TASK_NELEM NOTE that the 0 value of CONFIG_SCHED_TLS_NELEM disables these TLS interfaces. +config TLS_NCLEANUP + int "Number of cleanup stack levels" + default 0 + range 0 255 + ---help--- + The number of cleanup stack levels. These are used to support + POSIX pthread cancellation. The number of cleanup stack levels + is the maximum number of pthread_cleanup_push() calls that can + be made without a corresponding pthread_cleanup_pop() call. + endmenu # Thread Local Storage (TLS) diff --git a/libs/libc/tls/Make.defs b/libs/libc/tls/Make.defs index 834df9bc2da..788518b709c 100644 --- a/libs/libc/tls/Make.defs +++ b/libs/libc/tls/Make.defs @@ -28,6 +28,10 @@ ifneq ($(CONFIG_TLS_NELEM),0) CSRCS += tls_destruct.c endif +ifneq ($(CONFIG_TLS_NCLEANUP),0) +CSRCS += tls_cleanup.c +endif + # Include tls build support DEPPATH += --dep-path tls diff --git a/libs/libc/tls/tls_cleanup.c b/libs/libc/tls/tls_cleanup.c new file mode 100644 index 00000000000..acf52affe29 --- /dev/null +++ b/libs/libc/tls/tls_cleanup.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * libs/libc/tls/tls_cleanup.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 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void tls_cleanup_push(FAR struct tls_info_s *tls, + tls_cleanup_t routine, FAR void *arg) +{ + DEBUGASSERT(tls != NULL); + DEBUGASSERT(tls->tl_tos < CONFIG_TLS_NCLEANUP); + + if (tls->tl_tos < CONFIG_TLS_NCLEANUP) + { + unsigned int ndx = tls->tl_tos; + + tls->tl_tos++; + tls->tl_stack[ndx].tc_cleaner = routine; + tls->tl_stack[ndx].tc_arg = arg; + } +} + +void tls_cleanup_pop(FAR struct tls_info_s *tls, int execute) +{ + DEBUGASSERT(tls != NULL); + + if (tls->tl_tos > 0) + { + unsigned int ndx; + + /* Get the index to the last cleaner function pushed onto the stack */ + + ndx = tls->tl_tos - 1; + DEBUGASSERT(ndx >= 0 && ndx < CONFIG_TLS_NCLEANUP); + + /* Should we execute the cleanup routine at the top of the stack? */ + + if (execute != 0) + { + FAR struct tls_cleanup_s *cb; + + /* Yes.. Execute the clean-up routine. */ + + cb = &tls->tl_stack[ndx]; + cb->tc_cleaner(cb->tc_arg); + } + + tls->tl_tos = ndx; + } +} + +void tls_cleanup_popall(FAR struct tls_info_s *tls) +{ + DEBUGASSERT(tls != NULL); + + while (tls->tl_tos > 0) + { + tls_cleanup_pop(tls, 1); + } +} diff --git a/sched/Kconfig b/sched/Kconfig index 63f29596df7..dce434f6085 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -884,20 +884,6 @@ config PTHREAD_MUTEX_DEFAULT_PRIO_INHERIT endchoice # Default pthread mutex protocol -config PTHREAD_CLEANUP_STACKSIZE - int "pthread cleanup stack size" - default 0 - range 0 255 - ---help--- - The maximum number of cleanup actions that may be pushed by - pthread_cleanup_push(). - if 0 disable the interfaces pthread_cleanup_push() and pthread_cleanup_pop(). - This setting will increase the size of EVERY - pthread task control block by about n * CONFIG_PTHREAD_CLEANUP_STACKSIZE - where n is the size of a pointer, 2 * sizeof(uintptr_t), this would be - 8 for a CPU with 32-bit addressing and 4 for a CPU with 16-bit - addressing. - config CANCELLATION_POINTS bool "Cancellation points" default n diff --git a/sched/pthread/pthread_cancel.c b/sched/pthread/pthread_cancel.c index c5aeb744f1f..aa631d984c6 100644 --- a/sched/pthread/pthread_cancel.c +++ b/sched/pthread/pthread_cancel.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include "sched/sched.h" #include "task/task.h" @@ -99,9 +99,7 @@ int pthread_cancel(pthread_t thread) /* Refer to tls_get_info() */ -#if defined(CONFIG_PTHREAD_CLEANUP_STACKSIZE) && CONFIG_PTHREAD_CLEANUP_STACKSIZE > 0 - pthread_cleanup_popall(tcb->stack_alloc_ptr); -#endif + tls_cleanup_popall(tcb->stack_alloc_ptr); /* Complete pending join operations */