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
}
}