xref: /oneTBB/src/tbb/main.cpp (revision 71e1bb8e)
151c0b2f7Stbbdev /*
2c4568449SPavel Kumbrasev     Copyright (c) 2005-2023 Intel Corporation
351c0b2f7Stbbdev 
451c0b2f7Stbbdev     Licensed under the Apache License, Version 2.0 (the "License");
551c0b2f7Stbbdev     you may not use this file except in compliance with the License.
651c0b2f7Stbbdev     You may obtain a copy of the License at
751c0b2f7Stbbdev 
851c0b2f7Stbbdev         http://www.apache.org/licenses/LICENSE-2.0
951c0b2f7Stbbdev 
1051c0b2f7Stbbdev     Unless required by applicable law or agreed to in writing, software
1151c0b2f7Stbbdev     distributed under the License is distributed on an "AS IS" BASIS,
1251c0b2f7Stbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351c0b2f7Stbbdev     See the License for the specific language governing permissions and
1451c0b2f7Stbbdev     limitations under the License.
1551c0b2f7Stbbdev */
1651c0b2f7Stbbdev 
1749e08aacStbbdev #include "oneapi/tbb/detail/_config.h"
1851c0b2f7Stbbdev 
1951c0b2f7Stbbdev #include "main.h"
2051c0b2f7Stbbdev #include "governor.h"
21c4568449SPavel Kumbrasev #include "threading_control.h"
2251c0b2f7Stbbdev #include "environment.h"
2351c0b2f7Stbbdev #include "market.h"
24*71e1bb8eSPavel Kumbrasev #include "tcm_adaptor.h"
2551c0b2f7Stbbdev #include "misc.h"
2651c0b2f7Stbbdev #include "itt_notify.h"
2751c0b2f7Stbbdev 
2851c0b2f7Stbbdev namespace tbb {
2951c0b2f7Stbbdev namespace detail {
3051c0b2f7Stbbdev namespace r1 {
3151c0b2f7Stbbdev 
3251c0b2f7Stbbdev //------------------------------------------------------------------------
3351c0b2f7Stbbdev // Begin shared data layout.
3451c0b2f7Stbbdev // The following global data items are mostly read-only after initialization.
3551c0b2f7Stbbdev //------------------------------------------------------------------------
3651c0b2f7Stbbdev 
3751c0b2f7Stbbdev //------------------------------------------------------------------------
3851c0b2f7Stbbdev // governor data
3951c0b2f7Stbbdev basic_tls<thread_data*> governor::theTLS;
4051c0b2f7Stbbdev rml::tbb_factory governor::theRMLServerFactory;
4151c0b2f7Stbbdev bool governor::UsePrivateRML;
4251c0b2f7Stbbdev bool governor::is_rethrow_broken;
4351c0b2f7Stbbdev 
4451c0b2f7Stbbdev //------------------------------------------------------------------------
45c4568449SPavel Kumbrasev // threading_control data
46c4568449SPavel Kumbrasev threading_control* threading_control::g_threading_control;
47c4568449SPavel Kumbrasev threading_control::global_mutex_type threading_control::g_threading_control_mutex;
4851c0b2f7Stbbdev 
4951c0b2f7Stbbdev //------------------------------------------------------------------------
5051c0b2f7Stbbdev // context propagation data
5151c0b2f7Stbbdev context_state_propagation_mutex_type the_context_state_propagation_mutex;
5251c0b2f7Stbbdev std::atomic<uintptr_t> the_context_state_propagation_epoch{};
5351c0b2f7Stbbdev 
5451c0b2f7Stbbdev //------------------------------------------------------------------------
5551c0b2f7Stbbdev // One time initialization data
5651c0b2f7Stbbdev 
5751c0b2f7Stbbdev //! Counter of references to global shared resources such as TLS.
5851c0b2f7Stbbdev std::atomic<int> __TBB_InitOnce::count{};
5951c0b2f7Stbbdev 
6051c0b2f7Stbbdev std::atomic_flag __TBB_InitOnce::InitializationLock = ATOMIC_FLAG_INIT;
6151c0b2f7Stbbdev 
6251c0b2f7Stbbdev //! Flag that is set to true after one-time initializations are done.
6351c0b2f7Stbbdev std::atomic<bool> __TBB_InitOnce::InitializationDone{};
6451c0b2f7Stbbdev 
6551c0b2f7Stbbdev #if __TBB_USE_ITT_NOTIFY
6651c0b2f7Stbbdev //! Defined in profiling.cpp
6751c0b2f7Stbbdev extern bool ITT_Present;
6851c0b2f7Stbbdev void ITT_DoUnsafeOneTimeInitialization();
6951c0b2f7Stbbdev #endif
7051c0b2f7Stbbdev 
7151c0b2f7Stbbdev #if !(_WIN32||_WIN64) || __TBB_SOURCE_DIRECTLY_INCLUDED
7251c0b2f7Stbbdev static __TBB_InitOnce __TBB_InitOnceHiddenInstance;
7351c0b2f7Stbbdev #endif
7451c0b2f7Stbbdev 
7551c0b2f7Stbbdev #if TBB_USE_ASSERT
7651c0b2f7Stbbdev std::atomic<int> the_observer_proxy_count;
7751c0b2f7Stbbdev 
7851c0b2f7Stbbdev struct check_observer_proxy_count {
~check_observer_proxy_counttbb::detail::r1::check_observer_proxy_count7951c0b2f7Stbbdev     ~check_observer_proxy_count() {
8051c0b2f7Stbbdev         if (the_observer_proxy_count != 0) {
8151c0b2f7Stbbdev             runtime_warning("Leaked %ld observer_proxy objects\n", long(the_observer_proxy_count));
8251c0b2f7Stbbdev         }
8351c0b2f7Stbbdev     }
8451c0b2f7Stbbdev };
8551c0b2f7Stbbdev // The proxy count checker shall be defined after __TBB_InitOnceHiddenInstance to check the count
8651c0b2f7Stbbdev // after auto termination.
8751c0b2f7Stbbdev static check_observer_proxy_count the_check_observer_proxy_count;
8851c0b2f7Stbbdev #endif /* TBB_USE_ASSERT */
8951c0b2f7Stbbdev 
9051c0b2f7Stbbdev //------------------------------------------------------------------------
9151c0b2f7Stbbdev // __TBB_InitOnce
9251c0b2f7Stbbdev //------------------------------------------------------------------------
9351c0b2f7Stbbdev 
add_ref()9451c0b2f7Stbbdev void __TBB_InitOnce::add_ref() {
95*71e1bb8eSPavel Kumbrasev     if (++count == 1) {
9651c0b2f7Stbbdev         governor::acquire_resources();
97*71e1bb8eSPavel Kumbrasev         tcm_adaptor::initialize();
98*71e1bb8eSPavel Kumbrasev     }
9951c0b2f7Stbbdev }
10051c0b2f7Stbbdev 
remove_ref()10151c0b2f7Stbbdev void __TBB_InitOnce::remove_ref() {
10251c0b2f7Stbbdev     int k = --count;
10351c0b2f7Stbbdev     __TBB_ASSERT(k>=0,"removed __TBB_InitOnce ref that was not added?");
10451c0b2f7Stbbdev     if( k==0 ) {
10551c0b2f7Stbbdev         governor::release_resources();
10651c0b2f7Stbbdev         ITT_FINI_ITTLIB();
1070e6d4699SAnuya Welling         ITT_RELEASE_RESOURCES();
10851c0b2f7Stbbdev     }
10951c0b2f7Stbbdev }
11051c0b2f7Stbbdev 
11151c0b2f7Stbbdev //------------------------------------------------------------------------
11251c0b2f7Stbbdev // One-time Initializations
11351c0b2f7Stbbdev //------------------------------------------------------------------------
11451c0b2f7Stbbdev 
11551c0b2f7Stbbdev //! Defined in cache_aligned_allocator.cpp
11651c0b2f7Stbbdev void initialize_cache_aligned_allocator();
11751c0b2f7Stbbdev 
11851c0b2f7Stbbdev //! Performs thread-safe lazy one-time general TBB initialization.
DoOneTimeInitialization()11951c0b2f7Stbbdev void DoOneTimeInitialization() {
12051c0b2f7Stbbdev     __TBB_InitOnce::lock();
12151c0b2f7Stbbdev     // No fence required for load of InitializationDone, because we are inside a critical section.
12251c0b2f7Stbbdev     if( !__TBB_InitOnce::InitializationDone ) {
12351c0b2f7Stbbdev         __TBB_InitOnce::add_ref();
124*71e1bb8eSPavel Kumbrasev         if( GetBoolEnvironmentVariable("TBB_VERSION") ) {
12551c0b2f7Stbbdev             PrintVersion();
126*71e1bb8eSPavel Kumbrasev             tcm_adaptor::print_version();
127*71e1bb8eSPavel Kumbrasev         }
12851c0b2f7Stbbdev         bool itt_present = false;
12951c0b2f7Stbbdev #if __TBB_USE_ITT_NOTIFY
13051c0b2f7Stbbdev         ITT_DoUnsafeOneTimeInitialization();
13151c0b2f7Stbbdev         itt_present = ITT_Present;
13251c0b2f7Stbbdev #endif /* __TBB_USE_ITT_NOTIFY */
13351c0b2f7Stbbdev         initialize_cache_aligned_allocator();
13451c0b2f7Stbbdev         governor::initialize_rml_factory();
13551c0b2f7Stbbdev         // Force processor groups support detection
13651c0b2f7Stbbdev         governor::default_num_threads();
13751c0b2f7Stbbdev         // Force OS regular page size detection
13851c0b2f7Stbbdev         governor::default_page_size();
13951c0b2f7Stbbdev         PrintExtraVersionInfo( "TOOLS SUPPORT", itt_present ? "enabled" : "disabled" );
14051c0b2f7Stbbdev         __TBB_InitOnce::InitializationDone = true;
14151c0b2f7Stbbdev     }
14251c0b2f7Stbbdev     __TBB_InitOnce::unlock();
14351c0b2f7Stbbdev }
14451c0b2f7Stbbdev 
14551c0b2f7Stbbdev #if (_WIN32||_WIN64) && !__TBB_SOURCE_DIRECTLY_INCLUDED
14651c0b2f7Stbbdev //! Windows "DllMain" that handles startup and shutdown of dynamic library.
DllMain(HANDLE,DWORD reason,LPVOID lpvReserved)14751c0b2f7Stbbdev extern "C" bool WINAPI DllMain( HANDLE /*hinstDLL*/, DWORD reason, LPVOID lpvReserved ) {
14851c0b2f7Stbbdev     switch( reason ) {
14951c0b2f7Stbbdev         case DLL_PROCESS_ATTACH:
15051c0b2f7Stbbdev             __TBB_InitOnce::add_ref();
15151c0b2f7Stbbdev             break;
15251c0b2f7Stbbdev         case DLL_PROCESS_DETACH:
15351c0b2f7Stbbdev             // Since THREAD_DETACH is not called for the main thread, call auto-termination
15451c0b2f7Stbbdev             // here as well - but not during process shutdown (due to risk of a deadlock).
15557f524caSIlya Isaev             if ( lpvReserved == nullptr ) { // library unload
15651c0b2f7Stbbdev                 governor::terminate_external_thread();
15751c0b2f7Stbbdev             }
15851c0b2f7Stbbdev             __TBB_InitOnce::remove_ref();
15951c0b2f7Stbbdev             // It is assumed that InitializationDone is not set after DLL_PROCESS_DETACH,
16051c0b2f7Stbbdev             // and thus no race on InitializationDone is possible.
16151c0b2f7Stbbdev             if ( __TBB_InitOnce::initialization_done() ) {
16251c0b2f7Stbbdev                 // Remove reference that we added in DoOneTimeInitialization.
16351c0b2f7Stbbdev                 __TBB_InitOnce::remove_ref();
16451c0b2f7Stbbdev             }
16551c0b2f7Stbbdev             break;
16651c0b2f7Stbbdev         case DLL_THREAD_DETACH:
16751c0b2f7Stbbdev             governor::terminate_external_thread();
16851c0b2f7Stbbdev             break;
16951c0b2f7Stbbdev     }
17051c0b2f7Stbbdev     return true;
17151c0b2f7Stbbdev }
17251c0b2f7Stbbdev #endif /* (_WIN32||_WIN64) && !__TBB_SOURCE_DIRECTLY_INCLUDED */
17351c0b2f7Stbbdev 
17451c0b2f7Stbbdev } // namespace r1
17551c0b2f7Stbbdev } // namespace detail
17651c0b2f7Stbbdev } // namespace tbb
177