Subversion Repositories Kolibri OS

Rev

Rev 4874 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  * COmmon routine to call call registered atexit-like routines.
  3.  */
  4.  
  5.  
  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 free.  */
  12. void free(void *) _ATTRIBUTE((__weak__));
  13.  
  14. __LOCK_INIT_RECURSIVE(, __atexit_lock);
  15.  
  16. #ifdef _REENT_GLOBAL_ATEXIT
  17. struct _atexit *_global_atexit = _NULL;
  18. #endif
  19.  
  20. #ifdef _WANT_REGISTER_FINI
  21.  
  22. /* If "__libc_fini" is defined, finalizers (either
  23.    "__libc_fini_array", or "_fini", as appropriate) will be run after
  24.    all user-specified atexit handlers.  For example, you can define
  25.    "__libc_fini" to "_fini" in your linker script if you want the C
  26.    library, rather than startup code, to register finalizers.  If you
  27.    do that, then your startup code need not contain references to
  28.    "atexit" or "exit".  As a result, only applications that reference
  29.    "exit" explicitly will pull in finalization code.
  30.  
  31.    The choice of whether to register finalizers from libc or from
  32.    startup code is deferred to link-time, rather than being a
  33.    configure-time option, so that the same C library binary can be
  34.    used with multiple BSPs, some of which register finalizers from
  35.    startup code, while others defer to the C library.  */
  36. extern char __libc_fini __attribute__((weak));
  37.  
  38. /* Register the application finalization function with atexit.  These
  39.    finalizers should run last.  Therefore, we want to call atexit as
  40.    soon as possible.  */
  41. static void
  42. register_fini(void) __attribute__((constructor (0)));
  43.  
  44. static void
  45. register_fini(void)
  46. {
  47.   if (&__libc_fini) {
  48. #ifdef HAVE_INITFINI_ARRAY
  49.     extern void __libc_fini_array (void);
  50.     atexit (__libc_fini_array);
  51. #else
  52.     extern void _fini (void);
  53.     atexit (_fini);
  54. #endif
  55.   }
  56. }
  57.  
  58. #endif /* _WANT_REGISTER_FINI  */
  59.  
  60. /*
  61.  * Call registered exit handlers.  If D is null then all handlers are called,
  62.  * otherwise only the handlers from that DSO are called.
  63.  */
  64.  
  65. void
  66. _DEFUN (__call_exitprocs, (code, d),
  67.         int code _AND _PTR d)
  68. {
  69.   register struct _atexit *p;
  70.   struct _atexit **lastp;
  71.   register struct _on_exit_args * args;
  72.   register int n;
  73.   int i;
  74.   void (*fn) (void);
  75.  
  76.  
  77. #ifndef __SINGLE_THREAD__
  78.   __lock_acquire_recursive(__atexit_lock);
  79. #endif
  80.  
  81.  restart:
  82.  
  83.   p = _GLOBAL_ATEXIT;
  84.   lastp = &_GLOBAL_ATEXIT;
  85.   while (p)
  86.     {
  87. #ifdef _REENT_SMALL
  88.       args = p->_on_exit_args_ptr;
  89. #else
  90.       args = &p->_on_exit_args;
  91. #endif
  92.       for (n = p->_ind - 1; n >= 0; n--)
  93.         {
  94.           int ind;
  95.  
  96.           i = 1 << n;
  97.  
  98.           /* Skip functions not from this dso.  */
  99.           if (d && (!args || args->_dso_handle[n] != d))
  100.             continue;
  101.  
  102.           /* Remove the function now to protect against the
  103.              function calling exit recursively.  */
  104.           fn = p->_fns[n];
  105.           if (n == p->_ind - 1)
  106.             p->_ind--;
  107.           else
  108.             p->_fns[n] = NULL;
  109.  
  110.           /* Skip functions that have already been called.  */
  111.           if (!fn)
  112.             continue;
  113.  
  114.           ind = p->_ind;
  115.  
  116.           /* Call the function.  */
  117.           if (!args || (args->_fntypes & i) == 0)
  118.             fn ();
  119.           else if ((args->_is_cxa & i) == 0)
  120.             (*((void (*)(int, _PTR)) fn))(code, args->_fnargs[n]);
  121.           else
  122.             (*((void (*)(_PTR)) fn))(args->_fnargs[n]);
  123.  
  124.           /* The function we called call atexit and registered another
  125.              function (or functions).  Call these new functions before
  126.              continuing with the already registered functions.  */
  127.           if (ind != p->_ind || *lastp != p)
  128.             goto restart;
  129.         }
  130.  
  131. #ifndef _ATEXIT_DYNAMIC_ALLOC
  132.       break;
  133. #else
  134.       /* Don't dynamically free the atexit array if free is not
  135.          available.  */
  136.       if (!free)
  137.         break;
  138.  
  139.       /* Move to the next block.  Free empty blocks except the last one,
  140.          which is part of _GLOBAL_REENT.  */
  141.       if (p->_ind == 0 && p->_next)
  142.         {
  143.           /* Remove empty block from the list.  */
  144.           *lastp = p->_next;
  145. #ifdef _REENT_SMALL
  146.           if (args)
  147.             free (args);
  148. #endif
  149.           free (p);
  150.           p = *lastp;
  151.         }
  152.       else
  153.         {
  154.           lastp = &p->_next;
  155.           p = p->_next;
  156.         }
  157. #endif
  158.     }
  159. #ifndef __SINGLE_THREAD__
  160.   __lock_release_recursive(__atexit_lock);
  161. #endif
  162.  
  163. }
  164.