Index: fusl/src/exit/atexit.c |
diff --git a/fusl/src/exit/atexit.c b/fusl/src/exit/atexit.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2b58b8bbf7416ad378f0068553417f9c50ff9c3f |
--- /dev/null |
+++ b/fusl/src/exit/atexit.c |
@@ -0,0 +1,71 @@ |
+#include <stdlib.h> |
+#include <stdint.h> |
+#include "libc.h" |
+ |
+/* Ensure that at least 32 atexit handlers can be registered without malloc */ |
+#define COUNT 32 |
+ |
+static struct fl |
+{ |
+ struct fl *next; |
+ void (*f[COUNT])(void *); |
+ void *a[COUNT]; |
+} builtin, *head; |
+ |
+static int slot; |
+static volatile int lock[2]; |
+ |
+void __funcs_on_exit() |
+{ |
+ void (*func)(void *), *arg; |
+ LOCK(lock); |
+ for (; head; head=head->next, slot=COUNT) while(slot-->0) { |
+ func = head->f[slot]; |
+ arg = head->a[slot]; |
+ UNLOCK(lock); |
+ func(arg); |
+ LOCK(lock); |
+ } |
+} |
+ |
+void __cxa_finalize(void *dso) |
+{ |
+} |
+ |
+int __cxa_atexit(void (*func)(void *), void *arg, void *dso) |
+{ |
+ LOCK(lock); |
+ |
+ /* Defer initialization of head so it can be in BSS */ |
+ if (!head) head = &builtin; |
+ |
+ /* If the current function list is full, add a new one */ |
+ if (slot==COUNT) { |
+ struct fl *new_fl = calloc(sizeof(struct fl), 1); |
+ if (!new_fl) { |
+ UNLOCK(lock); |
+ return -1; |
+ } |
+ new_fl->next = head; |
+ head = new_fl; |
+ slot = 0; |
+ } |
+ |
+ /* Append function to the list. */ |
+ head->f[slot] = func; |
+ head->a[slot] = arg; |
+ slot++; |
+ |
+ UNLOCK(lock); |
+ return 0; |
+} |
+ |
+static void call(void *p) |
+{ |
+ ((void (*)(void))(uintptr_t)p)(); |
+} |
+ |
+int atexit(void (*func)(void)) |
+{ |
+ return __cxa_atexit(call, (void *)(uintptr_t)func, 0); |
+} |