1 // mutex -*- C++ -*- 2 3 // Copyright (C) 2008-2021 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library 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 #include <mutex> 26 27 #ifdef _GLIBCXX_HAS_GTHREADS 28 29 namespace std _GLIBCXX_VISIBILITY(default) 30 { 31 _GLIBCXX_BEGIN_NAMESPACE_VERSION 32 33 #ifdef _GLIBCXX_HAVE_TLS 34 __thread void* __once_callable; 35 __thread void (*__once_call)(); 36 __once_proxy()37 extern "C" void __once_proxy() 38 { 39 // The caller stored a function pointer in __once_call. If it requires 40 // any state, it gets it from __once_callable. 41 __once_call(); 42 } 43 44 #else // ! TLS 45 46 // Explicit instantiation due to -fno-implicit-instantiation. 47 template class function<void()>; 48 49 function<void()> __once_functor; 50 51 mutex& 52 __get_once_mutex() 53 { 54 static mutex once_mutex; 55 return once_mutex; 56 } 57 58 namespace 59 { 60 // Store ptr in a global variable and return the previous value. 61 inline unique_lock<mutex>* 62 set_lock_ptr(unique_lock<mutex>* ptr) 63 { 64 static unique_lock<mutex>* __once_functor_lock_ptr = nullptr; 65 return std::__exchange(__once_functor_lock_ptr, ptr); 66 } 67 } 68 69 // code linked against ABI 3.4.12 and later uses this 70 void 71 __set_once_functor_lock_ptr(unique_lock<mutex>* __ptr) 72 { 73 (void) set_lock_ptr(__ptr); 74 } 75 76 // unsafe - retained for compatibility with ABI 3.4.11 77 unique_lock<mutex>& 78 __get_once_functor_lock() 79 { 80 static unique_lock<mutex> once_functor_lock(__get_once_mutex(), defer_lock); 81 return once_functor_lock; 82 } 83 84 // This is called via pthread_once while __get_once_mutex() is locked. 85 extern "C" void 86 __once_proxy() 87 { 88 // Get the callable out of the global functor. 89 function<void()> callable = std::move(__once_functor); 90 91 // Then unlock the global mutex 92 if (unique_lock<mutex>* lock = set_lock_ptr(nullptr)) 93 { 94 // Caller is using the new ABI and provided a pointer to its lock. 95 lock->unlock(); 96 } 97 else 98 __get_once_functor_lock().unlock(); // global lock 99 100 // Finally, invoke the callable. 101 callable(); 102 } 103 #endif // ! TLS 104 105 _GLIBCXX_END_NAMESPACE_VERSION 106 } // namespace std 107 108 #endif // _GLIBCXX_HAS_GTHREADS 109