This is the mail archive of the newlib@sourceware.org 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]

RFA: reducing size of _atexit structure for _REENT_SMALL


Hi Jeff,

  Please could I have permission to check in the attached patch ?

  It changes the _atexit structure defined in libc/include/sys/reent.h
  so that the _fns[] array is replaced by a pointer, if the global
  define _REENT_SMALL is enabled.  If any of the atexit functions are
  used then this pointer is initialised to point to an ATEXIT_SIZE
  length array, but otherwise it is left as NULL, thus saving 31 words
  in the _reent structure.

  I checked the patch by building two toolchains - an xstormy16-elf
  toolchain which used _REENT_SMALL and an xscale-elf toolchain which
  does not.  With both toolchains successfully built and installed I
  compiled and ran a hello world program (with no exit functions) and
  this test program:

    #include <stdlib.h>
    #include <stdio.h>

    static void exit_func_1 (void) 
    { printf ("exit_func_1 called via atexit\n"); }

    static void exit_func_2 (char * arg) 
    { printf ("exit_func_2 called via __cxa_atexit with arg '%s'\n", arg); }

    static void exit_func_3 (int code, char * arg)
    { printf ("exit_func_3 called via on_exit with code %d and arg '%s'\n", code, arg); }

    int main (void)
    { printf ("main starting\n");
      atexit (exit_func_1);
      __cxa_atexit ((void (*)(void)) exit_func_2, "hi", NULL);
      on_exit ((void (*)(int,void *)) exit_func_3, "bye");
      return printf ("main ending\n");
    }

  For both toolchains the following output was produced:
  
    main starting
    main ending
    exit_func_3 called via on_exit with code 12 and arg 'bye'
    exit_func_2 called via __cxa_atexit with arg 'hi'
    exit_func_1 called via atexit

Cheers
  Nick

newlib/ChangeLog
2006-03-10  Nick Clifton  <nickc@redhat.com>

	For _REENT_SMALL...
	* libc/include/sys/reent.h (struct _atexit): Replace _fns array
	with a pointer '_fns_ptr'.
	(REENT_INIT, _REENT_INIT_PTR): Adjust initializations
	appropriately.
	* libc/reent/reent.c (_reclaim_reent): Free the _fns_ptr if it has
	been allocated.
	(_wrapup_reent): Indirect via _fns_ptr.
	* libc/stdlib/__atexit.c (__register_exitproc): If _fns_ptr is
	NULL allocate space for an array of function pointers.
	* libc/stdlib/__call_atexit.c (__call_exitprocs): Indirect via
	_fns_ptr.

Index: libc/include/sys/reent.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/sys/reent.h,v
retrieving revision 1.34
diff -c -3 -p -r1.34 reent.h
*** libc/include/sys/reent.h	8 Feb 2005 01:33:16 -0000	1.34
--- libc/include/sys/reent.h	10 Mar 2006 10:21:52 -0000
*************** struct _on_exit_args {
*** 74,84 ****
  	__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;
  };
  #else
--- 74,86 ----
  	__ULong _is_cxa;
  };
  
+ typedef void (* _at_exit_void_fn_ptr)(void);
+ 
  #ifdef _REENT_SMALL
  struct _atexit {
  	struct	_atexit *_next;			/* next in list */
  	int	_ind;				/* next index in this table */
!         _at_exit_void_fn_ptr * _fns_ptr;	/* pointer to a table of exit function pointers */
          struct _on_exit_args * _on_exit_args_ptr;
  };
  #else
*************** struct _atexit {
*** 86,92 ****
  	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;
  };
  #endif
--- 88,94 ----
  	struct	_atexit *_next;			/* next in list */
  	int	_ind;				/* next index in this table */
  	/* Some entries may already have been called, and will be NULL.  */
!         _at_exit_void_fn_ptr _fns[_ATEXIT_SIZE];/* table of exit function pointers */
          struct _on_exit_args _on_exit_args;
  };
  #endif
