Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libc / stdlib / __atexit.c
blobe59f04c2e440140348e69a10d13a31b9f4e558dd
1 /*
2 * Common routine to implement atexit-like functionality.
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.
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
14 * Here an -> means arrow tail invokes arrow head. All invocations here
15 * are non-weak reference in current newlib/libgloss.
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
24 * Lite exit also makes sure that __call_exitprocs will be referenced as non-weak
25 * whenever __register_exitproc is referenced as non-weak.
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.
31 * Lite exit is enabled with --enable-lite-exit, and is controlled with macro
32 * _LITE_EXIT.
35 #include <stddef.h>
36 #include <stdlib.h>
37 #include <reent.h>
38 #include <sys/lock.h>
39 #include "atexit.h"
41 /* Make this a weak reference to avoid pulling in malloc. */
42 #ifndef MALLOC_PROVIDED
43 void * malloc(size_t) _ATTRIBUTE((__weak__));
44 #endif
46 #ifdef _LITE_EXIT
47 /* As __call_exitprocs is weak reference in lite exit, make a
48 non-weak reference to it here. */
49 const void * __atexit_dummy = &__call_exitprocs;
50 #endif
52 #ifndef __SINGLE_THREAD__
53 extern _LOCK_RECURSIVE_T __atexit_recursive_mutex;
54 #endif
56 struct _atexit __atexit0 = _ATEXIT_INIT;
59 * Register a function to be performed at exit or on shared library unload.
62 int
63 __register_exitproc (int type,
64 void (*fn) (void),
65 void *arg,
66 void *d)
68 struct _on_exit_args * args;
69 register struct _atexit *p;
71 #ifndef __SINGLE_THREAD__
72 __lock_acquire_recursive(__atexit_recursive_mutex);
73 #endif
75 p = __atexit;
76 if (p == NULL)
78 __atexit = p = &__atexit0;
79 #ifdef _REENT_SMALL
80 extern struct _on_exit_args * const __on_exit_args _ATTRIBUTE ((weak));
81 if (&__on_exit_args != NULL)
82 p->_on_exit_args_ptr = __on_exit_args;
83 #endif /* def _REENT_SMALL */
85 if (p->_ind >= _ATEXIT_SIZE)
87 #if !defined (_ATEXIT_DYNAMIC_ALLOC) || !defined (MALLOC_PROVIDED)
88 #ifndef __SINGLE_THREAD__
89 __lock_release_recursive(__atexit_recursive_mutex);
90 #endif
91 return -1;
92 #else
93 p = (struct _atexit *) malloc (sizeof *p);
94 if (p == NULL)
96 #ifndef __SINGLE_THREAD__
97 __lock_release_recursive(__atexit_recursive_mutex);
98 #endif
99 return -1;
101 p->_ind = 0;
102 p->_next = __atexit;
103 __atexit = p;
104 #ifndef _REENT_SMALL
105 p->_on_exit_args._fntypes = 0;
106 p->_on_exit_args._is_cxa = 0;
107 #else
108 p->_on_exit_args_ptr = NULL;
109 #endif
110 #endif
113 if (type != __et_atexit)
115 #ifdef _REENT_SMALL
116 args = p->_on_exit_args_ptr;
117 if (args == NULL)
119 #ifndef _ATEXIT_DYNAMIC_ALLOC
120 #ifndef __SINGLE_THREAD__
121 __lock_release_recursive(__atexit_recursive_mutex);
122 #endif
123 return -1;
124 #else
125 if (malloc)
126 args = malloc (sizeof * p->_on_exit_args_ptr);
128 if (args == NULL)
130 #ifndef __SINGLE_THREAD__
131 __lock_release_recursive(__atexit_recursive_mutex);
132 #endif
133 return -1;
135 args->_fntypes = 0;
136 args->_is_cxa = 0;
137 p->_on_exit_args_ptr = args;
138 #endif
140 #else
141 args = &p->_on_exit_args;
142 #endif
143 args->_fnargs[p->_ind] = arg;
144 args->_fntypes |= (1 << p->_ind);
145 args->_dso_handle[p->_ind] = d;
146 if (type == __et_cxa)
147 args->_is_cxa |= (1 << p->_ind);
149 p->_fns[p->_ind++] = fn;
150 #ifndef __SINGLE_THREAD__
151 __lock_release_recursive(__atexit_recursive_mutex);
152 #endif
153 return 0;