libc: Implement quick_exit and at_quick_exit
Defined by c11: https://en.cppreference.com/w/c/program/quick_exit https://en.cppreference.com/w/c/program/at_quick_exit Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
parent
d7ee492fc4
commit
bcd1ebf260
|
@ -51,8 +51,10 @@ namespace std
|
||||||
// Process exit functions
|
// Process exit functions
|
||||||
|
|
||||||
using ::exit;
|
using ::exit;
|
||||||
|
using ::quick_exit;
|
||||||
using ::abort;
|
using ::abort;
|
||||||
using ::atexit;
|
using ::atexit;
|
||||||
|
using ::at_quick_exit;
|
||||||
using ::on_exit;
|
using ::on_exit;
|
||||||
|
|
||||||
#ifndef __KERNEL__
|
#ifndef __KERNEL__
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -44,6 +45,7 @@ enum atexit_type_e
|
||||||
{
|
{
|
||||||
ATTYPE_NONE,
|
ATTYPE_NONE,
|
||||||
ATTYPE_ATEXIT,
|
ATTYPE_ATEXIT,
|
||||||
|
ATTYPE_ATQUICKEXIT,
|
||||||
ATTYPE_ONEXIT,
|
ATTYPE_ONEXIT,
|
||||||
ATTYPE_CXA
|
ATTYPE_CXA
|
||||||
};
|
};
|
||||||
|
@ -106,10 +108,10 @@ int atexit_register(int type, CODE void (*func)(void), FAR void *arg,
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void atexit_call_exitfuncs(int status);
|
void atexit_call_exitfuncs(int status, bool quick);
|
||||||
#else
|
#else
|
||||||
# define atexit_register(type, func, arg, dso) (0)
|
# define atexit_register(type, func, arg, dso) (0)
|
||||||
# define atexit_call_exitfuncs(status)
|
# define atexit_call_exitfuncs(status, quick)
|
||||||
#endif /* CONFIG_LIBC_MAX_EXITFUNS */
|
#endif /* CONFIG_LIBC_MAX_EXITFUNS */
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
|
@ -166,8 +166,10 @@ int unsetenv(FAR const char *name);
|
||||||
/* Process exit functions */
|
/* Process exit functions */
|
||||||
|
|
||||||
void exit(int status) noreturn_function;
|
void exit(int status) noreturn_function;
|
||||||
|
void quick_exit(int status) noreturn_function;
|
||||||
void abort(void) noreturn_function;
|
void abort(void) noreturn_function;
|
||||||
int atexit(CODE void (*func)(void));
|
int atexit(CODE void (*func)(void));
|
||||||
|
int at_quick_exit(CODE void (*func)(void));
|
||||||
int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg);
|
int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg);
|
||||||
|
|
||||||
/* _Exit() is a stdlib.h equivalent to the unistd.h _exit() function */
|
/* _Exit() is a stdlib.h equivalent to the unistd.h _exit() function */
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static FAR struct atexit_list_s * get_exitfuncs(void)
|
static FAR struct atexit_list_s *get_exitfuncs(void)
|
||||||
{
|
{
|
||||||
FAR struct task_info_s *info;
|
FAR struct task_info_s *info;
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ int atexit_register(int type, CODE void (*func)(void), FAR void *arg,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void atexit_call_exitfuncs(int status)
|
void atexit_call_exitfuncs(int status, bool quick)
|
||||||
{
|
{
|
||||||
FAR struct atexit_list_s *aehead;
|
FAR struct atexit_list_s *aehead;
|
||||||
CODE void (*func)(void);
|
CODE void (*func)(void);
|
||||||
|
@ -134,9 +134,14 @@ void atexit_call_exitfuncs(int status)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (quick != (type == ATTYPE_ATQUICKEXIT))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Call the atexit/on_exit/cxa_atexit() function */
|
/* Call the atexit/on_exit/cxa_atexit() function */
|
||||||
|
|
||||||
if (type == ATTYPE_ATEXIT)
|
if (type == ATTYPE_ATEXIT || type == ATTYPE_ATQUICKEXIT)
|
||||||
{
|
{
|
||||||
(*func)();
|
(*func)();
|
||||||
}
|
}
|
||||||
|
@ -181,3 +186,23 @@ int atexit(CODE void (*func)(void))
|
||||||
{
|
{
|
||||||
return atexit_register(ATTYPE_ATEXIT, func, NULL, NULL);
|
return atexit_register(ATTYPE_ATEXIT, func, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: at_quick_exit
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Registers the function pointed to by func to be called on quick
|
||||||
|
* program termination (via quick_exit).
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* func - A pointer to the function to be called when the task exits.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero on success. Non-zero on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int at_quick_exit(CODE void (*func)(void))
|
||||||
|
{
|
||||||
|
return atexit_register(ATTYPE_ATQUICKEXIT, func, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
|
@ -46,11 +46,47 @@ FAR void *__dso_handle = &__dso_handle;
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: exit
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The exit() function causes normal process termination and the
|
||||||
|
* least significant byte of status (i.e., status & 0xFF) is
|
||||||
|
* returned to the parent (see wait(2)).
|
||||||
|
*
|
||||||
|
* All functions registered with atexit(3) and on_exit(3) are
|
||||||
|
* called, in the reverse order of their registration. (It is
|
||||||
|
* possible for one of these functions to use atexit(3) or
|
||||||
|
* on_exit(3) to register an additional function to be executed
|
||||||
|
* during exit processing; the new registration is added to the
|
||||||
|
* front of the list of functions that remain to be called.) If one
|
||||||
|
* of these functions does not return (e.g., it calls _exit(2), or
|
||||||
|
* kills itself with a signal), then none of the remaining functions
|
||||||
|
* is called, and further exit processing (in particular, flushing
|
||||||
|
* of stdio(3) streams) is abandoned. If a function has been
|
||||||
|
* registered multiple times using atexit(3) or on_exit(3), then it
|
||||||
|
* is called as many times as it was registered.
|
||||||
|
*
|
||||||
|
* All open stdio(3) streams are flushed and closed. Files created
|
||||||
|
* by tmpfile(3) are removed.
|
||||||
|
*
|
||||||
|
* The C standard specifies two constants, EXIT_SUCCESS and
|
||||||
|
* EXIT_FAILURE, that may be passed to exit() to indicate successful
|
||||||
|
* or unsuccessful termination, respectively.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* status - Exit status code
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Does not return.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void exit(int status)
|
void exit(int status)
|
||||||
{
|
{
|
||||||
/* Run the registered exit functions */
|
/* Run the registered exit functions */
|
||||||
|
|
||||||
atexit_call_exitfuncs(status);
|
atexit_call_exitfuncs(status, false);
|
||||||
|
|
||||||
/* Flush all streams */
|
/* Flush all streams */
|
||||||
|
|
||||||
|
@ -61,6 +97,51 @@ void exit(int status)
|
||||||
_exit(status);
|
_exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: quick_exit
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The quick_exit() function exits the program quickly calling any cleanup
|
||||||
|
* functions registered with at_quick_exit(3) but not any C++ destructors
|
||||||
|
* or cleanup code registered with atexit(3). The stdio(3) file buffers
|
||||||
|
* are not flushed.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* status - Exit status code
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Does not return.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void quick_exit(int status)
|
||||||
|
{
|
||||||
|
/* Run the registered exit functions */
|
||||||
|
|
||||||
|
atexit_call_exitfuncs(status, true);
|
||||||
|
|
||||||
|
/* Then perform the exit */
|
||||||
|
|
||||||
|
_exit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: _Exit
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The _Exit() functions shall not call functions registered with atexit()
|
||||||
|
* nor any registered signal handlers. Open streams shall not be flushed.
|
||||||
|
* Whether open streams are closed (without flushing) is implementation
|
||||||
|
* defined.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* status - Exit status code
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Does not return.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void _Exit(int status)
|
void _Exit(int status)
|
||||||
{
|
{
|
||||||
_exit(status);
|
_exit(status);
|
||||||
|
|
Loading…
Reference in New Issue