atexit.c 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #include <stddef.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4. #include "libc.h"
  5. /* Ensure that at least 32 atexit handlers can be registered without malloc */
  6. #define COUNT 32
  7. static struct fl
  8. {
  9. struct fl *next;
  10. void (*f[COUNT])(void);
  11. } builtin, *head;
  12. static int run_atexit_functions(void)
  13. {
  14. int i;
  15. for (; head; head=head->next) {
  16. for (i=COUNT-1; i>=0 && !head->f[i]; i--);
  17. for (; i>=0; i--) head->f[i]();
  18. }
  19. return 0;
  20. }
  21. int (*const __funcs_on_exit)(void) = run_atexit_functions;
  22. int atexit(void (*func)(void))
  23. {
  24. static int lock;
  25. int i;
  26. /* Hook for atexit extensions */
  27. if (libc.atexit) return libc.atexit(func);
  28. LOCK(&lock);
  29. /* Defer initialization of head so it can be in BSS */
  30. if (!head) head = &builtin;
  31. /* If the current function list is full, add a new one */
  32. if (head->f[COUNT-1]) {
  33. struct fl *new_fl = calloc(sizeof(struct fl), 1);
  34. if (!new_fl) {
  35. UNLOCK(&lock);
  36. return -1;
  37. }
  38. new_fl->next = head;
  39. head = new_fl;
  40. }
  41. /* Append function to the list. */
  42. for (i=0; i<COUNT && head->f[i]; i++);
  43. head->f[i] = func;
  44. UNLOCK(&lock);
  45. return 0;
  46. }