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,8 → 40,24 |
|
/* 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 |
__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,11 → 99,13 |
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; |
#else |
p->_on_exit_args_ptr = NULL; |
#endif |
#endif |
} |
74,7 → 122,7 |
if (args == NULL) |
{ |
#ifndef __SINGLE_THREAD__ |
__lock_release(lock); |
__lock_release(__atexit_lock); |
#endif |
return -1; |
} |