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
This commit is contained in:
patacongo 2012-11-01 16:50:53 +00:00
parent 1214744afc
commit eb26187767
11 changed files with 263 additions and 29 deletions

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -40,26 +40,22 @@
#include <nuttx/config.h>
#include <cstdlib>
#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
}
}

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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 */

View File

@ -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