Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Johnston <jjohnstn@redhat.com>2004-09-09 23:46:54 +0400
committerJeff Johnston <jjohnstn@redhat.com>2004-09-09 23:46:54 +0400
commit0c8593cf11a16ca75c72977a6f5e3983896940c4 (patch)
tree8133764892ae91831d48980ef216fc4935e45b5f /newlib/libc/stdlib/__call_atexit.c
parent582dde69f31fb0dbe4beca5461b2b08924ae4e20 (diff)
2004-09-09 Paul Brook <paul@codesourcery.com>
* libc/include/sys/reent.h (struct _on_exit_args): Add _dso_handle and _is_cxa. (struct _atexit): Add _next when _REENT_SMALL. (struct _reent): Add _atexit0 when _REENT_SMALL. (_REENT_INIT_PTR): Adjust. * libc/stdlib/Makefile.am (GENERAL_SOURCES): Add __atexit.c and __call_exit.c. (EXTENDED_SOURCES): Add cxa_atexit.c and cxa_finalize.c. * libc/stdlib/Makefile.in: Regenerate. * libc/stdlib/__atexit.c: New file. * libc/stdlib/__call_atexit.c: New file. * libc/stdlib/atexit.h: Remove old definitions. Add new. * libc/stdlib/atexit.c (atexit): Use __register_exitproc. * libc/stdlib/cxa_atexit.c: New file. * libc/stdlib/cxa_finalize.c: New file. * libc/stdlib/exit.c (exit): Use __call_exitprocs. * libc/stdlib/on_exit.c (on_exit): Use __register_exitproc. 2004-09-09 Jeff Johnston <jjohnstn@redhat.com> * libc/reent/reent.c [_REENT_SMALL]: Fix reference to _on_exit_args_ptr.
Diffstat (limited to 'newlib/libc/stdlib/__call_atexit.c')
-rw-r--r--newlib/libc/stdlib/__call_atexit.c83
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;
+ }
+ }
+}