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