atexit.c raw

   1  #include <stdlib.h>
   2  #include <stdint.h>
   3  #include "libc.h"
   4  #include "lock.h"
   5  #include "fork_impl.h"
   6  
   7  #define malloc __libc_malloc
   8  #define calloc __libc_calloc
   9  #define realloc undef
  10  #define free undef
  11  
  12  /* Ensure that at least 32 atexit handlers can be registered without malloc */
  13  #define COUNT 32
  14  
  15  static struct fl
  16  {
  17  	struct fl *next;
  18  	void (*f[COUNT])(void *);
  19  	void *a[COUNT];
  20  } builtin, *head;
  21  
  22  static int slot;
  23  static volatile int lock[1];
  24  volatile int *const __atexit_lockptr = lock;
  25  
  26  void __funcs_on_exit()
  27  {
  28  	void (*func)(void *), *arg;
  29  	LOCK(lock);
  30  	for (; head; head=head->next, slot=COUNT) while(slot-->0) {
  31  		func = head->f[slot];
  32  		arg = head->a[slot];
  33  		UNLOCK(lock);
  34  		func(arg);
  35  		LOCK(lock);
  36  	}
  37  }
  38  
  39  void __cxa_finalize(void *dso)
  40  {
  41  }
  42  
  43  int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
  44  {
  45  	LOCK(lock);
  46  
  47  	/* Defer initialization of head so it can be in BSS */
  48  	if (!head) head = &builtin;
  49  
  50  	/* If the current function list is full, add a new one */
  51  	if (slot==COUNT) {
  52  		struct fl *new_fl = calloc(sizeof(struct fl), 1);
  53  		if (!new_fl) {
  54  			UNLOCK(lock);
  55  			return -1;
  56  		}
  57  		new_fl->next = head;
  58  		head = new_fl;
  59  		slot = 0;
  60  	}
  61  
  62  	/* Append function to the list. */
  63  	head->f[slot] = func;
  64  	head->a[slot] = arg;
  65  	slot++;
  66  
  67  	UNLOCK(lock);
  68  	return 0;
  69  }
  70  
  71  static void call(void *p)
  72  {
  73  	((void (*)(void))(uintptr_t)p)();
  74  }
  75  
  76  int atexit(void (*func)(void))
  77  {
  78  	return __cxa_atexit(call, (void *)(uintptr_t)func, 0);
  79  }
  80