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