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