scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit a4fac35c95345ecbf5bd14d19a5e878e14b2b474
parent 62f0e08bbf82d768a2ef87af44b67b5547558d2f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 25 May 2022 22:30:42 +0200

libc: Pull atexit() buffer only when needed

Exit() has to call all the functions registered with atexit()
and it means that the code was pulling always the full buffer
even when atexit() was not called, that in some architectures
could be a large value. This code encapsulate the loop in a
function pointer that is set in every call to atexit(). This
could be done with common symbols but since there are some
portabilities issues around them we used this other solution
that will increase the size of bss in one pointer when atexit()
is called.

Diffstat:
Msrc/libc/libc.h | 1+
Msrc/libc/stdlib/atexit.c | 16+++++++++++++---
Msrc/libc/stdlib/exit.c | 7+++----
3 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/libc/libc.h b/src/libc/libc.h @@ -57,3 +57,4 @@ extern struct tzone tzones[]; extern void (*_exitf[])(void); extern unsigned _exitn; extern void (*_flushall)(void); +extern void (*_atexithdl)(void); diff --git a/src/libc/stdlib/atexit.c b/src/libc/stdlib/atexit.c @@ -5,15 +5,25 @@ #undef atexit +static void (*funs[_ATEXIT_MAX])(void); +static unsigned nfuns; + +static void +callhdls(void) +{ + while (nfuns > 0) + (*funs[--nfuns])(); +} + int atexit(void (*fun)(void)) { - if (_exitn == _ATEXIT_MAX) { + if (nfuns == _ATEXIT_MAX) { errno = ENOMEM; return -1; } - - _exitf[_exitn++] = fun; + funs[nfuns++] = fun; + _atexithdl = callhdls; return 0; } diff --git a/src/libc/stdlib/exit.c b/src/libc/stdlib/exit.c @@ -5,15 +5,14 @@ #undef exit -void (*_exitf[_ATEXIT_MAX])(void); -unsigned _exitn; void (*_flushall)(void); +void (*_atexithdl)(void); void exit(int status) { - while (_exitn > 0) - (*_exitf[--_exitn])(); + if (_atexithdl) + (*_atexithdl)(); if (_flushall) (*_flushall)(); _exit(status);