OSDN Git Service

2004-09-09 Paul Brook <paul@codesourcery.com>
authorjjohnstn <jjohnstn>
Thu, 9 Sep 2004 19:46:53 +0000 (19:46 +0000)
committerjjohnstn <jjohnstn>
Thu, 9 Sep 2004 19:46:53 +0000 (19:46 +0000)
        * 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.

13 files changed:
newlib/ChangeLog
newlib/libc/include/sys/reent.h
newlib/libc/reent/reent.c
newlib/libc/stdlib/Makefile.am
newlib/libc/stdlib/Makefile.in
newlib/libc/stdlib/__atexit.c [new file with mode: 0644]
newlib/libc/stdlib/__call_atexit.c [new file with mode: 0644]
newlib/libc/stdlib/atexit.c
newlib/libc/stdlib/atexit.h
newlib/libc/stdlib/cxa_atexit.c [new file with mode: 0644]
newlib/libc/stdlib/cxa_finalize.c [new file with mode: 0644]
newlib/libc/stdlib/exit.c
newlib/libc/stdlib/on_exit.c

index d5e7d17..5ac279f 100644 (file)
@@ -1,3 +1,26 @@
+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.
+
 2004-08-23  Jeff Johnston  <jjohnstn@redhat.com>
 
        * libc/include/sys/unistd.h (getpass): Change prototype to use
index a216c24..54f5d8e 100644 (file)
@@ -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} \
   }
index 1903e42..ddf6a82 100644 (file)
@@ -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))
index 471d17d..36e6107 100644 (file)
@@ -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        \
index d6c2644..46d96b8 100644 (file)
@@ -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 (file)
index 0000000..0c843ad
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  Common routine to implement atexit-like functionality.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <reent.h>
+#include <sys/lock.h>
+#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 (file)
index 0000000..cea569f
--- /dev/null
@@ -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;
+       }
+    }
+}
index 3a9cdc6..21ffd6e 100644 (file)
@@ -50,10 +50,8 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
 */
 
-#include <stddef.h>
 #include <stdlib.h>
-#include <reent.h>
-#include <sys/lock.h>
+#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);
 }
index 44a9281..e37a146 100644 (file)
@@ -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 (file)
index 0000000..8c39236
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Implementation of __cxa_atexit.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <reent.h>
+#include <sys/lock.h>
+#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 (file)
index 0000000..17d0526
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Implementation if __cxa_finalize.
+ */
+
+
+#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 (__cxa_finalize, (d),
+       void * d)
+{
+  __call_exitprocs (0, d);
+}
index be96488..b5ef05f 100644 (file)
@@ -48,6 +48,7 @@ Supporting OS subroutines required: <<_exit>>.
 #include <stdlib.h>
 #include <unistd.h>    /* for _exit() declaration */
 #include <reent.h>
+#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);
index f338350..3ac7f99 100644 (file)
@@ -56,7 +56,7 @@ Supporting OS subroutines required: None
 
 #include <stddef.h>
 #include <stdlib.h>
-#include <reent.h>
+#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);
 }