• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	void *dso[COUNT];
15 } builtin, *head;
16 
17 static int slot;
18 static volatile int lock[1];
19 
__funcs_on_exit()20 void __funcs_on_exit()
21 {
22 	void (*func)(void *), *arg;
23 	LOCK(lock);
24 	for (; head; head=head->next, slot=COUNT) while(slot-->0) {
25 		if (head->f[slot] != NULL) {
26 			func = head->f[slot];
27 			arg = head->a[slot];
28 			UNLOCK(lock);
29 			func(arg);
30 			LOCK(lock);
31 		}
32 	}
33 	UNLOCK(lock);
34 }
35 
__cxa_finalize(void * dso)36 void __cxa_finalize(void *dso)
37 {
38 	void (*func)(void *), *arg;
39 	struct fl *head_tmp = head;
40 	int slot_tmp = slot;
41 
42 	LOCK(lock);
43 	for (; head_tmp; head_tmp=head_tmp->next, slot_tmp=COUNT) while(slot_tmp-->0) {
44 		if (dso == head_tmp->dso[slot_tmp]) {
45 			func = head_tmp->f[slot_tmp];
46 			arg = head_tmp->a[slot_tmp];
47 			UNLOCK(lock);
48 			func(arg);
49 			LOCK(lock);
50 
51 			head_tmp->dso[slot_tmp] = NULL;
52 			head_tmp->f[slot_tmp] = NULL;
53 		}
54 	}
55 	UNLOCK(lock);
56 }
57 
__cxa_atexit(void (* func)(void *),void * arg,void * dso)58 int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
59 {
60 	LOCK(lock);
61 
62 	/* Defer initialization of head so it can be in BSS */
63 	if (!head) head = &builtin;
64 
65 	/* If the current function list is full, add a new one */
66 	if (slot==COUNT) {
67 		struct fl *new_fl = calloc(sizeof(struct fl), 1);
68 		if (!new_fl) {
69 			UNLOCK(lock);
70 			return -1;
71 		}
72 		new_fl->next = head;
73 		head = new_fl;
74 		slot = 0;
75 	}
76 
77 	/* Append function to the list. */
78 	head->f[slot] = func;
79 	head->a[slot] = arg;
80 	head->dso[slot] = dso;
81 
82 	slot++;
83 
84 	UNLOCK(lock);
85 	return 0;
86 }
87 
call(void * p)88 static void call(void *p)
89 {
90 	((void (*)(void))(uintptr_t)p)();
91 }
92 
atexit(void (* func)(void))93 int atexit(void (*func)(void))
94 {
95 	return __cxa_atexit(call, (void *)(uintptr_t)func, 0);
96 }