Subversion Repositories Kolibri OS

Rev

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

  1. // Copyright (C) 2002, 2004, 2006, 2008, 2009, 2010, 2011, 2012
  2. // Free Software Foundation, Inc.
  3. //  
  4. // This file is part of GCC.
  5. //
  6. // GCC is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10.  
  11. // GCC is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15.  
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. // Written by Mark Mitchell, CodeSourcery LLC, <mark@codesourcery.com>
  26. // Thread support written by Jason Merrill, Red Hat Inc. <jason@redhat.com>
  27.  
  28. #include <bits/c++config.h>
  29. #include <cxxabi.h>
  30. #include <exception>
  31. #include <new>
  32. #include <ext/atomicity.h>
  33. #include <ext/concurrence.h>
  34. #if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \
  35.   && (ATOMIC_INT_LOCK_FREE > 1) && defined(_GLIBCXX_HAVE_LINUX_FUTEX)
  36. # include <climits>
  37. # include <syscall.h>
  38. # include <unistd.h>
  39. # define _GLIBCXX_USE_FUTEX
  40. # define _GLIBCXX_FUTEX_WAIT 0
  41. # define _GLIBCXX_FUTEX_WAKE 1
  42. #endif
  43.  
  44. // The IA64/generic ABI uses the first byte of the guard variable.
  45. // The ARM EABI uses the least significant bit.
  46.  
  47. // Thread-safe static local initialization support.
  48. #ifdef __GTHREADS
  49. # ifndef _GLIBCXX_USE_FUTEX
  50. namespace
  51. {
  52.   // A single mutex controlling all static initializations.
  53.   static __gnu_cxx::__recursive_mutex* static_mutex;  
  54.  
  55.   typedef char fake_recursive_mutex[sizeof(__gnu_cxx::__recursive_mutex)]
  56.   __attribute__ ((aligned(__alignof__(__gnu_cxx::__recursive_mutex))));
  57.   fake_recursive_mutex fake_mutex;
  58.  
  59.   static void init()
  60.   { static_mutex =  new (&fake_mutex) __gnu_cxx::__recursive_mutex(); }
  61.  
  62.   __gnu_cxx::__recursive_mutex&
  63.   get_static_mutex()
  64.   {
  65.     static __gthread_once_t once = __GTHREAD_ONCE_INIT;
  66.     __gthread_once(&once, init);
  67.     return *static_mutex;
  68.   }
  69.  
  70.   // Simple wrapper for exception safety.
  71.   struct mutex_wrapper
  72.   {
  73.     bool unlock;
  74.     mutex_wrapper() : unlock(true)
  75.     { get_static_mutex().lock(); }
  76.  
  77.     ~mutex_wrapper()
  78.     {
  79.       if (unlock)
  80.         static_mutex->unlock();
  81.     }
  82.   };
  83. }
  84. # endif
  85.  
  86. # if defined(__GTHREAD_HAS_COND) && !defined(_GLIBCXX_USE_FUTEX)
  87. namespace
  88. {
  89.   // A single condition variable controlling all static initializations.
  90.   static __gnu_cxx::__cond* static_cond;  
  91.  
  92.   // using a fake type to avoid initializing a static class.
  93.   typedef char fake_cond_t[sizeof(__gnu_cxx::__cond)]
  94.   __attribute__ ((aligned(__alignof__(__gnu_cxx::__cond))));
  95.   fake_cond_t fake_cond;
  96.  
  97.   static void init_static_cond()
  98.   { static_cond =  new (&fake_cond) __gnu_cxx::__cond(); }
  99.  
  100.   __gnu_cxx::__cond&
  101.   get_static_cond()
  102.   {
  103.     static __gthread_once_t once = __GTHREAD_ONCE_INIT;
  104.     __gthread_once(&once, init_static_cond);
  105.     return *static_cond;
  106.   }
  107. }
  108. # endif
  109.  
  110. # ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
  111. inline bool
  112. __test_and_acquire (__cxxabiv1::__guard *g)
  113. {
  114.   bool b = _GLIBCXX_GUARD_TEST (g);
  115.   _GLIBCXX_READ_MEM_BARRIER;
  116.   return b;
  117. }
  118. #  define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G)
  119. # endif
  120.  
  121. # ifndef _GLIBCXX_GUARD_SET_AND_RELEASE
  122. inline void
  123. __set_and_release (__cxxabiv1::__guard *g)
  124. {
  125.   _GLIBCXX_WRITE_MEM_BARRIER;
  126.   _GLIBCXX_GUARD_SET (g);
  127. }
  128. #  define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G)
  129. # endif
  130.  
  131. #else /* !__GTHREADS */
  132.  
  133. # undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
  134. # undef _GLIBCXX_GUARD_SET_AND_RELEASE
  135. # define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G)
  136.  
  137. #endif /* __GTHREADS */
  138.  
  139. //
  140. // Here are C++ run-time routines for guarded initialization of static
  141. // variables. There are 4 scenarios under which these routines are called:
  142. //
  143. //   1. Threads not supported (__GTHREADS not defined)
  144. //   2. Threads are supported but not enabled at run-time.
  145. //   3. Threads enabled at run-time but __gthreads_* are not fully POSIX.
  146. //   4. Threads enabled at run-time and __gthreads_* support all POSIX threads
  147. //      primitives we need here.
  148. //
  149. // The old code supported scenarios 1-3 but was broken since it used a global
  150. // mutex for all threads and had the mutex locked during the whole duration of
  151. // initialization of a guarded static variable. The following created a
  152. // dead-lock with the old code.
  153. //
  154. //      Thread 1 acquires the global mutex.
  155. //      Thread 1 starts initializing static variable.
  156. //      Thread 1 creates thread 2 during initialization.
  157. //      Thread 2 attempts to acquire mutex to initialize another variable.
  158. //      Thread 2 blocks since thread 1 is locking the mutex.
  159. //      Thread 1 waits for result from thread 2 and also blocks. A deadlock.
  160. //
  161. // The new code here can handle this situation and thus is more robust. However,
  162. // we need to use the POSIX thread condition variable, which is not supported
  163. // in all platforms, notably older versions of Microsoft Windows. The gthr*.h
  164. // headers define a symbol __GTHREAD_HAS_COND for platforms that support POSIX
  165. // like condition variables. For platforms that do not support condition
  166. // variables, we need to fall back to the old code.
  167.  
  168. // If _GLIBCXX_USE_FUTEX, no global mutex or condition variable is used,
  169. // only atomic operations are used together with futex syscall.
  170. // Valid values of the first integer in guard are:
  171. // 0                              No thread encountered the guarded init
  172. //                                yet or it has been aborted.
  173. // _GLIBCXX_GUARD_BIT             The guarded static var has been successfully
  174. //                                initialized.
  175. // _GLIBCXX_GUARD_PENDING_BIT     The guarded static var is being initialized
  176. //                                and no other thread is waiting for its
  177. //                                initialization.
  178. // (_GLIBCXX_GUARD_PENDING_BIT    The guarded static var is being initialized
  179. //  | _GLIBCXX_GUARD_WAITING_BIT) and some other threads are waiting until
  180. //                                it is initialized.
  181.  
  182. namespace __cxxabiv1
  183. {
  184. #ifdef _GLIBCXX_USE_FUTEX
  185.   namespace
  186.   {
  187.     static inline int __guard_test_bit (const int __byte, const int __val)
  188.     {
  189.       union { int __i; char __c[sizeof (int)]; } __u = { 0 };
  190.       __u.__c[__byte] = __val;
  191.       return __u.__i;
  192.     }
  193.   }
  194. #endif
  195.  
  196.   static inline int
  197.   init_in_progress_flag(__guard* g)
  198.   { return ((char *)g)[1]; }
  199.  
  200.   static inline void
  201.   set_init_in_progress_flag(__guard* g, int v)
  202.   { ((char *)g)[1] = v; }
  203.  
  204.   static inline void
  205.   throw_recursive_init_exception()
  206.   {
  207. #ifdef __EXCEPTIONS
  208.         throw __gnu_cxx::recursive_init_error();
  209. #else
  210.         // Use __builtin_trap so we don't require abort().
  211.         __builtin_trap();
  212. #endif
  213.   }
  214.  
  215.   // acquire() is a helper function used to acquire guard if thread support is
  216.   // not compiled in or is compiled in but not enabled at run-time.
  217.   static int
  218.   acquire(__guard *g)
  219.   {
  220.     // Quit if the object is already initialized.
  221.     if (_GLIBCXX_GUARD_TEST(g))
  222.       return 0;
  223.  
  224.     if (init_in_progress_flag(g))
  225.       throw_recursive_init_exception();
  226.  
  227.     set_init_in_progress_flag(g, 1);
  228.     return 1;
  229.   }
  230.  
  231.   extern "C"
  232.   int __cxa_guard_acquire (__guard *g)
  233.   {
  234. #ifdef __GTHREADS
  235.     // If the target can reorder loads, we need to insert a read memory
  236.     // barrier so that accesses to the guarded variable happen after the
  237.     // guard test.
  238.     if (_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g))
  239.       return 0;
  240.  
  241. # ifdef _GLIBCXX_USE_FUTEX
  242.     // If __atomic_* and futex syscall are supported, don't use any global
  243.     // mutex.
  244.     if (__gthread_active_p ())
  245.       {
  246.         int *gi = (int *) (void *) g;
  247.         const int guard_bit = _GLIBCXX_GUARD_BIT;
  248.         const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT;
  249.         const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
  250.  
  251.         while (1)
  252.           {
  253.             int expected(0);
  254.             if (__atomic_compare_exchange_n(gi, &expected, pending_bit, false,
  255.                                             __ATOMIC_ACQ_REL,
  256.                                             __ATOMIC_ACQUIRE))
  257.               {
  258.                 // This thread should do the initialization.
  259.                 return 1;
  260.               }
  261.              
  262.             if (expected == guard_bit)
  263.               {
  264.                 // Already initialized.
  265.                 return 0;      
  266.               }
  267.  
  268.              if (expected == pending_bit)
  269.                {
  270.                  // Use acquire here.
  271.                  int newv = expected | waiting_bit;
  272.                  if (!__atomic_compare_exchange_n(gi, &expected, newv, false,
  273.                                                   __ATOMIC_ACQ_REL,
  274.                                                   __ATOMIC_ACQUIRE))
  275.                    {
  276.                      if (expected == guard_bit)
  277.                        {
  278.                          // Make a thread that failed to set the
  279.                          // waiting bit exit the function earlier,
  280.                          // if it detects that another thread has
  281.                          // successfully finished initialising.
  282.                          return 0;
  283.                        }
  284.                      if (expected == 0)
  285.                        continue;
  286.                    }
  287.                  
  288.                  expected = newv;
  289.                }
  290.  
  291.             syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAIT, expected, 0);
  292.           }
  293.       }
  294. # else
  295.     if (__gthread_active_p ())
  296.       {
  297.         mutex_wrapper mw;
  298.  
  299.         while (1)       // When this loop is executing, mutex is locked.
  300.           {
  301. #  ifdef __GTHREAD_HAS_COND
  302.             // The static is already initialized.
  303.             if (_GLIBCXX_GUARD_TEST(g))
  304.               return 0; // The mutex will be unlocked via wrapper
  305.  
  306.             if (init_in_progress_flag(g))
  307.               {
  308.                 // The guarded static is currently being initialized by
  309.                 // another thread, so we release mutex and wait for the
  310.                 // condition variable. We will lock the mutex again after
  311.                 // this.
  312.                 get_static_cond().wait_recursive(&get_static_mutex());
  313.               }
  314.             else
  315.               {
  316.                 set_init_in_progress_flag(g, 1);
  317.                 return 1; // The mutex will be unlocked via wrapper.
  318.               }
  319. #  else
  320.             // This provides compatibility with older systems not supporting
  321.             // POSIX like condition variables.
  322.             if (acquire(g))
  323.               {
  324.                 mw.unlock = false;
  325.                 return 1; // The mutex still locked.
  326.               }
  327.             return 0; // The mutex will be unlocked via wrapper.
  328. #  endif
  329.           }
  330.       }
  331. # endif
  332. #endif
  333.  
  334.     return acquire (g);
  335.   }
  336.  
  337.   extern "C"
  338.   void __cxa_guard_abort (__guard *g) throw ()
  339.   {
  340. #ifdef _GLIBCXX_USE_FUTEX
  341.     // If __atomic_* and futex syscall are supported, don't use any global
  342.     // mutex.
  343.     if (__gthread_active_p ())
  344.       {
  345.         int *gi = (int *) (void *) g;
  346.         const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
  347.         int old = __atomic_exchange_n (gi, 0, __ATOMIC_ACQ_REL);
  348.  
  349.         if ((old & waiting_bit) != 0)
  350.           syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX);
  351.         return;
  352.       }
  353. #elif defined(__GTHREAD_HAS_COND)
  354.     if (__gthread_active_p())
  355.       {
  356.         mutex_wrapper mw;
  357.  
  358.         set_init_in_progress_flag(g, 0);
  359.  
  360.         // If we abort, we still need to wake up all other threads waiting for
  361.         // the condition variable.
  362.         get_static_cond().broadcast();
  363.         return;
  364.       }
  365. #endif
  366.  
  367.     set_init_in_progress_flag(g, 0);
  368. #if defined(__GTHREADS) && !defined(__GTHREAD_HAS_COND)
  369.     // This provides compatibility with older systems not supporting POSIX like
  370.     // condition variables.
  371.     if (__gthread_active_p ())
  372.       static_mutex->unlock();
  373. #endif
  374.   }
  375.  
  376.   extern "C"
  377.   void __cxa_guard_release (__guard *g) throw ()
  378.   {
  379. #ifdef _GLIBCXX_USE_FUTEX
  380.     // If __atomic_* and futex syscall are supported, don't use any global
  381.     // mutex.
  382.     if (__gthread_active_p ())
  383.       {
  384.         int *gi = (int *) (void *) g;
  385.         const int guard_bit = _GLIBCXX_GUARD_BIT;
  386.         const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
  387.         int old = __atomic_exchange_n (gi, guard_bit, __ATOMIC_ACQ_REL);
  388.  
  389.         if ((old & waiting_bit) != 0)
  390.           syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX);
  391.         return;
  392.       }
  393. #elif defined(__GTHREAD_HAS_COND)
  394.     if (__gthread_active_p())
  395.       {
  396.         mutex_wrapper mw;
  397.  
  398.         set_init_in_progress_flag(g, 0);
  399.         _GLIBCXX_GUARD_SET_AND_RELEASE(g);
  400.  
  401.         get_static_cond().broadcast();
  402.         return;
  403.       }
  404. #endif
  405.  
  406.     set_init_in_progress_flag(g, 0);
  407.     _GLIBCXX_GUARD_SET_AND_RELEASE (g);
  408.  
  409. #if defined(__GTHREADS) && !defined(__GTHREAD_HAS_COND)
  410.     // This provides compatibility with older systems not supporting POSIX like
  411.     // condition variables.
  412.     if (__gthread_active_p())
  413.       static_mutex->unlock();
  414. #endif
  415.   }
  416. }
  417.