Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. // Copyright (C) 2012-2013 Free Software Foundation, Inc.
  2. //
  3. // This file is part of GCC.
  4. //
  5. // GCC is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9.  
  10. // GCC is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // Under Section 7 of GPL version 3, you are granted additional
  16. // permissions described in the GCC Runtime Library Exception, version
  17. // 3.1, as published by the Free Software Foundation.
  18.  
  19. // You should have received a copy of the GNU General Public License and
  20. // a copy of the GCC Runtime Library Exception along with this program;
  21. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  22. // <http://www.gnu.org/licenses/>.
  23.  
  24. #include <cxxabi.h>
  25. #include <cstdlib>
  26. #include <new>
  27. #include "bits/gthr.h"
  28.  
  29. #if HAVE___CXA_THREAD_ATEXIT_IMPL
  30.  
  31. extern "C" int __cxa_thread_atexit_impl (void (*func) (void *),
  32.                                          void *arg, void *d);
  33. extern "C" int
  34. __cxxabiv1::__cxa_thread_atexit (void (*dtor)(void *),
  35.                                  void *obj, void *dso_handle)
  36.   _GLIBCXX_NOTHROW
  37. {
  38.   return __cxa_thread_atexit_impl (dtor, obj, dso_handle);
  39. }
  40.  
  41. #else /* HAVE___CXA_THREAD_ATEXIT_IMPL */
  42.  
  43. namespace {
  44.   // One element in a singly-linked stack of cleanups.
  45.   struct elt
  46.   {
  47.     void (*destructor)(void *);
  48.     void *object;
  49.     elt *next;
  50.   };
  51.  
  52.   // Keep a per-thread list of cleanups in gthread_key storage.
  53.   __gthread_key_t key;
  54.   // But also support non-threaded mode.
  55.   elt *single_thread;
  56.  
  57.   // Run the specified stack of cleanups.
  58.   void run (void *p)
  59.   {
  60.     elt *e = static_cast<elt*>(p);
  61.     while (e)
  62.       {
  63.         elt *old_e = e;
  64.         e->destructor (e->object);
  65.         e = e->next;
  66.         delete (old_e);
  67.       }
  68.   }
  69.  
  70.   // Run the stack of cleanups for the current thread.
  71.   void run ()
  72.   {
  73.     void *e;
  74.     if (__gthread_active_p ())
  75.       {
  76.         e = __gthread_getspecific (key);
  77.         __gthread_setspecific (key, NULL);
  78.       }
  79.     else
  80.       {
  81.         e = single_thread;
  82.         single_thread = NULL;
  83.       }
  84.     run (e);
  85.   }
  86.  
  87.   // Initialize the key for the cleanup stack.  We use a static local for
  88.   // key init/delete rather than atexit so that delete is run on dlclose.
  89.   void key_init() {
  90.     struct key_s {
  91.       key_s() { __gthread_key_create (&key, run); }
  92.       ~key_s() { __gthread_key_delete (key); }
  93.     };
  94.     static key_s ks;
  95.     // Also make sure the destructors are run by std::exit.
  96.     // FIXME TLS cleanups should run before static cleanups and atexit
  97.     // cleanups.
  98.     std::atexit (run);
  99.   }
  100. }
  101.  
  102. extern "C" int
  103. __cxxabiv1::__cxa_thread_atexit (void (*dtor)(void *), void *obj, void */*dso_handle*/)
  104.   _GLIBCXX_NOTHROW
  105. {
  106.   // Do this initialization once.
  107.   if (__gthread_active_p ())
  108.     {
  109.       // When threads are active use __gthread_once.
  110.       static __gthread_once_t once = __GTHREAD_ONCE_INIT;
  111.       __gthread_once (&once, key_init);
  112.     }
  113.   else
  114.     {
  115.       // And when threads aren't active use a static local guard.
  116.       static bool queued;
  117.       if (!queued)
  118.         {
  119.           queued = true;
  120.           std::atexit (run);
  121.         }
  122.     }
  123.  
  124.   elt *first;
  125.   if (__gthread_active_p ())
  126.     first = static_cast<elt*>(__gthread_getspecific (key));
  127.   else
  128.     first = single_thread;
  129.  
  130.   elt *new_elt = new (std::nothrow) elt;
  131.   if (!new_elt)
  132.     return -1;
  133.   new_elt->destructor = dtor;
  134.   new_elt->object = obj;
  135.   new_elt->next = first;
  136.  
  137.   if (__gthread_active_p ())
  138.     __gthread_setspecific (key, new_elt);
  139.   else
  140.     single_thread = new_elt;
  141.  
  142.   return 0;
  143. }
  144.  
  145. #endif /* HAVE___CXA_THREAD_ATEXIT_IMPL */
  146.