2 * COmmon routine to call call registered atexit-like routines.
11 /* Make this a weak reference to avoid pulling in free. */
12 #ifndef MALLOC_PROVIDED
13 void free(void *) _ATTRIBUTE((__weak__
));
16 #ifndef __SINGLE_THREAD__
17 __LOCK_INIT_RECURSIVE(, __atexit_recursive_mutex
);
20 struct _atexit
*__atexit
= _NULL
;
22 #ifdef _WANT_REGISTER_FINI
24 /* If "__libc_fini" is defined, finalizers (either
25 "__libc_fini_array", or "_fini", as appropriate) will be run after
26 all user-specified atexit handlers. For example, you can define
27 "__libc_fini" to "_fini" in your linker script if you want the C
28 library, rather than startup code, to register finalizers. If you
29 do that, then your startup code need not contain references to
30 "atexit" or "exit". As a result, only applications that reference
31 "exit" explicitly will pull in finalization code.
33 The choice of whether to register finalizers from libc or from
34 startup code is deferred to link-time, rather than being a
35 configure-time option, so that the same C library binary can be
36 used with multiple BSPs, some of which register finalizers from
37 startup code, while others defer to the C library. */
38 extern char __libc_fini
__attribute__((weak
));
40 /* Register the application finalization function with atexit. These
41 finalizers should run last. Therefore, we want to call atexit as
44 register_fini(void) __attribute__((constructor (0)));
50 #ifdef _HAVE_INITFINI_ARRAY
51 extern void __libc_fini_array (void);
52 atexit (__libc_fini_array
);
54 extern void _fini (void);
60 #endif /* _WANT_REGISTER_FINI */
63 * Call registered exit handlers. If D is null then all handlers are called,
64 * otherwise only the handlers from that DSO are called.
68 __call_exitprocs (int code
, void *d
)
70 register struct _atexit
*p
;
71 struct _atexit
**lastp
;
72 register struct _on_exit_args
* args
;
78 #ifndef __SINGLE_THREAD__
79 __lock_acquire_recursive(__atexit_recursive_mutex
);
89 args
= p
->_on_exit_args_ptr
;
91 args
= &p
->_on_exit_args
;
93 for (n
= p
->_ind
- 1; n
>= 0; n
--)
99 /* Skip functions not from this dso. */
100 if (d
&& (!args
|| args
->_dso_handle
[n
] != d
))
103 /* Remove the function now to protect against the
104 function calling exit recursively. */
106 if (n
== p
->_ind
- 1)
111 /* Skip functions that have already been called. */
117 /* Call the function. */
118 if (!args
|| (args
->_fntypes
& i
) == 0)
120 else if ((args
->_is_cxa
& i
) == 0)
121 (*((void (*)(int, void *)) fn
))(code
, args
->_fnargs
[n
]);
123 (*((void (*)(void *)) fn
))(args
->_fnargs
[n
]);
125 /* The function we called call atexit and registered another
126 function (or functions). Call these new functions before
127 continuing with the already registered functions. */
128 if (ind
!= p
->_ind
|| *lastp
!= p
)
132 #if !defined (_ATEXIT_DYNAMIC_ALLOC) || !defined (MALLOC_PROVIDED)
135 /* Move to the next block. Free empty blocks except the last one,
136 which is part of _GLOBAL_REENT. */
137 if (p
->_ind
== 0 && p
->_next
)
139 /* Remove empty block from the list. */
155 #ifndef __SINGLE_THREAD__
156 __lock_release_recursive(__atexit_recursive_mutex
);