49c060e6eb9e63c7c47f5dcf2413071140df1c39
[musl] / src / exit / atexit.c
1 #include <stddef.h>
2 #include <stdlib.h>
3 #include <limits.h>
4 #include "libc.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 } builtin, *head;
14
15 static int run_atexit_functions(void)
16 {
17         int i;
18         for (; head; head=head->next) {
19                 for (i=COUNT-1; i>=0 && !head->f[i]; i--);
20                 for (; i>=0; i--) head->f[i]();
21         }
22         return 0;
23 }
24
25 int (*const __funcs_on_exit)(void) = run_atexit_functions;
26
27 int atexit(void (*func)(void))
28 {
29         static int lock;
30         int i;
31
32         /* Hook for atexit extensions */
33         if (libc.atexit) return libc.atexit(func);
34
35         LOCK(&lock);
36
37         /* Defer initialization of head so it can be in BSS */
38         if (!head) head = &builtin;
39
40         /* If the current function list is full, add a new one */
41         if (head->f[COUNT-1]) {
42                 struct fl *new_fl = calloc(sizeof(struct fl), 1);
43                 if (!new_fl) {
44                         UNLOCK(&lock);
45                         return -1;
46                 }
47                 new_fl->next = head;
48                 head = new_fl;
49         }
50
51         /* Append function to the list. */
52         for (i=0; i<COUNT && head->f[i]; i++);
53         head->f[i] = func;
54
55         UNLOCK(&lock);
56         return 0;
57 }