1*b1e83836Smrg /* Copyright (C) 1999-2022 Free Software Foundation, Inc.
248fb7bfaSmrg
348fb7bfaSmrg NOTE: This source is derived from an old version taken from the GNU C
448fb7bfaSmrg Library (glibc).
548fb7bfaSmrg
648fb7bfaSmrg This file is part of GCC.
748fb7bfaSmrg
848fb7bfaSmrg GCC is free software; you can redistribute it and/or modify it under
948fb7bfaSmrg the terms of the GNU General Public License as published by the Free
1048fb7bfaSmrg Software Foundation; either version 3, or (at your option) any later
1148fb7bfaSmrg version.
1248fb7bfaSmrg
1348fb7bfaSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1448fb7bfaSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1548fb7bfaSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1648fb7bfaSmrg for more details.
1748fb7bfaSmrg
1848fb7bfaSmrg Under Section 7 of GPL version 3, you are granted additional
1948fb7bfaSmrg permissions described in the GCC Runtime Library Exception, version
2048fb7bfaSmrg 3.1, as published by the Free Software Foundation.
2148fb7bfaSmrg
2248fb7bfaSmrg You should have received a copy of the GNU General Public License and
2348fb7bfaSmrg a copy of the GCC Runtime Library Exception along with this program;
2448fb7bfaSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2548fb7bfaSmrg <http://www.gnu.org/licenses/>. */
2648fb7bfaSmrg
2748fb7bfaSmrg #include <assert.h>
2848fb7bfaSmrg #include <stdlib.h>
2948fb7bfaSmrg #include "exit.h"
3048fb7bfaSmrg
3148fb7bfaSmrg
3248fb7bfaSmrg static boolean_t
catomic_compare_and_exchange_bool_acq(long * mem,long newval,long oldval)3348fb7bfaSmrg catomic_compare_and_exchange_bool_acq (long *mem, long newval, long oldval)
3448fb7bfaSmrg {
354d5abbe8Smrg return ! __atomic_compare_exchange (mem, &oldval, &newval, 0,
3648fb7bfaSmrg __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
3748fb7bfaSmrg }
3848fb7bfaSmrg
3948fb7bfaSmrg /* If D is non-NULL, call all functions registered with `__cxa_atexit'
4048fb7bfaSmrg with the same dso handle. Otherwise, if D is NULL, call all of the
4148fb7bfaSmrg registered handlers. */
4248fb7bfaSmrg void
__cxa_finalize(void * d)4348fb7bfaSmrg __cxa_finalize (void *d)
4448fb7bfaSmrg {
4548fb7bfaSmrg struct exit_function_list *funcs;
4648fb7bfaSmrg
4748fb7bfaSmrg restart:
4848fb7bfaSmrg for (funcs = __exit_funcs; funcs; funcs = funcs->next)
4948fb7bfaSmrg {
5048fb7bfaSmrg struct exit_function *f;
5148fb7bfaSmrg
5248fb7bfaSmrg for (f = &funcs->fns[funcs->idx - 1]; f >= &funcs->fns[0]; --f)
5348fb7bfaSmrg {
5448fb7bfaSmrg void (*cxafn) (void *arg, int status);
5548fb7bfaSmrg void *cxaarg;
5648fb7bfaSmrg
5748fb7bfaSmrg if ((d == NULL || d == f->func.cxa.dso_handle)
5848fb7bfaSmrg /* We don't want to run this cleanup more than once. */
5948fb7bfaSmrg && (cxafn = f->func.cxa.fn,
6048fb7bfaSmrg cxaarg = f->func.cxa.arg,
6148fb7bfaSmrg ! catomic_compare_and_exchange_bool_acq (&f->flavor, ef_free,
6248fb7bfaSmrg ef_cxa)))
6348fb7bfaSmrg {
6448fb7bfaSmrg uint64_t check = __new_exitfn_called;
6548fb7bfaSmrg
6648fb7bfaSmrg #ifdef PTR_DEMANGLE
6748fb7bfaSmrg PTR_DEMANGLE (cxafn);
6848fb7bfaSmrg #endif
6948fb7bfaSmrg cxafn (cxaarg, 0);
7048fb7bfaSmrg
7148fb7bfaSmrg /* It is possible that that last exit function registered
7248fb7bfaSmrg more exit functions. Start the loop over. */
7348fb7bfaSmrg if (__builtin_expect (check != __new_exitfn_called, 0))
7448fb7bfaSmrg goto restart;
7548fb7bfaSmrg }
7648fb7bfaSmrg }
7748fb7bfaSmrg }
7848fb7bfaSmrg
7948fb7bfaSmrg /* Remove the registered fork handlers. We do not have to
8048fb7bfaSmrg unregister anything if the program is going to terminate anyway. */
8148fb7bfaSmrg #ifdef UNREGISTER_ATFORK
8248fb7bfaSmrg if (d != NULL)
8348fb7bfaSmrg UNREGISTER_ATFORK (d);
8448fb7bfaSmrg #endif
8548fb7bfaSmrg }
86