Browse Source

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
sbg
patacongo 12 years ago
parent
commit
eb26187767
  1. 8
      nuttx/ChangeLog
  2. 3
      nuttx/configs/sim/cxxtest/defconfig
  3. 6
      nuttx/include/nuttx/sched.h
  4. 4
      nuttx/libxx/Makefile
  5. 143
      nuttx/libxx/libxx_cxa_atexit.cxx
  6. 23
      nuttx/libxx/libxx_eabi_atexit.cxx
  7. 67
      nuttx/libxx/libxx_internal.hxx
  8. 11
      nuttx/sched/Kconfig
  9. 16
      nuttx/sched/atexit.c
  10. 5
      nuttx/sched/on_exit.c
  11. 2
      nuttx/sched/task_exithook.c

8
nuttx/ChangeLog

@ -3547,4 +3547,10 @@
is equivalent to !feof()); the others should be good. is equivalent to !feof()); the others should be good.
* configs/stm32f4discovery/include/board.h: Correct timer 2-7 * configs/stm32f4discovery/include/board.h: Correct timer 2-7
base frequency (provided by Freddie Chopin). 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()

3
nuttx/configs/sim/cxxtest/defconfig

@ -136,7 +136,8 @@ CONFIG_SDCLONE_DISABLE=y
# CONFIG_SCHED_WORKQUEUE is not set # CONFIG_SCHED_WORKQUEUE is not set
# CONFIG_SCHED_WAITPID is not set # CONFIG_SCHED_WAITPID is not set
# CONFIG_SCHED_ATEXIT 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_USER_ENTRYPOINT="cxxtest_main"
CONFIG_DISABLE_OS_API=y CONFIG_DISABLE_OS_API=y
# CONFIG_DISABLE_CLOCK is not set # CONFIG_DISABLE_CLOCK is not set

6
nuttx/include/nuttx/sched.h

@ -138,11 +138,11 @@ typedef union entry_u entry_t;
*/ */
#ifdef CONFIG_SCHED_ATEXIT #ifdef CONFIG_SCHED_ATEXIT
typedef void (*atexitfunc_t)(void); typedef CODE void (*atexitfunc_t)(void);
#endif #endif
#ifdef CONFIG_SCHED_ONEXIT #ifdef CONFIG_SCHED_ONEXIT
typedef void (*onexitfunc_t)(int exitcode, FAR void *arg); typedef CODE void (*onexitfunc_t)(int exitcode, FAR void *arg);
#endif #endif
/* POSIX Message queue */ /* POSIX Message queue */
@ -189,7 +189,7 @@ struct _TCB
start_t start; /* Thread start function */ start_t start; /* Thread start function */
entry_t entry; /* Entry Point into the thread */ 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 # if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1
atexitfunc_t atexitfunc[CONFIG_SCHED_ATEXIT_MAX]; atexitfunc_t atexitfunc[CONFIG_SCHED_ATEXIT_MAX];
# else # else

4
nuttx/libxx/Makefile

@ -39,8 +39,10 @@
ASRCS = ASRCS =
CSRCS = CSRCS =
CXXSRCS = libxx_cxapurevirtual.cxx libxx_delete.cxx libxx_deletea.cxx CXXSRCS = libxx_cxapurevirtual.cxx libxx_delete.cxx libxx_deletea.cxx
CXXSRCS += libxx_eabi_atexit.cxx libxx_new.cxx libxx_newa.cxx CXXSRCS += libxx_eabi_atexit.cxx libxx_cxa_atexit.cxx libxx_new.cxx
CXXSRCS += libxx_newa.cxx
# Paths # Paths

143
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 <gnutt@nuttx.org>
//
// 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 <nuttx/config.h>
#include <cstdlib>
#include <cassert>
#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;
}
}
}

23
nuttx/libxx/libxx_eabi_atexit.cxx

