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