simplify atexit and fflush-on-exit handling
[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 void __funcs_on_exit()
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 }
23
24 int atexit(void (*func)(void))
25 {
26         static int lock;
27         int i;
28
29         /* Hook for atexit extensions */
30         if (libc.atexit) return libc.atexit(func);
31
32         LOCK(&lock);
33
34         /* Defer initialization of head so it can be in BSS */
35         if (!head) head = &builtin;
36
37         /* If the current function list is full, add a new one */
38         if (head->f[COUNT-1]) {
39                 struct fl *new_fl = calloc(sizeof(struct fl), 1);
40                 if (!new_fl) {
41                         UNLOCK(&lock);
42                         return -1;
43                 }
44                 new_fl->next = head;
45                 head = new_fl;
46         }
47
48         /* Append function to the list. */
49         for (i=0; i<COUNT && head->f[i]; i++);
50         head->f[i] = func;
51
52         UNLOCK(&lock);
53         return 0;
54 }