Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libc / stdlib / __call_atexit.c
blob710440389bfdbd98c9d33e10ac6e2aef5b3dd398
1 /*
2 * COmmon routine to call call registered atexit-like routines.
3 */
6 #include <stdlib.h>
7 #include <reent.h>
8 #include <sys/lock.h>
9 #include "atexit.h"
11 /* Make this a weak reference to avoid pulling in free. */
12 #ifndef MALLOC_PROVIDED
13 void free(void *) _ATTRIBUTE((__weak__));
14 #endif
16 #ifndef __SINGLE_THREAD__
17 __LOCK_INIT_RECURSIVE(, __atexit_recursive_mutex);
18 #endif
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
42 soon as possible. */
43 static void
44 register_fini(void) __attribute__((constructor (0)));
46 static void
47 register_fini(void)
49 if (&__libc_fini) {
50 #ifdef _HAVE_INITFINI_ARRAY
51 extern void __libc_fini_array (void);
52 atexit (__libc_fini_array);
53 #else
54 extern void _fini (void);
55 atexit (_fini);
56 #endif
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.
67 void
68 __call_exitprocs (int code, void *d)
70 register struct _atexit *p;
71 struct _atexit **lastp;
72 register struct _on_exit_args * args;
73 register int n;
74 int i;
75 void (*fn) (void);
78 #ifndef __SINGLE_THREAD__
79 __lock_acquire_recursive(__atexit_recursive_mutex);
80 #endif
82 restart:
84 p = __atexit;
85 lastp = &__atexit;
86 while (p)
88 #ifdef _REENT_SMALL
89 args = p->_on_exit_args_ptr;
90 #else
91 args = &p->_on_exit_args;
92 #endif
93 for (n = p->_ind - 1; n >= 0; n--)
95 int ind;
97 i = 1 << n;
99 /* Skip functions not from this dso. */
100 if (d && (!args || args->_dso_handle[n] != d))
101 continue;
103 /* Remove the function now to protect against the
104 function calling exit recursively. */
105 fn = p->_fns[n];
106 if (n == p->_ind - 1)
107 p->_ind--;
108 else
109 p->_fns[n] = NULL;
111 /* Skip functions that have already been called. */
112 if (!fn)
113 continue;
115 ind = p->_ind;
117 /* Call the function. */
118 if (!args || (args->_fntypes & i) == 0)
119 fn ();
120 else if ((args->_is_cxa & i) == 0)
121 (*((void (*)(int, void *)) fn))(code, args->_fnargs[n]);
122 else
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)
129 goto restart;
132 #if !defined (_ATEXIT_DYNAMIC_ALLOC) || !defined (MALLOC_PROVIDED)
133 break;
134 #else
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. */
140 *lastp = p->_next;
141 #ifdef _REENT_SMALL
142 if (args)
143 free (args);
144 #endif
145 free (p);
146 p = *lastp;
148 else
150 lastp = &p->_next;
151 p = p->_next;
153 #endif
155 #ifndef __SINGLE_THREAD__
156 __lock_release_recursive(__atexit_recursive_mutex);
157 #endif