@ -40,26 +40,22 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <cstdlib> #include <cstdlib>
#include "libxx_internal.hxx"
//*************************************************************************** //***************************************************************************
// Definitions // Pre-processor Definitions
//*************************************************************************** //***************************************************************************
//*************************************************************************** //***************************************************************************
// Private Data // Private Data
//*************************************************************************** //***************************************************************************
extern "C" //***************************************************************************
{
//*************************************************************************
// Public Data
//*************************************************************************
void *__dso_handle = NULL;
//*************************************************************************
// Public Functions // Public Functions
//************************************************************************* //***************************************************************************
extern "C"
{
//************************************************************************* //*************************************************************************
// Name: __aeabi_atexit // 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 __cxa_atexit(func, object, dso_handle); // 0 ? OK; non-0 ? failed
return 0;
} }
} }

67
nuttx/libxx/libxx_internal.hxx

@ -0,0 +1,67 @@
//***************************************************************************
// lib/libxx_internal.h
//
// Copyright (C) 2012 Gregory Nutt. All rights reserved.
// Author: Gregory Nutt <gnutt@nuttx.org>
//
// 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 <nuttx/config.h>
//***************************************************************************
// 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

11
nuttx/sched/Kconfig

@ -214,12 +214,17 @@ config SCHED_ATEXIT
config SCHED_ATEXIT_MAX config SCHED_ATEXIT_MAX
int "Max number of atexit() functions" int "Max number of atexit() functions"
default 1 default 1
depends on SCHED_ATEXIT depends on SCHED_ATEXIT && !SCHED_ONEXIT
---help--- ---help---
By default if SCHED_ATEXIT is selected, only a single atexit() function By default if SCHED_ATEXIT is selected, only a single atexit() function
is supported. That number can be increased by defined this setting to is supported. That number can be increased by defined this setting to
the number that you require. 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 config SCHED_ONEXIT
bool "Enable on_exit() API" bool "Enable on_exit() API"
default n default n
@ -235,6 +240,10 @@ config SCHED_ONEXIT_MAX
is supported. That number can be increased by defined this setting to the is supported. That number can be increased by defined this setting to the
number that you require. 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 config USER_ENTRYPOINT
string "Application entry point" string "Application entry point"
default "user_start" default "user_start"

16
nuttx/sched/atexit.c

@ -96,8 +96,13 @@
* CONFIG_SCHED_ATEXIT_MAX defines a larger number. * CONFIG_SCHED_ATEXIT_MAX defines a larger number.
* 2. atexit functions are not inherited when a new task is * 2. atexit functions are not inherited when a new task is
* created. * 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. * func - A pointer to the function to be called when the task exits.
* *
* Return Value: * Return Value:
@ -107,7 +112,14 @@
int atexit(void (*func)(void)) 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; _TCB *tcb = (_TCB*)g_readytorun.head;
int index; int index;
int ret = ERROR; int ret = ERROR;

5
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 #if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1
_TCB *tcb = (_TCB*)g_readytorun.head; _TCB *tcb = (_TCB*)g_readytorun.head;
int index; int index;
int ret = ERROR; int ret = ENOSPC;
/* The following must be atomic */ /* The following must be atomic */
@ -131,7 +131,6 @@ int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg)
* indices. * indices.
*/ */
available = -1;
for (index = 0; index < CONFIG_SCHED_ONEXIT_MAX; index++) for (index = 0; index < CONFIG_SCHED_ONEXIT_MAX; index++)
{ {
if (!tcb->onexitfunc[index]) if (!tcb->onexitfunc[index])
@ -149,7 +148,7 @@ int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg)
return ret; return ret;
#else #else
_TCB *tcb = (_TCB*)g_readytorun.head; _TCB *tcb = (_TCB*)g_readytorun.head;
int ret = ERROR; int ret = ENOSPC;
/* The following must be atomic */ /* The following must be atomic */

2
nuttx/sched/task_exithook.c

@ -82,7 +82,7 @@
* *
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SCHED_ATEXIT #if defined(CONFIG_SCHED_ATEXIT) && !defined(CONFIG_SCHED_ONEXIT)
static inline void task_atexit(FAR _TCB *tcb) static inline void task_atexit(FAR _TCB *tcb)
{ {
#if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 #if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1

Loading…
Cancel
Save