diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2002-05-15 22:58:10 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2002-05-15 22:58:10 +0000 |
commit | dc824ef7363e46b3602b458f7bf00303601c1102 (patch) | |
tree | e323a2db83cf227cf6ddd465d8657d9339d15369 /newlib | |
parent | e355de817c95c1b5b3fa98c0e5e2863a1ecb7679 (diff) | |
download | newlib-dc824ef7363e46b3602b458f7bf00303601c1102.zip newlib-dc824ef7363e46b3602b458f7bf00303601c1102.tar.gz newlib-dc824ef7363e46b3602b458f7bf00303601c1102.tar.bz2 |
2002-05-15 Jeff Johnston <jjohnstn@redhat.com>
* libc/include/stdlib.h: Add on_exit prototype.
* libc/include/sys/reent.h (struct _atexit): Add argument array
and bits to track type of exit routine to support both on_exit
and atexit.
(_REENT_INIT_PTR): Add missing fields that won't be zeroed out
by default and change the setting of the atexit structure.
(_REENT_INIT)[!_REENT_SMALL]: Remove extraneous end brace.
* libc/stdlib/on_exit.c: New file.
* libc/stdlib/Makefile.am: Add support for on_exit.
* libc/stdlib/Makefile.in: Regenerated.
* libc/stdlib/atexit.c: Change to initialize types field.
* libc/stdlib/exit.c: Change to look at types field for each
exit routine and either call an atexit-style or an on_exit-style
routine accordingly.
Diffstat (limited to 'newlib')
-rw-r--r-- | newlib/ChangeLog | 17 | ||||
-rw-r--r-- | newlib/libc/include/stdlib.h | 1 | ||||
-rw-r--r-- | newlib/libc/include/sys/reent.h | 35 | ||||
-rw-r--r-- | newlib/libc/stdlib/Makefile.am | 2 | ||||
-rw-r--r-- | newlib/libc/stdlib/Makefile.in | 23 | ||||
-rw-r--r-- | newlib/libc/stdlib/atexit.c | 1 | ||||
-rw-r--r-- | newlib/libc/stdlib/exit.c | 13 | ||||
-rw-r--r-- | newlib/libc/stdlib/on_exit.c | 96 |
8 files changed, 168 insertions, 20 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 0da1e32..8e04d64 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,20 @@ +2002-05-15 Jeff Johnston <jjohnstn@redhat.com> + + * libc/include/stdlib.h: Add on_exit prototype. + * libc/include/sys/reent.h (struct _atexit): Add argument array + and bits to track type of exit routine to support both on_exit + and atexit. + (_REENT_INIT_PTR): Add missing fields that won't be zeroed out + by default and change the setting of the atexit structure. + (_REENT_INIT)[!_REENT_SMALL]: Remove extraneous end brace. + * libc/stdlib/on_exit.c: New file. + * libc/stdlib/Makefile.am: Add support for on_exit. + * libc/stdlib/Makefile.in: Regenerated. + * libc/stdlib/atexit.c: Change to initialize types field. + * libc/stdlib/exit.c: Change to look at types field for each + exit routine and either call an atexit-style or an on_exit-style + routine accordingly. + 2002-05-13 Jeff Johnston <jjohnstn@redhat.com> * libc/machine/powerpc/vfprintf.c(__VFPRINTF_R)[__ALTIVEC__]: Don't diff --git a/newlib/libc/include/stdlib.h b/newlib/libc/include/stdlib.h index 3889067..ca7c2a7 100644 --- a/newlib/libc/include/stdlib.h +++ b/newlib/libc/include/stdlib.h @@ -108,6 +108,7 @@ int _EXFUN(system,(const char *__string)); long _EXFUN(a64l,(const char *__input)); char * _EXFUN(l64a,(long __input)); char * _EXFUN(_l64a_r,(struct _reent *,long __input)); +int _EXFUN(on_exit,(_VOID (*__func)(int, _PTR),_PTR __arg)); int _EXFUN(putenv,(const char *__string)); int _EXFUN(_putenv_r,(struct _reent *, const char *__string)); int _EXFUN(setenv,(const char *__string, const char *__value, int __overwrite)); diff --git a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h index 7a53053..5303ed3 100644 --- a/newlib/libc/include/sys/reent.h +++ b/newlib/libc/include/sys/reent.h @@ -72,11 +72,15 @@ struct _atexit { struct _atexit *_next; /* next in list */ int _ind; /* next index in this table */ void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */ + void *_fnargs[_ATEXIT_SIZE]; /* fn args for on_exit */ + __uint32_t _fntypes; /* type of exit routine */ }; #else struct _atexit { int _ind; /* next index in this table */ void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */ + void *_fnargs[_ATEXIT_SIZE]; /* fn args for on_exit */ + __uint32_t _fntypes; /* type of exit routine */ }; #endif @@ -304,14 +308,15 @@ struct _reent }; #define _REENT_INIT(var) \ - { &var.__sf_fake, &var.__sf_fake, &var.__sf_fake, 0, 0, _NULL, 0, 0, \ + { (struct __sFILE *)&var.__sf_fake, (struct __sFILE *)&var.__sf_fake, \ + (struct __sFILE *)&var.__sf_fake, 0, 0, _NULL, 0, 0, \ "C", _NULL, _NULL, 0, 0, _NULL, _NULL, _NULL, _NULL, _NULL, \ - { 0, _NULL }, { _NULL, 0, _NULL }, 0, _NULL } + { 0, _NULL, _NULL, 0 }, { _NULL, 0, _NULL }, _NULL, 0, _NULL } #define _REENT_INIT_PTR(var) \ - { var->_stdin = &var->__sf_fake; \ - var->_stdout = &var->__sf_fake; \ - var->_stderr = &var->__sf_fake; \ + { var->_stdin = (struct __sFILE *)&var->__sf_fake; \ + var->_stdout = (struct __sFILE *)&var->__sf_fake; \ + var->_stderr = (struct __sFILE *)&var->__sf_fake; \ var->_errno = 0; \ var->_inc = 0; \ var->_emergency = _NULL; \ @@ -328,12 +333,21 @@ struct _reent var->_asctime_buf = _NULL; \ var->_sig_func = _NULL; \ var->_atexit._ind = 0; \ - var->_atexit._fns = _NULL}; \ + var->_atexit._fns[0] = _NULL; \ + var->_atexit._fnargs[0] = _NULL; \ + var->_atexit._fntypes = 0; \ var->__sglue._next = _NULL; \ var->__sglue._niobs = 0; \ var->__sglue._iobs = _NULL; \ var->__sf = 0; \ var->_misc = _NULL; \ + var->__sf_fake._p = _NULL; \ + var->__sf_fake._r = 0; \ + var->__sf_fake._w = 0; \ + var->__sf_fake._flags = 0; \ + var->__sf_fake._file = 0; \ + var->__sf_fake._lbfsize = 0; \ + var->__sf_fake._data = _NULL; \ } /* signal info */ @@ -537,6 +551,15 @@ struct _reent var->_new._reent._mbtowc_state = 0; \ var->_new._reent._wctomb_state = 0; \ var->_new._reent._l64a_buf[0] = '\0'; \ + var->_atexit = _NULL; \ + var->_atexit0._ind = 0; \ + var->_atexit0._fns[0] = _NULL; \ + var->_atexit0._fntypes = 0; \ + var->_sig_func = _NULL; \ + var->__sglue._next = _NULL; \ + var->__sglue._niobs = 0; \ + var->__sglue._iobs = _NULL; \ + memset(var->__sf,0,sizeof(var->__sf)); \ } #define _REENT_CHECK_RAND48(ptr) /* nothing */ diff --git a/newlib/libc/stdlib/Makefile.am b/newlib/libc/stdlib/Makefile.am index aad1032..26e4b53 100644 --- a/newlib/libc/stdlib/Makefile.am +++ b/newlib/libc/stdlib/Makefile.am @@ -55,6 +55,7 @@ LIB_SOURCES = \ mstats.c \ mtrim.c \ nrand48.c \ + on_exit.c \ putenv.c \ putenv_r.c \ qsort.c \ @@ -167,6 +168,7 @@ CHEWOUT_FILES= \ mbtowc.def \ mlock.def \ mstats.def \ + on_exit.def \ qsort.def \ rand.def \ rand48.def \ diff --git a/newlib/libc/stdlib/Makefile.in b/newlib/libc/stdlib/Makefile.in index 95c56e6..fdb3733 100644 --- a/newlib/libc/stdlib/Makefile.in +++ b/newlib/libc/stdlib/Makefile.in @@ -153,6 +153,7 @@ LIB_SOURCES = \ mstats.c \ mtrim.c \ nrand48.c \ + on_exit.c \ putenv.c \ putenv_r.c \ qsort.c \ @@ -226,6 +227,7 @@ CHEWOUT_FILES = \ mbtowc.def \ mlock.def \ mstats.def \ + on_exit.def \ qsort.def \ rand.def \ rand48.def \ @@ -268,12 +270,13 @@ LIBS = @LIBS@ @USE_LIBTOOL_FALSE@lcong48.o ldiv.o ldtoa.o lrand48.o malign.o malloc.o \ @USE_LIBTOOL_FALSE@mblen.o mblen_r.o mbstowcs.o mbstowcs_r.o mbtowc.o \ @USE_LIBTOOL_FALSE@mbtowc_r.o mlock.o mprec.o mrand48.o msize.o \ -@USE_LIBTOOL_FALSE@mstats.o mtrim.o nrand48.o putenv.o putenv_r.o \ -@USE_LIBTOOL_FALSE@qsort.o rand.o rand48.o rand_r.o realloc.o seed48.o \ -@USE_LIBTOOL_FALSE@setenv.o setenv_r.o srand48.o strdup.o strdup_r.o \ -@USE_LIBTOOL_FALSE@strtod.o strtol.o strtoll.o strtoll_r.o strtoul.o \ -@USE_LIBTOOL_FALSE@strtoull.o strtoull_r.o system.o valloc.o wcstombs.o \ -@USE_LIBTOOL_FALSE@wcstombs_r.o wctomb.o wctomb_r.o +@USE_LIBTOOL_FALSE@mstats.o mtrim.o nrand48.o on_exit.o putenv.o \ +@USE_LIBTOOL_FALSE@putenv_r.o qsort.o rand.o rand48.o rand_r.o \ +@USE_LIBTOOL_FALSE@realloc.o seed48.o setenv.o setenv_r.o srand48.o \ +@USE_LIBTOOL_FALSE@strdup.o strdup_r.o strtod.o strtol.o strtoll.o \ +@USE_LIBTOOL_FALSE@strtoll_r.o strtoul.o strtoull.o strtoull_r.o \ +@USE_LIBTOOL_FALSE@system.o valloc.o wcstombs.o wcstombs_r.o wctomb.o \ +@USE_LIBTOOL_FALSE@wctomb_r.o LTLIBRARIES = $(noinst_LTLIBRARIES) @USE_LIBTOOL_TRUE@libstdlib_la_DEPENDENCIES = freer.$(oext) \ @@ -291,10 +294,10 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) @USE_LIBTOOL_TRUE@ldtoa.lo lrand48.lo malign.lo malloc.lo mblen.lo \ @USE_LIBTOOL_TRUE@mblen_r.lo mbstowcs.lo mbstowcs_r.lo mbtowc.lo \ @USE_LIBTOOL_TRUE@mbtowc_r.lo mlock.lo mprec.lo mrand48.lo msize.lo \ -@USE_LIBTOOL_TRUE@mstats.lo mtrim.lo nrand48.lo putenv.lo putenv_r.lo \ -@USE_LIBTOOL_TRUE@qsort.lo rand.lo rand48.lo rand_r.lo realloc.lo \ -@USE_LIBTOOL_TRUE@seed48.lo setenv.lo setenv_r.lo srand48.lo strdup.lo \ -@USE_LIBTOOL_TRUE@strdup_r.lo strtod.lo strtol.lo strtoll.lo \ +@USE_LIBTOOL_TRUE@mstats.lo mtrim.lo nrand48.lo on_exit.lo putenv.lo \ +@USE_LIBTOOL_TRUE@putenv_r.lo qsort.lo rand.lo rand48.lo rand_r.lo \ +@USE_LIBTOOL_TRUE@realloc.lo seed48.lo setenv.lo setenv_r.lo srand48.lo \ +@USE_LIBTOOL_TRUE@strdup.lo strdup_r.lo strtod.lo strtol.lo strtoll.lo \ @USE_LIBTOOL_TRUE@strtoll_r.lo strtoul.lo strtoull.lo strtoull_r.lo \ @USE_LIBTOOL_TRUE@system.lo valloc.lo wcstombs.lo wcstombs_r.lo \ @USE_LIBTOOL_TRUE@wctomb.lo wctomb_r.lo diff --git a/newlib/libc/stdlib/atexit.c b/newlib/libc/stdlib/atexit.c index 77aab0c..165b3cf 100644 --- a/newlib/libc/stdlib/atexit.c +++ b/newlib/libc/stdlib/atexit.c @@ -74,6 +74,7 @@ _DEFUN (atexit, if ((p = (struct _atexit *) malloc (sizeof *p)) == NULL) return -1; p->_ind = 0; + p->_fntypes = 0; p->_next = _REENT->_atexit; _REENT->_atexit = p; } diff --git a/newlib/libc/stdlib/exit.c b/newlib/libc/stdlib/exit.c index fb7f73e..54664fe 100644 --- a/newlib/libc/stdlib/exit.c +++ b/newlib/libc/stdlib/exit.c @@ -61,15 +61,20 @@ _DEFUN (exit, (code), { register struct _atexit *p; register int n; + int i = 1; #ifdef _REENT_SMALL - for (p = &_REENT->_atexit, n = p->_ind; --n >= 0;) - (*p->_fns[n]) (); + for (p = &_REENT->_atexit, n = p->_ind-1, i = (n>=0) ? (1<<n) : 0; + n >= 0; --n, i >>= 1) #else for (p = _REENT->_atexit; p; p = p->_next) - for (n = p->_ind; --n >= 0;) - (*p->_fns[n]) (); + for (n = p->_ind - 1, i = (n >= 0) ? (1 << n) : 0; n >= 0; --n, i >>= 1) #endif + if (p->_fntypes & i) + (*((void (*)(int, void *))p->_fns[n]))(code, p->_fnargs[n]); + else + (*p->_fns[n]) (); + if (_REENT->__cleanup) (*_REENT->__cleanup) (_REENT); _exit (code); diff --git a/newlib/libc/stdlib/on_exit.c b/newlib/libc/stdlib/on_exit.c new file mode 100644 index 0000000..1b6cd2a --- /dev/null +++ b/newlib/libc/stdlib/on_exit.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1990 Regents of the University of California. + * All rights reserved. + * + * %sccs.include.redist.c% + * + * This function is a modified version of atexit.c + */ + +/* +FUNCTION +<<on_exit>>---request execution of function with argument at program exit + +INDEX + on_exit + +ANSI_SYNOPSIS + #include <stdlib.h> + int on_exit (void (*<[function]>)(int, void *), void *<[arg]>); + +TRAD_SYNOPSIS + #include <stdlib.h> + int on_exit ((<[function]>, <[arg]>) + void (*<[function]>)(int, void *); + void *<[arg]>; + +DESCRIPTION +You can use <<on_exit>> to enroll functions in a list of functions that +will be called when your program terminates normally. The argument is +a pointer to a user-defined function which takes two arguments. The +first is the status code passed to exit and the second argument is of type +pointer to void. The function must not return a result. The value +of <[arg]> is registered and passed as the argument to <[function]>. + +The functions are kept in a LIFO stack; that is, the last function +enrolled by <<atexit>> or <<on_exit>> will be the first to execute when +your program exits. You can intermix functions using <<atexit>> and +<<on_exit>>. + +There is no built-in limit to the number of functions you can enroll +in this list; however, after every group of 32 functions is enrolled, +<<atexit>>/<<on_exit>> will call <<malloc>> to get space for the next part +of the list. The initial list of 32 functions is statically allocated, so +you can always count on at least that many slots available. + +RETURNS +<<on_exit>> returns <<0>> if it succeeds in enrolling your function, +<<-1>> if it fails (possible only if no space was available for +<<malloc>> to extend the list of functions). + +PORTABILITY +<<on_exit>> is a non-standard glibc extension + +Supporting OS subroutines required: None +*/ + +#include <stddef.h> +#include <stdlib.h> +#include <reent.h> + +/* + * Register a function to be performed at exit. + */ + +int +_DEFUN (on_exit, + (fn, arg), + _VOID _EXFUN ((*fn), (int, _PTR)) _AND + _PTR arg) +{ + register struct _atexit *p; + void (*x)(void) = (void (*)(void))fn; + +/* _REENT_SMALL on_exit() doesn't allow more than the required 32 entries. */ +#ifndef _REENT_SMALL + if ((p = _REENT->_atexit) == NULL) + _REENT->_atexit = p = &_REENT->_atexit0; + if (p->_ind >= _ATEXIT_SIZE) + { + if ((p = (struct _atexit *) malloc (sizeof *p)) == NULL) + return -1; + p->_ind = 0; + p->_fntypes = 0; + p->_next = _REENT->_atexit; + _REENT->_atexit = p; + } +#else + p = &_REENT->_atexit; + if (p->_ind >= _ATEXIT_SIZE) + return -1; +#endif + p->_fntypes |= (1 << p->_ind); + p->_fnargs[p->_ind] = arg; + p->_fns[p->_ind++] = x; + return 0; +} |