From 0c8593cf11a16ca75c72977a6f5e3983896940c4 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Thu, 9 Sep 2004 19:46:54 +0000 Subject: [PATCH] 2004-09-09 Paul Brook * 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 * libc/reent/reent.c [_REENT_SMALL]: Fix reference to _on_exit_args_ptr. --- newlib/ChangeLog | 23 ++++++++ newlib/libc/include/sys/reent.h | 28 ++++++---- newlib/libc/reent/reent.c | 4 +- newlib/libc/stdlib/Makefile.am | 4 ++ newlib/libc/stdlib/Makefile.in | 50 +++++++++-------- newlib/libc/stdlib/__atexit.c | 86 ++++++++++++++++++++++++++++++ newlib/libc/stdlib/__call_atexit.c | 83 ++++++++++++++++++++++++++++ newlib/libc/stdlib/atexit.c | 46 +--------------- newlib/libc/stdlib/atexit.h | 17 +++--- newlib/libc/stdlib/cxa_atexit.c | 23 ++++++++ newlib/libc/stdlib/cxa_finalize.c | 20 +++++++ newlib/libc/stdlib/exit.c | 39 +------------- newlib/libc/stdlib/on_exit.c | 39 +------------- 13 files changed, 302 insertions(+), 160 deletions(-) create mode 100644 newlib/libc/stdlib/__atexit.c create mode 100644 newlib/libc/stdlib/__call_atexit.c create mode 100644 newlib/libc/stdlib/cxa_atexit.c create mode 100644 newlib/libc/stdlib/cxa_finalize.c diff --git a/newlib/ChangeLog b/newlib/ChangeLog index d5e7d1769..5ac279f6e 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,26 @@ +2004-09-09 Paul Brook + + * 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 + * libc/reent/reent.c [_REENT_SMALL]: Fix reference to + _on_exit_args_ptr. + 2004-08-23 Jeff Johnston * libc/include/sys/unistd.h (getpass): Change prototype to use diff --git a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h index a216c2434..54f5d8efe 100644 --- a/newlib/libc/include/sys/reent.h +++ b/newlib/libc/include/sys/reent.h @@ -59,19 +59,24 @@ struct __tm }; /* - * atexit() support. For _REENT_SMALL, we limit to 32 max. + * atexit() support. */ #define _ATEXIT_SIZE 32 /* must be at least 32 to guarantee ANSI conformance */ struct _on_exit_args { - void * _fnargs[_ATEXIT_SIZE]; /* fn args for on_exit */ + void * _fnargs[_ATEXIT_SIZE]; /* user fn args */ + void * _dso_handle[_ATEXIT_SIZE]; + /* Bitmask is set if user function takes arguments. */ __ULong _fntypes; /* type of exit routine - - Must have at least _ATEXIT_SIZE bits */ + Must have at least _ATEXIT_SIZE bits */ + /* Bitmask is set if function was registered via __cxa_atexit. */ + __ULong _is_cxa; }; #ifdef _REENT_SMALL struct _atexit { + struct _atexit *_next; /* next in list */ int _ind; /* next index in this table */ void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */ struct _on_exit_args * _on_exit_args_ptr; @@ -80,6 +85,7 @@ struct _atexit { struct _atexit { struct _atexit *_next; /* next in list */ int _ind; /* next index in this table */ + /* Some entries may already have been called, and will be NULL. */ void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */ struct _on_exit_args _on_exit_args; }; @@ -371,7 +377,8 @@ struct _reent void (**(_sig_func))(int); /* atexit stuff */ - struct _atexit _atexit; + struct _atexit *_atexit; + struct _atexit _atexit0; struct _glue __sglue; /* root of glue chain */ __FILE *__sf; /* file descriptors */ @@ -399,7 +406,8 @@ struct _reent _NULL, \ _NULL, \ _NULL, \ - {0, {_NULL}, _NULL}, \ + _NULL, \ + {_NULL, 0, {_NULL}, _NULL}, \ {_NULL, 0, _NULL}, \ _NULL, \ {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL}, \ @@ -426,9 +434,11 @@ struct _reent var->_localtime_buf = _NULL; \ var->_asctime_buf = _NULL; \ var->_sig_func = _NULL; \ - var->_atexit._ind = 0; \ - var->_atexit._fns[0] = _NULL; \ - var->_atexit._on_exit_args = _NULL; \ + var->_atexit = _NULL; \ + var->_atexit0._next = _NULL; \ + var->_atexit0._ind = 0; \ + var->_atexit0._fns[0] = _NULL; \ + var->_atexit0._on_exit_args_ptr = _NULL; \ var->__sglue._next = _NULL; \ var->__sglue._niobs = 0; \ var->__sglue._iobs = _NULL; \ @@ -673,7 +683,7 @@ struct _reent } \ }, \ _NULL, \ - {_NULL, 0, {_NULL}, {{_NULL}, 0}}, \ + {_NULL, 0, {_NULL}, {{_NULL}, {_NULL}, 0, 0}}, \ _NULL, \ {_NULL, 0, _NULL} \ } diff --git a/newlib/libc/reent/reent.c b/newlib/libc/reent/reent.c index 1903e4261..ddf6a8267 100644 --- a/newlib/libc/reent/reent.c +++ b/newlib/libc/reent/reent.c @@ -81,8 +81,8 @@ _DEFUN (_reclaim_reent, (ptr), _free_r (ptr, ptr->_localtime_buf); if (ptr->_asctime_buf) _free_r (ptr, ptr->_asctime_buf); - if (ptr->_atexit._on_exit_args_ptr) - _free_r (ptr, ptr->_atexit._on_exit_args_ptr); + if (ptr->_atexit->_on_exit_args_ptr) + _free_r (ptr, ptr->_atexit->_on_exit_args_ptr); #else /* atexit stuff */ if ((ptr->_atexit) && (ptr->_atexit != &ptr->_atexit0)) diff --git a/newlib/libc/stdlib/Makefile.am b/newlib/libc/stdlib/Makefile.am index 471d17d00..36e61074f 100644 --- a/newlib/libc/stdlib/Makefile.am +++ b/newlib/libc/stdlib/Makefile.am @@ -6,6 +6,8 @@ INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) GENERAL_SOURCES = \ __adjust.c \ + __atexit.c \ + __call_atexit.c \ __exp10.c \ __ten_mu.c \ _Exit.c \ @@ -52,6 +54,8 @@ GENERAL_SOURCES = \ wctomb_r.c EXTENDED_SOURCES = \ + cxa_atexit.c \ + cxa_finalize.c \ drand48.c \ ecvtbuf.c \ efgcvt.c \ diff --git a/newlib/libc/stdlib/Makefile.in b/newlib/libc/stdlib/Makefile.in index d6c264440..46d96b859 100644 --- a/newlib/libc/stdlib/Makefile.in +++ b/newlib/libc/stdlib/Makefile.in @@ -110,10 +110,10 @@ AUTOMAKE_OPTIONS = cygnus INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) -GENERAL_SOURCES = __adjust.c __exp10.c __ten_mu.c _Exit.c abort.c abs.c assert.c atexit.c atof.c atoff.c atoi.c atol.c calloc.c div.c dtoa.c dtoastub.c environ.c envlock.c eprintf.c exit.c getenv.c getenv_r.c labs.c ldiv.c ldtoa.c malloc.c mblen.c mblen_r.c mbstowcs.c mbstowcs_r.c mbtowc.c mbtowc_r.c mlock.c mprec.c mstats.c rand.c rand_r.c realloc.c strtod.c strtol.c strtoul.c wcstombs.c wcstombs_r.c wctomb.c wctomb_r.c +GENERAL_SOURCES = __adjust.c __atexit.c __call_atexit.c __exp10.c __ten_mu.c _Exit.c abort.c abs.c assert.c atexit.c atof.c atoff.c atoi.c atol.c calloc.c div.c dtoa.c dtoastub.c environ.c envlock.c eprintf.c exit.c getenv.c getenv_r.c labs.c ldiv.c ldtoa.c malloc.c mblen.c mblen_r.c mbstowcs.c mbstowcs_r.c mbtowc.c mbtowc_r.c mlock.c mprec.c mstats.c rand.c rand_r.c realloc.c strtod.c strtol.c strtoul.c wcstombs.c wcstombs_r.c wctomb.c wctomb_r.c -EXTENDED_SOURCES = drand48.c ecvtbuf.c efgcvt.c erand48.c jrand48.c lcong48.c lrand48.c mrand48.c msize.c mtrim.c nrand48.c rand48.c seed48.c srand48.c strtoll.c strtoll_r.c strtoull.c strtoull_r.c atoll.c llabs.c lldiv.c +EXTENDED_SOURCES = cxa_atexit.c cxa_finalize.c drand48.c ecvtbuf.c efgcvt.c erand48.c jrand48.c lcong48.c lrand48.c mrand48.c msize.c mtrim.c nrand48.c rand48.c seed48.c srand48.c strtoll.c strtoll_r.c strtoull.c strtoull_r.c atoll.c llabs.c lldiv.c ELIX_2_OBJS = a64l.$(oext) btowc.$(oext) getopt.$(oext) getsubopt.$(oext) l64a.$(oext) malign.$(oext) malignr.$(oext) malloptr.$(oext) mbrlen.$(oext) mbrtowc.$(oext) mbsinit.$(oext) mbsrtowcs.$(oext) on_exit.$(oext) pvallocr.$(oext) valloc.$(oext) vallocr.$(oext) wcrtomb.$(oext) wcsrtombs.$(oext) wctob.$(oext) @@ -168,23 +168,26 @@ LIBRARIES = $(noinst_LIBRARIES) DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LIBS = @LIBS@ -@USE_LIBTOOL_FALSE@lib_a_OBJECTS = __adjust.$(OBJEXT) __exp10.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@__ten_mu.$(OBJEXT) _Exit.$(OBJEXT) abort.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@abs.$(OBJEXT) assert.$(OBJEXT) atexit.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@atof.$(OBJEXT) atoff.$(OBJEXT) atoi.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@atol.$(OBJEXT) calloc.$(OBJEXT) div.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@dtoa.$(OBJEXT) dtoastub.$(OBJEXT) environ.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@envlock.$(OBJEXT) eprintf.$(OBJEXT) exit.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@getenv.$(OBJEXT) getenv_r.$(OBJEXT) labs.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@ldiv.$(OBJEXT) ldtoa.$(OBJEXT) malloc.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mblen.$(OBJEXT) mblen_r.$(OBJEXT) mbstowcs.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@lib_a_OBJECTS = __adjust.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@__atexit.$(OBJEXT) __call_atexit.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@__exp10.$(OBJEXT) __ten_mu.$(OBJEXT) _Exit.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@abort.$(OBJEXT) abs.$(OBJEXT) assert.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@atexit.$(OBJEXT) atof.$(OBJEXT) atoff.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@atoi.$(OBJEXT) atol.$(OBJEXT) calloc.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@div.$(OBJEXT) dtoa.$(OBJEXT) dtoastub.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@environ.$(OBJEXT) envlock.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@eprintf.$(OBJEXT) exit.$(OBJEXT) getenv.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@getenv_r.$(OBJEXT) labs.$(OBJEXT) ldiv.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@ldtoa.$(OBJEXT) malloc.$(OBJEXT) mblen.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mblen_r.$(OBJEXT) mbstowcs.$(OBJEXT) \ @USE_LIBTOOL_FALSE@mbstowcs_r.$(OBJEXT) mbtowc.$(OBJEXT) \ @USE_LIBTOOL_FALSE@mbtowc_r.$(OBJEXT) mlock.$(OBJEXT) mprec.$(OBJEXT) \ @USE_LIBTOOL_FALSE@mstats.$(OBJEXT) rand.$(OBJEXT) rand_r.$(OBJEXT) \ @USE_LIBTOOL_FALSE@realloc.$(OBJEXT) strtod.$(OBJEXT) strtol.$(OBJEXT) \ @USE_LIBTOOL_FALSE@strtoul.$(OBJEXT) wcstombs.$(OBJEXT) \ @USE_LIBTOOL_FALSE@wcstombs_r.$(OBJEXT) wctomb.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@wctomb_r.$(OBJEXT) drand48.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@wctomb_r.$(OBJEXT) cxa_atexit.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@cxa_finalize.$(OBJEXT) drand48.$(OBJEXT) \ @USE_LIBTOOL_FALSE@ecvtbuf.$(OBJEXT) efgcvt.$(OBJEXT) erand48.$(OBJEXT) \ @USE_LIBTOOL_FALSE@jrand48.$(OBJEXT) lcong48.$(OBJEXT) \ @USE_LIBTOOL_FALSE@lrand48.$(OBJEXT) mrand48.$(OBJEXT) msize.$(OBJEXT) \ @@ -195,16 +198,17 @@ LIBS = @LIBS@ @USE_LIBTOOL_FALSE@lldiv.$(OBJEXT) LTLIBRARIES = $(noinst_LTLIBRARIES) -@USE_LIBTOOL_TRUE@libstdlib_la_OBJECTS = __adjust.lo __exp10.lo \ -@USE_LIBTOOL_TRUE@__ten_mu.lo _Exit.lo abort.lo abs.lo assert.lo \ -@USE_LIBTOOL_TRUE@atexit.lo atof.lo atoff.lo atoi.lo atol.lo calloc.lo \ -@USE_LIBTOOL_TRUE@div.lo dtoa.lo dtoastub.lo environ.lo envlock.lo \ -@USE_LIBTOOL_TRUE@eprintf.lo exit.lo getenv.lo getenv_r.lo labs.lo \ -@USE_LIBTOOL_TRUE@ldiv.lo ldtoa.lo malloc.lo mblen.lo mblen_r.lo \ -@USE_LIBTOOL_TRUE@mbstowcs.lo mbstowcs_r.lo mbtowc.lo mbtowc_r.lo \ -@USE_LIBTOOL_TRUE@mlock.lo mprec.lo mstats.lo rand.lo rand_r.lo \ -@USE_LIBTOOL_TRUE@realloc.lo strtod.lo strtol.lo strtoul.lo wcstombs.lo \ -@USE_LIBTOOL_TRUE@wcstombs_r.lo wctomb.lo wctomb_r.lo drand48.lo \ +@USE_LIBTOOL_TRUE@libstdlib_la_OBJECTS = __adjust.lo __atexit.lo \ +@USE_LIBTOOL_TRUE@__call_atexit.lo __exp10.lo __ten_mu.lo _Exit.lo \ +@USE_LIBTOOL_TRUE@abort.lo abs.lo assert.lo atexit.lo atof.lo atoff.lo \ +@USE_LIBTOOL_TRUE@atoi.lo atol.lo calloc.lo div.lo dtoa.lo dtoastub.lo \ +@USE_LIBTOOL_TRUE@environ.lo envlock.lo eprintf.lo exit.lo getenv.lo \ +@USE_LIBTOOL_TRUE@getenv_r.lo labs.lo ldiv.lo ldtoa.lo malloc.lo \ +@USE_LIBTOOL_TRUE@mblen.lo mblen_r.lo mbstowcs.lo mbstowcs_r.lo \ +@USE_LIBTOOL_TRUE@mbtowc.lo mbtowc_r.lo mlock.lo mprec.lo mstats.lo \ +@USE_LIBTOOL_TRUE@rand.lo rand_r.lo realloc.lo strtod.lo strtol.lo \ +@USE_LIBTOOL_TRUE@strtoul.lo wcstombs.lo wcstombs_r.lo wctomb.lo \ +@USE_LIBTOOL_TRUE@wctomb_r.lo cxa_atexit.lo cxa_finalize.lo drand48.lo \ @USE_LIBTOOL_TRUE@ecvtbuf.lo efgcvt.lo erand48.lo jrand48.lo lcong48.lo \ @USE_LIBTOOL_TRUE@lrand48.lo mrand48.lo msize.lo mtrim.lo nrand48.lo \ @USE_LIBTOOL_TRUE@rand48.lo seed48.lo srand48.lo strtoll.lo \ diff --git a/newlib/libc/stdlib/__atexit.c b/newlib/libc/stdlib/__atexit.c new file mode 100644 index 000000000..0c843ade6 --- /dev/null +++ b/newlib/libc/stdlib/__atexit.c @@ -0,0 +1,86 @@ +/* + * Common routine to implement atexit-like functionality. + */ + +#include +#include +#include +#include +#include "atexit.h" + +/* + * Register a function to be performed at exit or on shared library unload. + */ + +int +_DEFUN (__register_exitproc, + (type, fn, arg, d), + int type _AND + void (*fn) (void) _AND + void *arg _AND + void *d) +{ + struct _on_exit_args * args; + register struct _atexit *p; + +#ifndef __SINGLE_THREAD__ + __LOCK_INIT(static, lock); + + __lock_acquire(lock); +#endif + + p = _GLOBAL_REENT->_atexit; + if (p == NULL) + _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0; + if (p->_ind >= _ATEXIT_SIZE) + { + p = (struct _atexit *) malloc (sizeof *p); + if (p == NULL) + { +#ifndef __SINGLE_THREAD__ + __lock_release(lock); +#endif + return -1; + } + p->_ind = 0; + p->_next = _GLOBAL_REENT->_atexit; + _GLOBAL_REENT->_atexit = p; +#ifndef _REENT_SMALL + p->_on_exit_args._fntypes = 0; + p->_on_exit_args._is_cxa = 0; +#endif + } + + if (type != __et_atexit) + { +#ifdef _REENT_SMALL + args = p->_on_exit_args_ptr; + if (args == NULL) + { + args = malloc (sizeof * p->_on_exit_args_ptr); + if (args == NULL) + { +#ifndef __SINGLE_THREAD__ + __lock_release(lock); +#endif + return -1; + } + args->_fntypes = 0; + args->_is_cxa = 0; + p->_on_exit_args_ptr = args; + } +#else + args = &p->_on_exit_args; +#endif + args->_fnargs[p->_ind] = arg; + args->_dso_handle[p->_ind] = d; + args->_fntypes |= (1 << p->_ind); + if (type == __et_cxa) + args->_is_cxa |= (1 << p->_ind); + } + p->_fns[p->_ind++] = fn; +#ifndef __SINGLE_THREAD__ + __lock_release(lock); +#endif + return 0; +} 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 +#include +#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; + } + } +} diff --git a/newlib/libc/stdlib/atexit.c b/newlib/libc/stdlib/atexit.c index 3a9cdc6a3..21ffd6e7b 100644 --- a/newlib/libc/stdlib/atexit.c +++ b/newlib/libc/stdlib/atexit.c @@ -50,10 +50,8 @@ Supporting OS subroutines required: <>, <>, <>, <>, <>, <>, <>. */ -#include #include -#include -#include +#include "atexit.h" /* * Register a function to be performed at exit. @@ -64,45 +62,5 @@ _DEFUN (atexit, (fn), _VOID _EXFUN ((*fn), (_VOID))) { - register struct _atexit *p; - -#ifndef __SINGLE_THREAD__ - __LOCK_INIT(static, lock); - - __lock_acquire(lock); -#endif - - /* _REENT_SMALL atexit() doesn't allow more than the required 32 entries. */ -#ifndef _REENT_SMALL - if ((p = _GLOBAL_REENT->_atexit) == NULL) - _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0; - if (p->_ind >= _ATEXIT_SIZE) - { - if ((p = (struct _atexit *) malloc (sizeof *p)) == NULL) - { -#ifndef __SINGLE_THREAD__ - __lock_release(lock); -#endif - return -1; - } - p->_ind = 0; - p->_on_exit_args._fntypes = 0; - p->_next = _GLOBAL_REENT->_atexit; - _GLOBAL_REENT->_atexit = p; - } -#else - p = &_GLOBAL_REENT->_atexit; - if (p->_ind >= _ATEXIT_SIZE) - { -#ifndef __SINGLE_THREAD__ - __lock_release(lock); -#endif - return -1; - } -#endif - p->_fns[p->_ind++] = fn; -#ifndef __SINGLE_THREAD__ - __lock_release(lock); -#endif - return 0; + return __register_exitproc (__et_atexit, fn, NULL, NULL); } diff --git a/newlib/libc/stdlib/atexit.h b/newlib/libc/stdlib/atexit.h index 44a928126..e37a146a0 100644 --- a/newlib/libc/stdlib/atexit.h +++ b/newlib/libc/stdlib/atexit.h @@ -1,13 +1,14 @@ /* - * %G% (UofMD) %D% + * Common definitions for atexit-like routines */ -#define ATEXIT_SIZE 32 /* must be at least 32 to guarantee ANSI conformance */ - -struct atexit { - struct atexit *next; /* next in list */ - int ind; /* next index in this table */ - void (*fns[ATEXIT_SIZE])(); /* the table itself */ +enum __atexit_types +{ + __et_atexit, + __et_onexit, + __et_cxa }; -struct atexit *__atexit; /* points to head of LIFO stack */ +void __call_exitprocs _PARAMS ((int, _PTR)); +int __register_exitproc _PARAMS ((int, void (*fn) (void), _PTR, _PTR)); + diff --git a/newlib/libc/stdlib/cxa_atexit.c b/newlib/libc/stdlib/cxa_atexit.c new file mode 100644 index 000000000..8c39236de --- /dev/null +++ b/newlib/libc/stdlib/cxa_atexit.c @@ -0,0 +1,23 @@ +/* + * Implementation of __cxa_atexit. + */ + +#include +#include +#include +#include +#include "atexit.h" + +/* + * Register a function to be performed at exit or DSO unload. + */ + +int +_DEFUN (__cxa_atexit, + (fn, arg, d), + void (*fn) (void *) _AND + void *arg _AND + void *d) +{ + return __register_exitproc (__et_cxa, (void (*)(void)) fn, arg, d); +} diff --git a/newlib/libc/stdlib/cxa_finalize.c b/newlib/libc/stdlib/cxa_finalize.c new file mode 100644 index 000000000..17d0526a7 --- /dev/null +++ b/newlib/libc/stdlib/cxa_finalize.c @@ -0,0 +1,20 @@ +/* + * Implementation if __cxa_finalize. + */ + + +#include +#include +#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 (__cxa_finalize, (d), + void * d) +{ + __call_exitprocs (0, d); +} diff --git a/newlib/libc/stdlib/exit.c b/newlib/libc/stdlib/exit.c index be96488c8..b5ef05f5b 100644 --- a/newlib/libc/stdlib/exit.c +++ b/newlib/libc/stdlib/exit.c @@ -48,6 +48,7 @@ Supporting OS subroutines required: <<_exit>>. #include #include /* for _exit() declaration */ #include +#include "atexit.h" #ifndef _REENT_ONLY @@ -59,43 +60,7 @@ void _DEFUN (exit, (code), int code) { - register struct _atexit *p; - register struct _on_exit_args * args; - register int n; - int i; - -#ifdef _REENT_SMALL - p = &_GLOBAL_REENT->_atexit; - args = p->_on_exit_args_ptr; - - if (args == NULL) - { - for (n = p->_ind; n--;) - p->_fns[n] (); - } - else - { - for (n = p->_ind - 1, i = (n >= 0) ? (1 << n) : 0; n >= 0; --n, i >>= 1) - if (args->_fntypes & i) - (*((void (*)(int, void *)) p->_fns[n]))(code, args->_fnargs[n]); - else - p->_fns[n] (); - } -#else - p = _GLOBAL_REENT->_atexit; - while (p) - { - args = & p->_on_exit_args; - - for (n = p->_ind - 1, i = (n >= 0) ? (1 << n) : 0; n >= 0; --n, i >>= 1) - if (args->_fntypes & i) - (*((void (*)(int, void *)) p->_fns[n]))(code, args->_fnargs[n]); - else - p->_fns[n] (); - - p = p->_next; - } -#endif + __call_exitprocs (code, NULL); if (_GLOBAL_REENT->__cleanup) (*_GLOBAL_REENT->__cleanup) (_GLOBAL_REENT); diff --git a/newlib/libc/stdlib/on_exit.c b/newlib/libc/stdlib/on_exit.c index f3383501f..3ac7f998b 100644 --- a/newlib/libc/stdlib/on_exit.c +++ b/newlib/libc/stdlib/on_exit.c @@ -56,7 +56,7 @@ Supporting OS subroutines required: None #include #include -#include +#include "atexit.h" /* * Register a function to be performed at exit. @@ -68,40 +68,5 @@ _DEFUN (on_exit, _VOID _EXFUN ((*fn), (int, _PTR)) _AND _PTR arg) { - struct _on_exit_args * args; - register struct _atexit *p; - void (*x)(void) = (void (*)(void))fn; - -/* _REENT_SMALL on_exit() doesn't allow more than the required 32 entries. */ -#ifdef _REENT_SMALL - p = &_GLOBAL_REENT->_atexit; - if (p->_ind >= _ATEXIT_SIZE) - return -1; - args = p->_on_exit_args_ptr; - if (args == NULL) - { - args = malloc (sizeof * p->_on_exit_args_ptr); - if (args == NULL) - return -1; - args->_fntypes = 0; - p->_on_exit_args_ptr = args; - } -#else - if ((p = _GLOBAL_REENT->_atexit) == NULL) - _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0; - if (p->_ind >= _ATEXIT_SIZE) - { - if ((p = (struct _atexit *) malloc (sizeof *p)) == NULL) - return -1; - p->_ind = 0; - p->_on_exit_args._fntypes = 0; - p->_next = _GLOBAL_REENT->_atexit; - _GLOBAL_REENT->_atexit = p; - } - args = & p->_on_exit_args; -#endif - args->_fntypes |= (1 << p->_ind); - args->_fnargs[p->_ind] = arg; - p->_fns[p->_ind++] = x; - return 0; + return __register_exitproc (__et_onexit, (void (*)(void)) fn, arg, NULL); }