Rev 4874 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4874 | Rev 4921 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* |
1 | /* |
2 | * Common routine to implement atexit-like functionality. |
2 | * Common routine to implement atexit-like functionality. |
- | 3 | * |
|
- | 4 | * This is also the key function to be configured as lite exit, a size-reduced |
|
- | 5 | * implementation of exit that doesn't invoke clean-up functions such as _fini |
|
- | 6 | * or global destructors. |
|
- | 7 | * |
|
- | 8 | * Default (without lite exit) call graph is like: |
|
- | 9 | * _start -> atexit -> __register_exitproc |
|
- | 10 | * _start -> __libc_init_array -> __cxa_atexit -> __register_exitproc |
|
- | 11 | * on_exit -> __register_exitproc |
|
- | 12 | * _start -> exit -> __call_exitprocs |
|
- | 13 | * |
|
- | 14 | * Here an -> means arrow tail invokes arrow head. All invocations here |
|
- | 15 | * are non-weak reference in current newlib/libgloss. |
|
- | 16 | * |
|
- | 17 | * Lite exit makes some of above calls as weak reference, so that size expansive |
|
- | 18 | * functions __register_exitproc and __call_exitprocs may not be linked. These |
|
- | 19 | * calls are: |
|
- | 20 | * _start w-> atexit |
|
- | 21 | * __cxa_atexit w-> __register_exitproc |
|
- | 22 | * exit w-> __call_exitprocs |
|
- | 23 | * |
|
- | 24 | * Lite exit also makes sure that __call_exitprocs will be referenced as non-weak |
|
- | 25 | * whenever __register_exitproc is referenced as non-weak. |
|
- | 26 | * |
|
- | 27 | * Thus with lite exit libs, a program not explicitly calling atexit or on_exit |
|
- | 28 | * will escape from the burden of cleaning up code. A program with atexit or on_exit |
|
- | 29 | * will work consistently to normal libs. |
|
- | 30 | * |
|
- | 31 | * Lite exit is enabled with --enable-lite-exit, and is controlled with macro |
|
- | 32 | * _LITE_EXIT. |
|
3 | */ |
33 | */ |
Line 4... | Line 34... | ||
4 | 34 | ||
5 | #include |
35 | #include |
6 | #include |
36 | #include |
7 | #include |
37 | #include |
8 | #include |
38 | #include |
Line 9... | Line 39... | ||
9 | #include "atexit.h" |
39 | #include "atexit.h" |
10 | 40 | ||
- | 41 | /* Make this a weak reference to avoid pulling in malloc. */ |
|
- | 42 | void * malloc(size_t) _ATTRIBUTE((__weak__)); |
|
- | 43 | ||
- | 44 | #ifdef _LITE_EXIT |
|
- | 45 | /* As __call_exitprocs is weak reference in lite exit, make a |
|
- | 46 | non-weak reference to it here. */ |
|
- | 47 | const void * __atexit_dummy = &__call_exitprocs; |
|
- | 48 | #endif |
|
11 | /* Make this a weak reference to avoid pulling in malloc. */ |
49 | |
- | 50 | #ifndef __SINGLE_THREAD__ |
|
- | 51 | extern _LOCK_RECURSIVE_T __atexit_lock; |
|
- | 52 | #endif |
|
- | 53 | ||
- | 54 | #ifdef _REENT_GLOBAL_ATEXIT |
|
- | 55 | static struct _atexit _global_atexit0 = _ATEXIT_INIT; |
|
- | 56 | # define _GLOBAL_ATEXIT0 (&_global_atexit0) |
|
- | 57 | #else |
|
Line 12... | Line 58... | ||
12 | void * malloc(size_t) _ATTRIBUTE((__weak__)); |
58 | # define _GLOBAL_ATEXIT0 (&_GLOBAL_REENT->_atexit0) |
13 | __LOCK_INIT_RECURSIVE(, __atexit_lock); |
59 | #endif |
14 | 60 | ||
Line 29... | Line 75... | ||
29 | 75 | ||
30 | #ifndef __SINGLE_THREAD__ |
76 | #ifndef __SINGLE_THREAD__ |
31 | __lock_acquire_recursive(__atexit_lock); |
77 | __lock_acquire_recursive(__atexit_lock); |
Line 32... | Line 78... | ||
32 | #endif |
78 | #endif |
33 | 79 | ||
34 | p = _GLOBAL_REENT->_atexit; |
80 | p = _GLOBAL_ATEXIT; |
35 | if (p == NULL) |
81 | if (p == NULL) |
36 | _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0; |
82 | _GLOBAL_ATEXIT = p = _GLOBAL_ATEXIT0; |
37 | if (p->_ind >= _ATEXIT_SIZE) |
83 | if (p->_ind >= _ATEXIT_SIZE) |
38 | { |
84 | { |
39 | #ifndef _ATEXIT_DYNAMIC_ALLOC |
85 | #ifndef _ATEXIT_DYNAMIC_ALLOC |
Line 51... | Line 97... | ||
51 | __lock_release_recursive(__atexit_lock); |
97 | __lock_release_recursive(__atexit_lock); |
52 | #endif |
98 | #endif |
53 | return -1; |
99 | return -1; |
54 | } |
100 | } |
55 | p->_ind = 0; |
101 | p->_ind = 0; |
56 | p->_next = _GLOBAL_REENT->_atexit; |
102 | p->_next = _GLOBAL_ATEXIT; |
57 | _GLOBAL_REENT->_atexit = p; |
103 | _GLOBAL_ATEXIT = p; |
58 | #ifndef _REENT_SMALL |
104 | #ifndef _REENT_SMALL |
59 | p->_on_exit_args._fntypes = 0; |
105 | p->_on_exit_args._fntypes = 0; |
60 | p->_on_exit_args._is_cxa = 0; |
106 | p->_on_exit_args._is_cxa = 0; |
- | 107 | #else |
|
- | 108 | p->_on_exit_args_ptr = NULL; |
|
61 | #endif |
109 | #endif |
62 | #endif |
110 | #endif |
63 | } |
111 | } |
Line 64... | Line 112... | ||
64 | 112 | ||
Line 72... | Line 120... | ||
72 | args = malloc (sizeof * p->_on_exit_args_ptr); |
120 | args = malloc (sizeof * p->_on_exit_args_ptr); |
Line 73... | Line 121... | ||
73 | 121 | ||
74 | if (args == NULL) |
122 | if (args == NULL) |
75 | { |
123 | { |
76 | #ifndef __SINGLE_THREAD__ |
124 | #ifndef __SINGLE_THREAD__ |
77 | __lock_release(lock); |
125 | __lock_release(__atexit_lock); |
78 | #endif |
126 | #endif |
79 | return -1; |
127 | return -1; |
80 | } |
128 | } |
81 | args->_fntypes = 0; |
129 | args->_fntypes = 0; |