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 8static struct fl 9{ 10 struct fl *next; 11 void (*f[COUNT])(void *); 12 void *a[COUNT]; 13} builtin, *head; 14 15static int slot; 16static volatile int lock[2]; 17 18void __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 31void __cxa_finalize(void *dso) 32{ 33} 34 35int __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 63static void call(void *p) 64{ 65 ((void (*)(void))(uintptr_t)p)(); 66} 67 68int atexit(void (*func)(void)) 69{ 70 return __cxa_atexit(call, (void *)(uintptr_t)func, 0); 71} 72