github.com/afumu/libc@v0.0.6/musl/src/exit/atexit.c (about)

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