From eb26187767da1e752bfdc6571ccb70e3f84fd954 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 1 Nov 2012 16:50:53 +0000 Subject: Add __cxa_atexit(); atexit() is now built on top of on_exit() git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5292 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/ChangeLog | 8 +- nuttx/configs/sim/cxxtest/defconfig | 3 +- nuttx/include/nuttx/sched.h | 6 +- nuttx/libxx/Makefile | 6 +- nuttx/libxx/libxx_cxa_atexit.cxx | 143 ++++++++++++++++++++++++++++++++++++ nuttx/libxx/libxx_eabi_atexit.cxx | 23 +++--- nuttx/libxx/libxx_internal.hxx | 67 +++++++++++++++++ nuttx/sched/Kconfig | 11 ++- nuttx/sched/atexit.c | 16 +++- nuttx/sched/on_exit.c | 5 +- nuttx/sched/task_exithook.c | 4 +- 11 files changed, 263 insertions(+), 29 deletions(-) create mode 100644 nuttx/libxx/libxx_cxa_atexit.cxx create mode 100644 nuttx/libxx/libxx_internal.hxx (limited to 'nuttx') diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 40ff0a51b..6fa9ffbfe 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -3547,4 +3547,10 @@ is equivalent to !feof()); the others should be good. * configs/stm32f4discovery/include/board.h: Correct timer 2-7 base frequency (provided by Freddie Chopin). - + * include/nuttx/sched.h, sched/atexit.c, and sched/task_deletehook.c: + If both atexit() and on_exit() are enabled, then implement atexit() + as just a special caseof on_exit(). This assumes that the ABI can + handle receipt of more call parameters than the receiving function + expects. That is usually the case if parameters are passed in + registers. + * libxx/libxx_cxa_atexit(): Implements __cxa_atexit() diff --git a/nuttx/configs/sim/cxxtest/defconfig b/nuttx/configs/sim/cxxtest/defconfig index 5797c8d4c..d7f5efff5 100644 --- a/nuttx/configs/sim/cxxtest/defconfig +++ b/nuttx/configs/sim/cxxtest/defconfig @@ -136,7 +136,8 @@ CONFIG_SDCLONE_DISABLE=y # CONFIG_SCHED_WORKQUEUE is not set # CONFIG_SCHED_WAITPID is not set # CONFIG_SCHED_ATEXIT is not set -# CONFIG_SCHED_ONEXIT is not set +CONFIG_SCHED_ONEXIT=y +CONFIG_SCHED_ONEXIT_MAX=4 CONFIG_USER_ENTRYPOINT="cxxtest_main" CONFIG_DISABLE_OS_API=y # CONFIG_DISABLE_CLOCK is not set diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h index 241af6210..172f46901 100644 --- a/nuttx/include/nuttx/sched.h +++ b/nuttx/include/nuttx/sched.h @@ -138,11 +138,11 @@ typedef union entry_u entry_t; */ #ifdef CONFIG_SCHED_ATEXIT -typedef void (*atexitfunc_t)(void); +typedef CODE void (*atexitfunc_t)(void); #endif #ifdef CONFIG_SCHED_ONEXIT -typedef void (*onexitfunc_t)(int exitcode, FAR void *arg); +typedef CODE void (*onexitfunc_t)(int exitcode, FAR void *arg); #endif /* POSIX Message queue */ @@ -189,7 +189,7 @@ struct _TCB start_t start; /* Thread start function */ entry_t entry; /* Entry Point into the thread */ -#ifdef CONFIG_SCHED_ATEXIT +#if defined(CONFIG_SCHED_ATEXIT) && !defined(CONFIG_SCHED_ONEXIT) # if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 atexitfunc_t atexitfunc[CONFIG_SCHED_ATEXIT_MAX]; # else diff --git a/nuttx/libxx/Makefile b/nuttx/libxx/Makefile index 922c8d825..bc8c5012e 100644 --- a/nuttx/libxx/Makefile +++ b/nuttx/libxx/Makefile @@ -39,8 +39,10 @@ ASRCS = CSRCS = -CXXSRCS = libxx_cxapurevirtual.cxx libxx_delete.cxx libxx_deletea.cxx -CXXSRCS += libxx_eabi_atexit.cxx libxx_new.cxx libxx_newa.cxx + +CXXSRCS = libxx_cxapurevirtual.cxx libxx_delete.cxx libxx_deletea.cxx +CXXSRCS += libxx_eabi_atexit.cxx libxx_cxa_atexit.cxx libxx_new.cxx +CXXSRCS += libxx_newa.cxx # Paths diff --git a/nuttx/libxx/libxx_cxa_atexit.cxx b/nuttx/libxx/libxx_cxa_atexit.cxx new file mode 100644 index 000000000..7e6d00a37 --- /dev/null +++ b/nuttx/libxx/libxx_cxa_atexit.cxx @@ -0,0 +1,143 @@ +//*************************************************************************** +// libxx/libxx_eabi_atexit.cxx +// +// Copyright (C) 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +#include +#include + +#include "libxx_internal.hxx" + +//*************************************************************************** +// Pre-processor Definitions +//*************************************************************************** + +//*************************************************************************** +// Private Types +//*************************************************************************** + +struct __cxa_atexit_s +{ + __cxa_exitfunc_t func; + FAR void *arg; +}; + +//*************************************************************************** +// Private Data +//*************************************************************************** + +extern "C" +{ + //************************************************************************* + // Public Data + //************************************************************************* + + FAR void *__dso_handle = NULL; + + //************************************************************************* + // Private Functions + //************************************************************************* + + //************************************************************************* + // Name: __cxa_callback + // + // Description: + // This is really just an "adaptor" function that matches the form of + // the __cxa_exitfunc_t to an onexitfunc_t using an allocated structure + // to marshall the call parameters. + // + //************************************************************************* + +#if CONFIG_SCHED_ONEXIT + static void __cxa_callback(int exitcode, FAR void *arg) + { + FAR struct __cxa_atexit_s *alloc = (FAR struct __cxa_atexit_s *)arg; + DEBUGASSERT(alloc && alloc->func); + + alloc->func(alloc->arg); + free(alloc); + } +#endif + + //************************************************************************* + // Public Functions + //************************************************************************* + + //************************************************************************* + // Name: __cxa_atexit + // + // Description: + // __cxa_atexit() registers a destructor function to be called by exit(). + // On a call to exit(), the registered functions should be called with + // the single argument 'arg'. Destructor functions shall always be + // called in the reverse order to their registration (i.e. the most + // recently registered function shall be called first), + // + // If shared libraries were supported, the callbacks should be invoked + // when the shared library is unloaded as well. + // + // Reference: + // Linux base + // + //************************************************************************* + + int __cxa_atexit(__cxa_exitfunc_t func, FAR void *arg, FAR void *dso_handle) + { +#if CONFIG_SCHED_ONEXIT + // Allocate memory to hold the marshaled __cxa_exitfunc_t call + // information. + + FAR struct __cxa_atexit_s *alloc = + (FAR struct __cxa_atexit_s *)malloc(sizeof(struct __cxa_atexit_s)); + + if (alloc) + { + // Register the function to be called when the task/thread exists. + + return on_exit(__cxa_callback, alloc); + } + else +#endif + { + // What else can we do? + + return 0; + } + } +} diff --git a/nuttx/libxx/libxx_eabi_atexit.cxx b/nuttx/libxx/libxx_eabi_atexit.cxx index aa0ff6956..25f8306a8 100644 --- a/nuttx/libxx/libxx_eabi_atexit.cxx +++ b/nuttx/libxx/libxx_eabi_atexit.cxx @@ -40,26 +40,22 @@ #include #include +#include "libxx_internal.hxx" + //*************************************************************************** -// Definitions +// Pre-processor Definitions //*************************************************************************** //*************************************************************************** // Private Data //*************************************************************************** +//*************************************************************************** +// Public Functions +//*************************************************************************** + extern "C" { - //************************************************************************* - // Public Data - //************************************************************************* - - void *__dso_handle = NULL; - - //************************************************************************* - // Public Functions - //************************************************************************* - //************************************************************************* // Name: __aeabi_atexit // @@ -75,9 +71,8 @@ extern "C" // //************************************************************************* - int __aeabi_atexit(void* object, void (*destroyer)(void*), void *dso_handle) + int __aeabi_atexit(FAR void *object, __cxa_exitfunc_t func, FAR void *dso_handle) { - //return __cxa_atexit(destroyer, object, dso_handle); // 0 ? OK; non-0 ? failed } - return 0; + return __cxa_atexit(func, object, dso_handle); // 0 ? OK; non-0 ? failed } } diff --git a/nuttx/libxx/libxx_internal.hxx b/nuttx/libxx/libxx_internal.hxx new file mode 100644 index 000000000..fe84c763e --- /dev/null +++ b/nuttx/libxx/libxx_internal.hxx @@ -0,0 +1,67 @@ +//*************************************************************************** +// lib/libxx_internal.h +// +// Copyright (C) 2012 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//*************************************************************************** + +#ifndef __LIBXX_LIBXX_INTERNAL_HXX +#define __LIBXX_LIBXX_INTERNAL_HXX + +//*************************************************************************** +// Included Files +//*************************************************************************** + +#include + +//*************************************************************************** +// Definitions +//*************************************************************************** + +//*************************************************************************** +// Public Types +//***************************************************************************/ + +typedef CODE void (*__cxa_exitfunc_t)(void *arg); + +//*************************************************************************** +// Public Variables +//*************************************************************************** + +extern "C" FAR void *__dso_handle; + +//*************************************************************************** +// Public Function Prototypes +//*************************************************************************** + +extern "C" int __cxa_atexit(__cxa_exitfunc_t func, void *arg, void *dso_handle); + +#endif // __LIBXX_LIBXX_INTERNAL_HXX diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig index 4f7149595..4a3e87745 100644 --- a/nuttx/sched/Kconfig +++ b/nuttx/sched/Kconfig @@ -214,12 +214,17 @@ config SCHED_ATEXIT config SCHED_ATEXIT_MAX int "Max number of atexit() functions" default 1 - depends on SCHED_ATEXIT + depends on SCHED_ATEXIT && !SCHED_ONEXIT ---help--- By default if SCHED_ATEXIT is selected, only a single atexit() function is supported. That number can be increased by defined this setting to the number that you require. + If both SCHED_ONEXIT and SCHED_ATEXIT are selected, then atexit() is built + on top of the on_exit() implementation. In that case, SCHED_ONEXIT_MAX + determines the size of the combined number of atexit(0) and on_exit calls + and SCHED_ATEXIT_MAX is not used. + config SCHED_ONEXIT bool "Enable on_exit() API" default n @@ -235,6 +240,10 @@ config SCHED_ONEXIT_MAX is supported. That number can be increased by defined this setting to the number that you require. + If both SCHED_ONEXIT and SCHED_ATEXIT are selected, then atexit() is built + on top of the on_exit() implementation. In that case, SCHED_ONEXIT_MAX + determines the size of the combined number of atexit(0) and on_exit calls. + config USER_ENTRYPOINT string "Application entry point" default "user_start" diff --git a/nuttx/sched/atexit.c b/nuttx/sched/atexit.c index f7d81bec2..b0559b01b 100644 --- a/nuttx/sched/atexit.c +++ b/nuttx/sched/atexit.c @@ -96,8 +96,13 @@ * CONFIG_SCHED_ATEXIT_MAX defines a larger number. * 2. atexit functions are not inherited when a new task is * created. + * 3. If both SCHED_ONEXIT and SCHED_ATEXIT are selected, then atexit() + * is built on top of the on_exit() implementation. In that case, + * CONFIG_SCHED_ONEXIT_MAX determines the size of the combined + * number of atexit(0) and on_exit calls and SCHED_ATEXIT_MAX is + * not used. * - * Parameters: + * Input Parameters: * func - A pointer to the function to be called when the task exits. * * Return Value: @@ -107,7 +112,14 @@ int atexit(void (*func)(void)) { -#if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 +#if defined(CONFIG_SCHED_ONEXIT) + /* atexit is equivalent to on_exit() with no argument (Assuming that the ABI + * can handle a callback function that recieves more parameters than it expects). + */ + + return on_exit(onexitfunc_t func, NULL); + +#elif defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 _TCB *tcb = (_TCB*)g_readytorun.head; int index; int ret = ERROR; diff --git a/nuttx/sched/on_exit.c b/nuttx/sched/on_exit.c index 5b8be5cd1..19a4f9196 100644 --- a/nuttx/sched/on_exit.c +++ b/nuttx/sched/on_exit.c @@ -117,7 +117,7 @@ int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg) #if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1 _TCB *tcb = (_TCB*)g_readytorun.head; int index; - int ret = ERROR; + int ret = ENOSPC; /* The following must be atomic */ @@ -131,7 +131,6 @@ int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg) * indices. */ - available = -1; for (index = 0; index < CONFIG_SCHED_ONEXIT_MAX; index++) { if (!tcb->onexitfunc[index]) @@ -149,7 +148,7 @@ int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg) return ret; #else _TCB *tcb = (_TCB*)g_readytorun.head; - int ret = ERROR; + int ret = ENOSPC; /* The following must be atomic */ diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c index e94476f2a..6f52ef739 100644 --- a/nuttx/sched/task_exithook.c +++ b/nuttx/sched/task_exithook.c @@ -81,8 +81,8 @@ * Call any registerd atexit function(s) * ****************************************************************************/ - -#ifdef CONFIG_SCHED_ATEXIT + +#if defined(CONFIG_SCHED_ATEXIT) && !defined(CONFIG_SCHED_ONEXIT) static inline void task_atexit(FAR _TCB *tcb) { #if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 -- cgit v1.2.3