This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Implement __cxa_atexit


The attached patch implements __cxa_atexit and __cxa_finalize.

As the name suggests these are used by C++ code to register static object 
destructors. They are documented in section 3.3.5 of the C++ ABI 
(http://www.codesourcery.com/cxx-abi/abi.html)

Despite this they are generally provided by the C library, not the C++ runtime 
library.

I basically took the exitsing atexit/on_exit implementation, broke it out into 
separate files, and added the extra _dso_handle field. I also modified the 
_REENT_SMALL case to allow more than 32 handlers to be registered.

Tested with cross to arm-none-elf.
Ok?

Paul

2004-09-03  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.
Index: libc/include/sys/reent.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/sys/reent.h,v
retrieving revision 1.29
diff -u -p -r1.29 reent.h
--- libc/include/sys/reent.h	18 Jun 2004 00:33:53 -0000	1.29
+++ libc/include/sys/reent.h	3 Sep 2004 17:35:58 -0000
@@ -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 aguments.  */
 	__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 = _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: libc/stdlib/Makefile.am
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/Makefile.am,v
retrieving revision 1.19
diff -u -p -r1.19 Makefile.am
--- libc/stdlib/Makefile.am	9 Feb 2004 21:47:47 -0000	1.19
+++ libc/stdlib/Makefile.am	3 Sep 2004 17:35:58 -0000
@@ -6,6 +6,8 @@ INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLA
 
 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: libc/stdlib/Makefile.in
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/Makefile.in,v
retrieving revision 1.24
diff -u -p -r1.24 Makefile.in
--- libc/stdlib/Makefile.in	9 Feb 2004 21:47:47 -0000	1.24
+++ libc/stdlib/Makefile.in	3 Sep 2004 17:35:58 -0000
@@ -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 \
Index: libc/stdlib/__atexit.c
===================================================================
RCS file: libc/stdlib/__atexit.c
diff -N libc/stdlib/__atexit.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libc/stdlib/__atexit.c	3 Sep 2004 17:35:58 -0000
@@ -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;
+}
Index: libc/stdlib/__call_atexit.c
===================================================================
RCS file: libc/stdlib/__call_atexit.c
diff -N libc/stdlib/__call_atexit.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libc/stdlib/__call_atexit.c	3 Sep 2004 17:35:58 -0000
@@ -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;
+#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 protected 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: libc/stdlib/atexit.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/atexit.c,v
retrieving revision 1.6
diff -u -p -r1.6 atexit.c
--- libc/stdlib/atexit.c	28 Jan 2004 01:00:37 -0000	1.6
+++ libc/stdlib/atexit.c	3 Sep 2004 17:35:58 -0000
@@ -50,10 +50,8 @@ Supporting OS subroutines required: <<cl
 <<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: libc/stdlib/atexit.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/atexit.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 atexit.h
--- libc/stdlib/atexit.h	17 Feb 2000 19:39:47 -0000	1.1.1.1
+++ libc/stdlib/atexit.h	3 Sep 2004 17:35:58 -0000
@@ -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));
+
Index: libc/stdlib/cxa_atexit.c
===================================================================
RCS file: libc/stdlib/cxa_atexit.c
diff -N libc/stdlib/cxa_atexit.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libc/stdlib/cxa_atexit.c	3 Sep 2004 17:35:58 -0000
@@ -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);
+}
Index: libc/stdlib/cxa_finalize.c
===================================================================
RCS file: libc/stdlib/cxa_finalize.c
diff -N libc/stdlib/cxa_finalize.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libc/stdlib/cxa_finalize.c	3 Sep 2004 17:35:58 -0000
@@ -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: libc/stdlib/exit.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/exit.c,v
retrieving revision 1.7
diff -u -p -r1.7 exit.c
--- libc/stdlib/exit.c	22 Oct 2003 08:45:01 -0000	1.7
+++ libc/stdlib/exit.c	3 Sep 2004 17:35:58 -0000
@@ -48,6 +48,7 @@ Supporting OS subroutines required: <<_e
 #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: libc/stdlib/on_exit.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/on_exit.c,v
retrieving revision 1.3
diff -u -p -r1.3 on_exit.c
--- libc/stdlib/on_exit.c	2 Sep 2003 22:42:05 -0000	1.3
+++ libc/stdlib/on_exit.c	3 Sep 2004 17:35:58 -0000
@@ -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);
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]