diff options
Diffstat (limited to 'newlib/libc/stdlib/__call_atexit.c')
-rw-r--r-- | newlib/libc/stdlib/__call_atexit.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/newlib/libc/stdlib/__call_atexit.c b/newlib/libc/stdlib/__call_atexit.c new file mode 100644 index 000000000..cea569ff4 --- /dev/null +++ b/newlib/libc/stdlib/__call_atexit.c @@ -0,0 +1,83 @@ +/* + * COmmon routine to call call registered atexit-like routines. + */ + + +#include <stdlib.h> +#include <reent.h> +#include "atexit.h" + +/* + * Call registered exit handlers. If D is null then all handlers are called, + * otherwise only the handlers from that DSO are called. + */ + +void +_DEFUN (__call_exitprocs, (code, d), + int code _AND _PTR d) +{ + register struct _atexit *p; + struct _atexit **lastp; + register struct _on_exit_args * args; + register int n; + int i; + void (*fn) (void); + + p = _GLOBAL_REENT->_atexit; + lastp = &_GLOBAL_REENT->_atexit; + while (p) + { +#ifdef _REENT_SMALL + args = p->_on_exit_args_ptr; +#else + args = &p->_on_exit_args; +#endif + for (n = p->_ind - 1; n >= 0; n--) + { + i = 1 << n; + + /* Skip functions not from this dso. */ + if (d && (!args || args->_dso_handle[n] != d)) + continue; + + /* Remove the function now to protect against the + function calling exit recursively. */ + fn = p->_fns[n]; + if (n == p->_ind - 1) + p->_ind--; + else + p->_fns[n] = NULL; + + /* Skip functions that have already been called. */ + if (!fn) + continue; + + /* Call the function. */ + if (!args || (args->_fntypes & i) == 0) + fn (); + else if ((args->_is_cxa & i) == 0) + (*((void (*)(int, _PTR)) fn))(code, args->_fnargs[n]); + else + (*((void (*)(_PTR)) fn))(args->_fnargs[n]); + } + + /* Move to the next block. Free empty blocks except the last one, + which is part of _GLOBAL_REENT. */ + if (p->_ind == 0 && p->_next) + { + /* Remove empty block from the list. */ + *lastp = p->_next; +#ifdef _REENT_SMALL + if (args) + free (args); +#endif + free (p); + p = *lastp; + } + else + { + lastp = &p->_next; + p = p->_next; + } + } +} |