shithub: scc

Download patch

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