1 /*
2     Copyright (c) 2005-2021 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 {
~check_observer_proxy_counttbb::detail::r1::check_observer_proxy_count77     ~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 
add_ref()92 void __TBB_InitOnce::add_ref() {
93     if( ++count==1 )
94         governor::acquire_resources();
95 }
96 
remove_ref()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     }
104 }
105 
106 //------------------------------------------------------------------------
107 // One-time Initializations
108 //------------------------------------------------------------------------
109 
110 //! Defined in cache_aligned_allocator.cpp
111 void initialize_cache_aligned_allocator();
112 
113 //! Performs thread-safe lazy one-time general TBB initialization.
DoOneTimeInitialization()114 void DoOneTimeInitialization() {
115     __TBB_InitOnce::lock();
116     // No fence required for load of InitializationDone, because we are inside a critical section.
117     if( !__TBB_InitOnce::InitializationDone ) {
118         __TBB_InitOnce::add_ref();
119         if( GetBoolEnvironmentVariable("TBB_VERSION") )
120             PrintVersion();
121         bool itt_present = false;
122 #if __TBB_USE_ITT_NOTIFY
123         ITT_DoUnsafeOneTimeInitialization();
124         itt_present = ITT_Present;
125 #endif /* __TBB_USE_ITT_NOTIFY */
126         initialize_cache_aligned_allocator();
127         governor::initialize_rml_factory();
128         // Force processor groups support detection
129         governor::default_num_threads();
130         // Force OS regular page size detection
131         governor::default_page_size();
132         PrintExtraVersionInfo( "TOOLS SUPPORT", itt_present ? "enabled" : "disabled" );
133         __TBB_InitOnce::InitializationDone = true;
134     }
135     __TBB_InitOnce::unlock();
136 }
137 
138 #if (_WIN32||_WIN64) && !__TBB_SOURCE_DIRECTLY_INCLUDED
139 //! Windows "DllMain" that handles startup and shutdown of dynamic library.
DllMain(HANDLE,DWORD reason,LPVOID lpvReserved)140 extern "C" bool WINAPI DllMain( HANDLE /*hinstDLL*/, DWORD reason, LPVOID lpvReserved ) {
141     switch( reason ) {
142         case DLL_PROCESS_ATTACH:
143             __TBB_InitOnce::add_ref();
144             break;
145         case DLL_PROCESS_DETACH:
146             // Since THREAD_DETACH is not called for the main thread, call auto-termination
147             // here as well - but not during process shutdown (due to risk of a deadlock).
148             if ( lpvReserved==NULL ) { // library unload
149                 governor::terminate_external_thread();
150             }
151             __TBB_InitOnce::remove_ref();
152             // It is assumed that InitializationDone is not set after DLL_PROCESS_DETACH,
153             // and thus no race on InitializationDone is possible.
154             if ( __TBB_InitOnce::initialization_done() ) {
155                 // Remove reference that we added in DoOneTimeInitialization.
156                 __TBB_InitOnce::remove_ref();
157             }
158             break;
159         case DLL_THREAD_DETACH:
160             governor::terminate_external_thread();
161             break;
162     }
163     return true;
164 }
165 #endif /* (_WIN32||_WIN64) && !__TBB_SOURCE_DIRECTLY_INCLUDED */
166 
167 } // namespace r1
168 } // namespace detail
169 } // namespace tbb
170