rework langinfo code for ABI compat and for use by time code
[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) for (i=COUNT-1; i>=0; i--) {
25                 if (!head->f[i]) continue;
26                 func = head->f[i];
27                 arg = head->a[i];
28                 head->f[i] = 0;
29                 UNLOCK(lock);
30                 func(arg);
31                 LOCK(lock);
32         }
33 }
34
35 void __cxa_finalize(void *dso)
36 {
37 }
38
39 int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
40 {
41         int i;
42
43         LOCK(lock);
44
45         /* Defer initialization of head so it can be in BSS */
46         if (!head) head = &builtin;
47
48         /* If the current function list is full, add a new one */
49         if (head->f[COUNT-1]) {
50                 struct fl *new_fl = calloc(sizeof(struct fl), 1);
51                 if (!new_fl) {
52                         UNLOCK(lock);
53                         return -1;
54                 }
55                 new_fl->next = head;
56                 head = new_fl;
57         }
58
59         /* Append function to the list. */
60         for (i=0; i<COUNT && head->f[i]; i++);
61         head->f[i] = func;
62         head->a[i] = arg;
63
64         UNLOCK(lock);
65         return 0;
66 }
67
68 static void call(void *p)
69 {
70         ((void (*)(void))(uintptr_t)p)();
71 }
72
73 int atexit(void (*func)(void))
74 {
75         return __cxa_atexit(call, (void *)(uintptr_t)func, 0);
76 }