Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  Common routine to implement atexit-like functionality.
  3.  */
  4.  
  5. #include <stddef.h>
  6. #include <stdlib.h>
  7. #include <reent.h>
  8. #include <sys/lock.h>
  9. #include "atexit.h"
  10.  
  11. /* Make this a weak reference to avoid pulling in malloc.  */
  12. void * malloc(size_t) _ATTRIBUTE((__weak__));
  13. __LOCK_INIT_RECURSIVE(, __atexit_lock);
  14.  
  15. /*
  16.  * Register a function to be performed at exit or on shared library unload.
  17.  */
  18.  
  19. int
  20. _DEFUN (__register_exitproc,
  21.         (type, fn, arg, d),
  22.         int type _AND
  23.         void (*fn) (void) _AND
  24.         void *arg _AND
  25.         void *d)
  26. {
  27.   struct _on_exit_args * args;
  28.   register struct _atexit *p;
  29.  
  30. #ifndef __SINGLE_THREAD__
  31.   __lock_acquire_recursive(__atexit_lock);
  32. #endif
  33.  
  34.   p = _GLOBAL_REENT->_atexit;
  35.   if (p == NULL)
  36.     _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0;
  37.   if (p->_ind >= _ATEXIT_SIZE)
  38.     {
  39. #ifndef _ATEXIT_DYNAMIC_ALLOC
  40.       return -1;
  41. #else
  42.       /* Don't dynamically allocate the atexit array if malloc is not
  43.          available.  */
  44.       if (!malloc)
  45.         return -1;
  46.  
  47.       p = (struct _atexit *) malloc (sizeof *p);
  48.       if (p == NULL)
  49.         {
  50. #ifndef __SINGLE_THREAD__
  51.           __lock_release_recursive(__atexit_lock);
  52. #endif
  53.           return -1;
  54.         }
  55.       p->_ind = 0;
  56.       p->_next = _GLOBAL_REENT->_atexit;
  57.       _GLOBAL_REENT->_atexit = p;
  58. #ifndef _REENT_SMALL
  59.       p->_on_exit_args._fntypes = 0;
  60.       p->_on_exit_args._is_cxa = 0;
  61. #endif
  62. #endif
  63.     }
  64.  
  65.   if (type != __et_atexit)
  66.     {
  67. #ifdef _REENT_SMALL
  68.       args = p->_on_exit_args_ptr;
  69.       if (args == NULL)
  70.         {
  71.           if (malloc)
  72.             args = malloc (sizeof * p->_on_exit_args_ptr);
  73.  
  74.           if (args == NULL)
  75.             {
  76. #ifndef __SINGLE_THREAD__
  77.               __lock_release(lock);
  78. #endif
  79.               return -1;
  80.             }
  81.           args->_fntypes = 0;
  82.           args->_is_cxa = 0;
  83.           p->_on_exit_args_ptr = args;
  84.         }
  85. #else
  86.       args = &p->_on_exit_args;
  87. #endif
  88.       args->_fnargs[p->_ind] = arg;
  89.       args->_fntypes |= (1 << p->_ind);
  90.       args->_dso_handle[p->_ind] = d;
  91.       if (type == __et_cxa)
  92.         args->_is_cxa |= (1 << p->_ind);
  93.     }
  94.   p->_fns[p->_ind++] = fn;
  95. #ifndef __SINGLE_THREAD__
  96.   __lock_release_recursive(__atexit_lock);
  97. #endif
  98.   return 0;
  99. }
  100.