Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/stdlib/__atexit.c')
-rw-r--r--newlib/libc/stdlib/__atexit.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/newlib/libc/stdlib/__atexit.c b/newlib/libc/stdlib/__atexit.c
index 4687d0023..d36a1a4e5 100644
--- a/newlib/libc/stdlib/__atexit.c
+++ b/newlib/libc/stdlib/__atexit.c
@@ -1,5 +1,35 @@
/*
* Common routine to implement atexit-like functionality.
+ *
+ * This is also the key function to be configured as lite exit, a size-reduced
+ * implementation of exit that doesn't invoke clean-up functions such as _fini
+ * or global destructors.
+ *
+ * Default (without lite exit) call graph is like:
+ * _start -> atexit -> __register_exitproc
+ * _start -> __libc_init_array -> __cxa_atexit -> __register_exitproc
+ * on_exit -> __register_exitproc
+ * _start -> exit -> __call_exitprocs
+ *
+ * Here an -> means arrow tail invokes arrow head. All invocations here
+ * are non-weak reference in current newlib/libgloss.
+ *
+ * Lite exit makes some of above calls as weak reference, so that size expansive
+ * functions __register_exitproc and __call_exitprocs may not be linked. These
+ * calls are:
+ * _start w-> atexit
+ * __cxa_atexit w-> __register_exitproc
+ * exit w-> __call_exitprocs
+ *
+ * Lite exit also makes sure that __call_exitprocs will be referenced as non-weak
+ * whenever __register_exitproc is referenced as non-weak.
+ *
+ * Thus with lite exit libs, a program not explicitly calling atexit or on_exit
+ * will escape from the burden of cleaning up code. A program with atexit or on_exit
+ * will work consistently to normal libs.
+ *
+ * Lite exit is enabled with --enable-lite-exit, and is controlled with macro
+ * _LITE_EXIT.
*/
#include <stddef.h>
@@ -10,7 +40,23 @@
/* Make this a weak reference to avoid pulling in malloc. */
void * malloc(size_t) _ATTRIBUTE((__weak__));
-__LOCK_INIT_RECURSIVE(, __atexit_lock);
+
+#ifdef _LITE_EXIT
+/* As __call_exitprocs is weak reference in lite exit, make a
+ non-weak reference to it here. */
+const void * __atexit_dummy = &__call_exitprocs;
+#endif
+
+#ifndef __SINGLE_THREAD__
+extern _LOCK_RECURSIVE_T __atexit_lock;
+#endif
+
+#ifdef _REENT_GLOBAL_ATEXIT
+static struct _atexit _global_atexit0 = _ATEXIT_INIT;
+# define _GLOBAL_ATEXIT0 (&_global_atexit0)
+#else
+# define _GLOBAL_ATEXIT0 (&_GLOBAL_REENT->_atexit0)
+#endif
/*
* Register a function to be performed at exit or on shared library unload.
@@ -31,9 +77,9 @@ _DEFUN (__register_exitproc,
__lock_acquire_recursive(__atexit_lock);
#endif
- p = _GLOBAL_REENT->_atexit;
+ p = _GLOBAL_ATEXIT;
if (p == NULL)
- _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0;
+ _GLOBAL_ATEXIT = p = _GLOBAL_ATEXIT0;
if (p->_ind >= _ATEXIT_SIZE)
{
#ifndef _ATEXIT_DYNAMIC_ALLOC
@@ -53,8 +99,8 @@ _DEFUN (__register_exitproc,
return -1;
}
p->_ind = 0;
- p->_next = _GLOBAL_REENT->_atexit;
- _GLOBAL_REENT->_atexit = p;
+ p->_next = _GLOBAL_ATEXIT;
+ _GLOBAL_ATEXIT = p;
#ifndef _REENT_SMALL
p->_on_exit_args._fntypes = 0;
p->_on_exit_args._is_cxa = 0;