You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pk...@apache.org on 2023/01/25 12:31:44 UTC
[nuttx] 01/03: libc: Implement quick_exit and at_quick_exit
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit bcd1ebf26056fb1ebbd0abfdd081c1568f299d32
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Sat Jan 21 00:23:16 2023 +0800
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 <xi...@xiaomi.com>
---
include/cxx/cstdlib | 2 ++
include/nuttx/atexit.h | 6 ++--
include/stdlib.h | 2 ++
libs/libc/stdlib/lib_atexit.c | 31 ++++++++++++++--
libs/libc/stdlib/lib_exit.c | 83 ++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 118 insertions(+), 6 deletions(-)
diff --git a/include/cxx/cstdlib b/include/cxx/cstdlib
index 51bc3d8d26..34483cdf9c 100644
--- a/include/cxx/cstdlib
+++ b/include/cxx/cstdlib
@@ -51,8 +51,10 @@ namespace std
// Process exit functions
using ::exit;
+ using ::quick_exit;
using ::abort;
using ::atexit;
+ using ::at_quick_exit;
using ::on_exit;
#ifndef __KERNEL__
diff --git a/include/nuttx/atexit.h b/include/nuttx/atexit.h
index ad511290b5..84a0167f3a 100644
--- a/include/nuttx/atexit.h
+++ b/include/nuttx/atexit.h
@@ -26,6 +26,7 @@
****************************************************************************/
#include <nuttx/config.h>
+#include <stdbool.h>
#include <stdlib.h>
/****************************************************************************
@@ -44,6 +45,7 @@ enum atexit_type_e
{
ATTYPE_NONE,
ATTYPE_ATEXIT,
+ ATTYPE_ATQUICKEXIT,
ATTYPE_ONEXIT,
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
# define atexit_register(type, func, arg, dso) (0)
-# define atexit_call_exitfuncs(status)
+# define atexit_call_exitfuncs(status, quick)
#endif /* CONFIG_LIBC_MAX_EXITFUNS */
#if defined(__cplusplus)
diff --git a/include/stdlib.h b/include/stdlib.h
index a522680a65..5e90eb5d08 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -166,8 +166,10 @@ int unsetenv(FAR const char *name);
/* Process exit functions */
void exit(int status) noreturn_function;
+void quick_exit(int status) noreturn_function;
void abort(void) noreturn_function;
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);
/* _Exit() is a stdlib.h equivalent to the unistd.h _exit() function */
diff --git a/libs/libc/stdlib/lib_atexit.c b/libs/libc/stdlib/lib_atexit.c
index 0486cdf63b..eab0894667 100644
--- a/libs/libc/stdlib/lib_atexit.c
+++ b/libs/libc/stdlib/lib_atexit.c
@@ -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;
@@ -105,7 +105,7 @@ int atexit_register(int type, CODE void (*func)(void), FAR void *arg,
return ret;
}
-void atexit_call_exitfuncs(int status)
+void atexit_call_exitfuncs(int status, bool quick)
{
FAR struct atexit_list_s *aehead;
CODE void (*func)(void);
@@ -134,9 +134,14 @@ void atexit_call_exitfuncs(int status)
continue;
}
+ if (quick != (type == ATTYPE_ATQUICKEXIT))
+ {
+ continue;
+ }
+
/* Call the atexit/on_exit/cxa_atexit() function */
- if (type == ATTYPE_ATEXIT)
+ if (type == ATTYPE_ATEXIT || type == ATTYPE_ATQUICKEXIT)
{
(*func)();
}
@@ -181,3 +186,23 @@ int atexit(CODE void (*func)(void))
{
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);
+}
diff --git a/libs/libc/stdlib/lib_exit.c b/libs/libc/stdlib/lib_exit.c
index c2e81206c5..2cef9eff1b 100644
--- a/libs/libc/stdlib/lib_exit.c
+++ b/libs/libc/stdlib/lib_exit.c
@@ -46,11 +46,47 @@ FAR void *__dso_handle = &__dso_handle;
* 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)
{
/* Run the registered exit functions */
- atexit_call_exitfuncs(status);
+ atexit_call_exitfuncs(status, false);
/* Flush all streams */
@@ -61,6 +97,51 @@ void exit(int 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)
{
_exit(status);