ref: a4fac35c95345ecbf5bd14d19a5e878e14b2b474
parent: 62f0e08bbf82d768a2ef87af44b67b5547558d2f
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed May 25 18:30:42 EDT 2022
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.
--- a/src/libc/libc.h
+++ b/src/libc/libc.h
@@ -57,3 +57,4 @@
extern void (*_exitf[])(void);
extern unsigned _exitn;
extern void (*_flushall)(void);
+extern void (*_atexithdl)(void);
--- 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;
}
--- 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);