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.
This commit is contained in:
Jeff Johnston 2002-05-15 22:58:10 +00:00
parent e355de817c
commit dc824ef736
8 changed files with 168 additions and 20 deletions

View File

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

View File

@ -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));

View File

@ -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 */

View File

@ -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 \

View File

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

View File

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

View File

@ -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);

View File

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