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