1 /*
2 Copyright (c) 2004 Paul Brook <paul@codesourcery.com>
3 
4 Common routine to implement atexit-like functionality.
5 
6 This is also the key function to be configured as lite exit, a size-reduced
7 implementation of exit that doesn't invoke clean-up functions such as _fini
8 or global destructors.
9 
10 Default (without lite exit) call graph is like:
11 start -> atexit -> __register_exitproc
12 start -> __libc_init_array -> __cxa_atexit -> __register_exitproc
13 on_exit -> __register_exitproc
14 start -> exit -> __call_exitprocs
15 
16 Here an -> means arrow tail invokes arrow head. All invocations here
17 are non-weak reference in current newlib.
18 
19 Lite exit makes some of above calls as weak reference, so that size expansive
20 functions __register_exitproc and __call_exitprocs may not be linked. These
21 calls are:
22 start w-> atexit
23 cxa_atexit w-> __register_exitproc
24 exit w-> __call_exitprocs
25 
26 Lite exit also makes sure that __call_exitprocs will be referenced as non-weak
27 whenever __register_exitproc is referenced as non-weak.
28 
29 Thus with lite exit libs, a program not explicitly calling atexit or on_exit
30 will escape from the burden of cleaning up code. A program with atexit or on_exit
31 will work consistently to normal libs.
32 
33 Lite exit is enabled with --enable-lite-exit, and is controlled with macro
34 LITE_EXIT.
35  */
36 /*
37  * Implementation of __cxa_atexit.
38  */
39 
40 #include <stddef.h>
41 #include <stdlib.h>
42 #include <sys/lock.h>
43 #include "atexit.h"
44 
45 /*
46  * Register a function to be performed at exit or DSO unload.
47  */
48 
49 int
__cxa_atexit(void (* fn)(void *),void * arg,void * d)50 __cxa_atexit (void (*fn) (void *),
51 	void *arg,
52 	void *d)
53 {
54 #ifdef _LITE_EXIT
55   /* Refer to comments in __atexit.c for more details of lite exit.  */
56   int __register_exitproc (int, void (*fn) (void), void *, void *)
57     __attribute__ ((weak));
58 
59   if (!__register_exitproc)
60     return 0;
61   else
62 #endif
63     return __register_exitproc (__et_cxa, (void (*)(void)) fn, arg, d);
64 }
65