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