*************** struct _reent
*** 407,413 ****
      _NULL, \
      _NULL, \
      _NULL, \
!     {_NULL, 0, {_NULL}, _NULL}, \
      {_NULL, 0, _NULL}, \
      _NULL, \
      {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL}, \
--- 409,415 ----
      _NULL, \
      _NULL, \
      _NULL, \
!     {_NULL, 0, _NULL, _NULL}, \
      {_NULL, 0, _NULL}, \
      _NULL, \
      {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL}, \
*************** struct _reent
*** 437,443 ****
      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; \
--- 439,445 ----
      var->_atexit = _NULL; \
      var->_atexit0._next = _NULL; \
      var->_atexit0._ind = 0; \
!     var->_atexit0._fns_ptr = _NULL; \
      var->_atexit0._on_exit_args_ptr = _NULL; \
      var->__sglue._next = _NULL; \
      var->__sglue._niobs = 0; \
Index: libc/reent/reent.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/reent/reent.c,v
retrieving revision 1.8
diff -c -3 -p -r1.8 reent.c
*** libc/reent/reent.c	9 Sep 2004 19:46:54 -0000	1.8
--- libc/reent/reent.c	10 Mar 2006 10:21:52 -0000
*************** _DEFUN (_reclaim_reent, (ptr),
*** 83,88 ****
--- 83,90 ----
  	_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->_fns_ptr)
+ 	_free_r (ptr, ptr->_atexit->_fns_ptr);
  #else
        /* atexit stuff */
        if ((ptr->_atexit) && (ptr->_atexit != &ptr->_atexit0))
*************** _DEFUN (_wrapup_reent, (ptr), struct _re
*** 131,144 ****
    if (ptr == 0)
        ptr = _REENT;
  
  #ifdef _REENT_SMALL
!   for (p = &ptr->_atexit, n = p->_ind; --n >= 0;)
!     (*p->_fns[n]) ();
  #else
!   for (p = ptr->_atexit; p; p = p->_next)
      for (n = p->_ind; --n >= 0;)
        (*p->_fns[n]) ();
  #endif
    if (ptr->__cleanup)
      (*ptr->__cleanup) (ptr);
  }
--- 133,154 ----
    if (ptr == 0)
        ptr = _REENT;
  
+   p = ptr->_atexit;
  #ifdef _REENT_SMALL
!   if (p != NULL)
!     {
!       _at_exit_void_fn_ptr * fns = p->_fns_ptr;
! 
!       if (fns != NULL)
! 	for (n = p->_ind; --n >= 0;)
! 	  fns[n] ();
!     }
  #else
!   for (; p; p = p->_next)
      for (n = p->_ind; --n >= 0;)
        (*p->_fns[n]) ();
  #endif
+ 
    if (ptr->__cleanup)
      (*ptr->__cleanup) (ptr);
  }
Index: libc/stdlib/__atexit.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/__atexit.c,v
retrieving revision 1.3
diff -c -3 -p -r1.3 __atexit.c
*** libc/stdlib/__atexit.c	15 Sep 2004 20:50:07 -0000	1.3
--- libc/stdlib/__atexit.c	10 Mar 2006 10:21:52 -0000
***************
*** 9,14 ****
--- 9,27 ----
  #include "atexit.h"
  
  
+ #ifndef __SINGLE_THREAD__
+ #define FAIL			\
+   do				\
+     {				\
+       __lock_release (lock);	\
+       return -1;		\
+     }				\
+   while (0)
+ #else
+ #define FAIL \
+   return -1
+ #endif     
+ 
  /*
   * Register a function to be performed at exit or on shared library unload.
   */
