restore _Noreturn to __assert_fail
[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 slot;
16 static volatile int lock[2];
17
18 void __funcs_on_exit()
19 {
20         void (*func)(void *), *arg;
21         LOCK(lock);
22         for (; head; head=head->next, slot=COUNT) while(slot-->0) {
23                 func = head->f[slot];
24                 arg = head->a[slot];
25                 UNLOCK(lock);
26                 func(arg);
27                 LOCK(lock);
28         }
29 }
30
31 void __cxa_finalize(void *dso)
32 {
33 }
34
35 int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
36 {
37         LOCK(lock);
38
39         /* Defer initialization of head so it can be in BSS */
40         if (!head) head = &builtin;
41
42         /* If the current function list is full, add a new one */
43         if (slot==COUNT) {
44                 struct fl *new_fl = calloc(sizeof(struct fl), 1);
45                 if (!new_fl) {
46                         UNLOCK(lock);
47                         return -1;
48                 }
49                 new_fl->next = head;
50                 head = new_fl;
51                 slot = 0;
52         }
53
54         /* Append function to the list. */
55         head->f[slot] = func;
56         head->a[slot] = arg;
57         slot++;
58
59         UNLOCK(lock);
60         return 0;
61 }
62
63 static void call(void *p)
64 {
65         ((void (*)(void))(uintptr_t)p)();
66 }
67
68 int atexit(void (*func)(void))
69 {
70         return __cxa_atexit(call, (void *)(uintptr_t)func, 0);
71 }