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 _GLIBCXX_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 /* _GLIBCXX_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 /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */ 146