xref: /oneTBB/src/tbb/main.cpp (revision 2a6bd1e1)
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