summaryrefslogtreecommitdiffstats
path: root/newlib/libc/stdlib/__call_atexit.c
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/stdlib/__call_atexit.c')
-rw-r--r--newlib/libc/stdlib/__call_atexit.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/newlib/libc/stdlib/__call_atexit.c b/newlib/libc/stdlib/__call_atexit.c
index 6dd2ec63a..c99b2744e 100644
--- a/newlib/libc/stdlib/__call_atexit.c
+++ b/newlib/libc/stdlib/__call_atexit.c
@@ -15,6 +15,42 @@ void free(void *) _ATTRIBUTE((__weak__));
extern _LOCK_RECURSIVE_T __atexit_lock;
#endif
+/* If "__libc_fini" is defined, finalizers (either
+ "__libc_fini_array", or "_fini", as appropriate) will be run after
+ all user-specified atexit handlers. For example, you can define
+ "__libc_fini" to "_fini" in your linker script if you want the C
+ library, rather than startup code, to register finalizers. If you
+ do that, then your startup code need not contain references to
+ "atexit" or "exit". As a result, only applications that reference
+ "exit" explicitly will pull in finalization code.
+
+ The choice of whether to register finalizers from libc or from
+ startup code is deferred to link-time, rather than being a
+ configure-time option, so that the same C library binary can be
+ used with multiple BSPs, some of which register finalizers from
+ startup code, while others defer to the C library. */
+extern char __libc_fini __attribute__((weak));
+
+/* Register the application finalization function with atexit. These
+ finalizers should run last. Therefore, we want to call atexit as
+ soon as possible. */
+static void
+register_fini(void) __attribute__((constructor (0)));
+
+static void
+register_fini(void)
+{
+ if (&__libc_fini) {
+#ifdef HAVE_INITFINI_ARRAY
+ extern void __libc_fini_array (void);
+ atexit (__libc_fini_array);
+#else
+ extern void _fini (void);
+ atexit (_fini);
+#endif
+ }
+}
+
/*
* Call registered exit handlers. If D is null then all handlers are called,
* otherwise only the handlers from that DSO are called.