*************** _DEFUN (__register_exitproc,
*** 35,52 ****
      _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
--- 48,63 ----
      _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0;
    if (p->_ind >= _ATEXIT_SIZE)
      {
+ #ifdef _REENT_SMALL
+       FAIL;
+ #else
        p = (struct _atexit *) malloc (sizeof *p);
        if (p == NULL)
! 	FAIL;
! 
        p->_ind = 0;
        p->_next = _GLOBAL_REENT->_atexit;
        _GLOBAL_REENT->_atexit = p;
        p->_on_exit_args._fntypes = 0;
        p->_on_exit_args._is_cxa = 0;
  #endif
*************** _DEFUN (__register_exitproc,
*** 60,71 ****
  	{
  	  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;
--- 71,78 ----
  	{
  	  args = malloc (sizeof * p->_on_exit_args_ptr);
  	  if (args == NULL)
! 	    FAIL;
! 
  	  args->_fntypes = 0;
  	  args->_is_cxa = 0;
  	  p->_on_exit_args_ptr = args;
*************** _DEFUN (__register_exitproc,
*** 79,85 ****
        if (type == __et_cxa)
  	args->_is_cxa |= (1 << p->_ind);
      }
!   p->_fns[p->_ind++] = fn;
  #ifndef __SINGLE_THREAD__
    __lock_release(lock);
  #endif
--- 86,110 ----
        if (type == __et_cxa)
  	args->_is_cxa |= (1 << p->_ind);
      }
! 
! #ifdef _REENT_SMALL
!  {
!    _at_exit_void_fn_ptr * fns = p->_fns_ptr;
! 
!    if (fns == NULL)
!     {
!       fns = p->_fns_ptr = malloc ((sizeof (* fns)) * _ATEXIT_SIZE);
!       if (fns == NULL)
! 	FAIL;
!     }
!    fns[p->_ind] = fn;
!  }
! #else
!   p->_fns[p->_ind] = fn;
! #endif
! 
!   p->_ind ++;
! 
  #ifndef __SINGLE_THREAD__
    __lock_release(lock);
  #endif
Index: libc/stdlib/__call_atexit.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/__call_atexit.c,v
retrieving revision 1.3
diff -c -3 -p -r1.3 __call_atexit.c
*** libc/stdlib/__call_atexit.c	15 Sep 2004 20:50:07 -0000	1.3
--- libc/stdlib/__call_atexit.c	10 Mar 2006 10:21:52 -0000
*************** _DEFUN (__call_exitprocs, (code, d),
*** 28,33 ****
--- 28,38 ----
    while (p)
      {
  #ifdef _REENT_SMALL
+       _at_exit_void_fn_ptr * fns = p->_fns_ptr;
+ 
+       if (fns == NULL)
+ 	break;
+ 	    
        args = p->_on_exit_args_ptr;
  #else
        args = &p->_on_exit_args;
*************** _DEFUN (__call_exitprocs, (code, d),
*** 42,52 ****
  
  	  /* 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)
--- 47,61 ----
  
  	  /* Remove the function now to protect against the
  	     function calling exit recursively.  */
+ #ifdef _REENT_SMALL
+ 	  fn = fns[n];
+ 	  fns[n] = NULL;
+ #else
  	  fn = p->_fns[n];
+ 	  p->_fns[n] = NULL;
+ #endif
  	  if (n == p->_ind - 1)
  	    p->_ind--;
  
  	  /* Skip functions that have already been called.  */
  	  if (!fn)
*************** _DEFUN (__call_exitprocs, (code, d),
*** 63,76 ****
  
        /* 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;
  	}
--- 72,86 ----
  
        /* Move to the next block.  Free empty blocks except the last one,
  	 which is part of _GLOBAL_REENT.  */
+ #ifdef _REENT_SMALL
+       p = NULL;
+ #else
        if (p->_ind == 0 && p->_next)
  	{
  	  /* Remove empty block from the list.  */
  	  *lastp = p->_next;
  	  if (args)
  	    free (args);
  	  free (p);
  	  p = *lastp;
  	}
*************** _DEFUN (__call_exitprocs, (code, d),
*** 79,83 ****
--- 89,94 ----
  	  lastp = &p->_next;
  	  p = p->_next;
  	}
+ #endif
      }
  }

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