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