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