1 #include <stdlib.h>
2 #include <stdint.h>
3 #include "libc.h"
4 #include "lock.h"
5
6 /* Ensure that at least 32 atexit handlers can be registered without malloc */
7 #define COUNT 32
8
9 static struct fl
10 {
11 struct fl *next;
12 void (*f[COUNT])(void *);
13 void *a[COUNT];
14 } builtin, *head;
15
16 static int slot;
17 static volatile int lock[1];
18
__funcs_on_exit()19 void __funcs_on_exit()
20 {
21 void (*func)(void *), *arg;
22 LOCK(lock);
23 for (; head; head=head->next, slot=COUNT) while(slot-->0) {
24 func = head->f[slot];
25 arg = head->a[slot];
26 UNLOCK(lock);
27 func(arg);
28 LOCK(lock);
29 }
30 }
31
__cxa_finalize(void * dso)32 void __cxa_finalize(void *dso)
33 {
34 }
35
__cxa_atexit(void (* func)(void *),void * arg,void * dso)36 int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
37 {
38 LOCK(lock);
39
40 /* Defer initialization of head so it can be in BSS */
41 if (!head) head = &builtin;
42
43 /* If the current function list is full, add a new one */
44 if (slot==COUNT) {
45 struct fl *new_fl = calloc(sizeof(struct fl), 1);
46 if (!new_fl) {
47 UNLOCK(lock);
48 return -1;
49 }
50 new_fl->next = head;
51 head = new_fl;
52 slot = 0;
53 }
54
55 /* Append function to the list. */
56 head->f[slot] = func;
57 head->a[slot] = arg;
58 slot++;
59
60 UNLOCK(lock);
61 return 0;
62 }
63
call(void * p)64 static void call(void *p)
65 {
66 ((void (*)(void))(uintptr_t)p)();
67 }
68
atexit(void (* func)(void))69 int atexit(void (*func)(void))
70 {
71 return __cxa_atexit(call, (void *)(uintptr_t)func, 0);
72 }
73