1 /* 2 Copyright (c) 2005-2022 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #include "oneapi/tbb/detail/_config.h" 18 19 #include "main.h" 20 #include "governor.h" 21 #include "environment.h" 22 #include "market.h" 23 #include "misc.h" 24 #include "itt_notify.h" 25 26 namespace tbb { 27 namespace detail { 28 namespace r1 { 29 30 //------------------------------------------------------------------------ 31 // Begin shared data layout. 32 // The following global data items are mostly read-only after initialization. 33 //------------------------------------------------------------------------ 34 35 //------------------------------------------------------------------------ 36 // governor data 37 basic_tls<thread_data*> governor::theTLS; 38 rml::tbb_factory governor::theRMLServerFactory; 39 bool governor::UsePrivateRML; 40 bool governor::is_rethrow_broken; 41 42 //------------------------------------------------------------------------ 43 // market data 44 market* market::theMarket; 45 market::global_market_mutex_type market::theMarketMutex; 46 47 //------------------------------------------------------------------------ 48 // context propagation data 49 context_state_propagation_mutex_type the_context_state_propagation_mutex; 50 std::atomic<uintptr_t> the_context_state_propagation_epoch{}; 51 52 //------------------------------------------------------------------------ 53 // One time initialization data 54 55 //! Counter of references to global shared resources such as TLS. 56 std::atomic<int> __TBB_InitOnce::count{}; 57 58 std::atomic_flag __TBB_InitOnce::InitializationLock = ATOMIC_FLAG_INIT; 59 60 //! Flag that is set to true after one-time initializations are done. 61 std::atomic<bool> __TBB_InitOnce::InitializationDone{}; 62 63 #if __TBB_USE_ITT_NOTIFY 64 //! Defined in profiling.cpp 65 extern bool ITT_Present; 66 void ITT_DoUnsafeOneTimeInitialization(); 67 #endif 68 69 #if !(_WIN32||_WIN64) || __TBB_SOURCE_DIRECTLY_INCLUDED 70 static __TBB_InitOnce __TBB_InitOnceHiddenInstance; 71 #endif 72 73 #if TBB_USE_ASSERT 74 std::atomic<int> the_observer_proxy_count; 75 76 struct check_observer_proxy_count { 77 ~check_observer_proxy_count() { 78 if (the_observer_proxy_count != 0) { 79 runtime_warning("Leaked %ld observer_proxy objects\n", long(the_observer_proxy_count)); 80 } 81 } 82 }; 83 // The proxy count checker shall be defined after __TBB_InitOnceHiddenInstance to check the count 84 // after auto termination. 85 static check_observer_proxy_count the_check_observer_proxy_count; 86 #endif /* TBB_USE_ASSERT */ 87 88 //------------------------------------------------------------------------ 89 // __TBB_InitOnce 90 //------------------------------------------------------------------------ 91 92 void __TBB_InitOnce::add_ref() { 93 if( ++count==1 ) 94 governor::acquire_resources(); 95 } 96 97 void __TBB_InitOnce::remove_ref() { 98 int k = --count; 99 __TBB_ASSERT(k>=0,"removed __TBB_InitOnce ref that was not added?"); 100 if( k==0 ) { 101 governor::release_resources(); 102 ITT_FINI_ITTLIB(); 103 ITT_RELEASE_RESOURCES(); 104 } 105 } 106 107 //------------------------------------------------------------------------ 108 // One-time Initializations 109 //------------------------------------------------------------------------ 110 111 //! Defined in cache_aligned_allocator.cpp 112 void initialize_cache_aligned_allocator(); 113 114 //! Performs thread-safe lazy one-time general TBB initialization. 115 void DoOneTimeInitialization() { 116 __TBB_InitOnce::lock(); 117 // No fence required for load of InitializationDone, because we are inside a critical section. 118 if( !__TBB_InitOnce::InitializationDone ) { 119 __TBB_InitOnce::add_ref(); 120 if( GetBoolEnvironmentVariable("TBB_VERSION") ) 121 PrintVersion(); 122 bool itt_present = false; 123 #if __TBB_USE_ITT_NOTIFY 124 ITT_DoUnsafeOneTimeInitialization(); 125 itt_present = ITT_Present; 126 #endif /* __TBB_USE_ITT_NOTIFY */ 127 initialize_cache_aligned_allocator(); 128 governor::initialize_rml_factory(); 129 // Force processor groups support detection 130 governor::default_num_threads(); 131 // Force OS regular page size detection 132 governor::default_page_size(); 133 PrintExtraVersionInfo( "TOOLS SUPPORT", itt_present ? "enabled" : "disabled" ); 134 __TBB_InitOnce::InitializationDone = true; 135 } 136 __TBB_InitOnce::unlock(); 137 } 138 139 #if (_WIN32||_WIN64) && !__TBB_SOURCE_DIRECTLY_INCLUDED 140 //! Windows "DllMain" that handles startup and shutdown of dynamic library. 141 extern "C" bool WINAPI DllMain( HANDLE /*hinstDLL*/, DWORD reason, LPVOID lpvReserved ) { 142 switch( reason ) { 143 case DLL_PROCESS_ATTACH: 144 __TBB_InitOnce::add_ref(); 145 break; 146 case DLL_PROCESS_DETACH: 147 // Since THREAD_DETACH is not called for the main thread, call auto-termination 148 // here as well - but not during process shutdown (due to risk of a deadlock). 149 if ( lpvReserved == nullptr ) { // library unload 150 governor::terminate_external_thread(); 151 } 152 __TBB_InitOnce::remove_ref(); 153 // It is assumed that InitializationDone is not set after DLL_PROCESS_DETACH, 154 // and thus no race on InitializationDone is possible. 155 if ( __TBB_InitOnce::initialization_done() ) { 156 // Remove reference that we added in DoOneTimeInitialization. 157 __TBB_InitOnce::remove_ref(); 158 } 159 break; 160 case DLL_THREAD_DETACH: 161 governor::terminate_external_thread(); 162 break; 163 } 164 return true; 165 } 166 #endif /* (_WIN32||_WIN64) && !__TBB_SOURCE_DIRECTLY_INCLUDED */ 167 168 } // namespace r1 169 } // namespace detail 170 } // namespace tbb 171