151c0b2f7Stbbdev /* 2*b15aabb3Stbbdev Copyright (c) 2005-2021 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" 1849e08aacStbbdev #include "oneapi/tbb/detail/_template_helpers.h" 1951c0b2f7Stbbdev 2051c0b2f7Stbbdev #include "main.h" 2151c0b2f7Stbbdev #include "itt_notify.h" 2251c0b2f7Stbbdev 2349e08aacStbbdev #include "oneapi/tbb/profiling.h" 2451c0b2f7Stbbdev 2551c0b2f7Stbbdev #include <string.h> 2651c0b2f7Stbbdev 2751c0b2f7Stbbdev namespace tbb { 2851c0b2f7Stbbdev namespace detail { 2951c0b2f7Stbbdev namespace r1 { 3051c0b2f7Stbbdev 3151c0b2f7Stbbdev #if __TBB_USE_ITT_NOTIFY 3251c0b2f7Stbbdev bool ITT_Present; 3351c0b2f7Stbbdev static std::atomic<bool> ITT_InitializationDone; 3451c0b2f7Stbbdev 3551c0b2f7Stbbdev static __itt_domain *tbb_domains[d1::ITT_NUM_DOMAINS] = {}; 3651c0b2f7Stbbdev 3751c0b2f7Stbbdev struct resource_string { 3851c0b2f7Stbbdev const char *str; 3951c0b2f7Stbbdev __itt_string_handle *itt_str_handle; 4051c0b2f7Stbbdev }; 4151c0b2f7Stbbdev 4251c0b2f7Stbbdev // 4351c0b2f7Stbbdev // populate resource strings 4451c0b2f7Stbbdev // 4551c0b2f7Stbbdev #define TBB_STRING_RESOURCE( index_name, str ) { str, nullptr }, 4651c0b2f7Stbbdev static resource_string strings_for_itt[] = { 4749e08aacStbbdev #include "oneapi/tbb/detail/_string_resource.h" 4851c0b2f7Stbbdev { "num_resource_strings", nullptr } 4951c0b2f7Stbbdev }; 5051c0b2f7Stbbdev #undef TBB_STRING_RESOURCE 5151c0b2f7Stbbdev 5251c0b2f7Stbbdev static __itt_string_handle* ITT_get_string_handle(std::uintptr_t idx) { 5351c0b2f7Stbbdev __TBB_ASSERT(idx < NUM_STRINGS, "string handle out of valid range"); 5451c0b2f7Stbbdev return idx < NUM_STRINGS ? strings_for_itt[idx].itt_str_handle : NULL; 5551c0b2f7Stbbdev } 5651c0b2f7Stbbdev 5751c0b2f7Stbbdev static void ITT_init_domains() { 5851c0b2f7Stbbdev tbb_domains[d1::ITT_DOMAIN_MAIN] = __itt_domain_create( _T("tbb") ); 5951c0b2f7Stbbdev tbb_domains[d1::ITT_DOMAIN_MAIN]->flags = 1; 6051c0b2f7Stbbdev tbb_domains[d1::ITT_DOMAIN_FLOW] = __itt_domain_create( _T("tbb.flow") ); 6151c0b2f7Stbbdev tbb_domains[d1::ITT_DOMAIN_FLOW]->flags = 1; 6251c0b2f7Stbbdev tbb_domains[d1::ITT_DOMAIN_ALGO] = __itt_domain_create( _T("tbb.algorithm") ); 6351c0b2f7Stbbdev tbb_domains[d1::ITT_DOMAIN_ALGO]->flags = 1; 6451c0b2f7Stbbdev } 6551c0b2f7Stbbdev 6651c0b2f7Stbbdev static void ITT_init_strings() { 6751c0b2f7Stbbdev for ( std::uintptr_t i = 0; i < NUM_STRINGS; ++i ) { 6851c0b2f7Stbbdev #if _WIN32||_WIN64 6951c0b2f7Stbbdev strings_for_itt[i].itt_str_handle = __itt_string_handle_createA( strings_for_itt[i].str ); 7051c0b2f7Stbbdev #else 7151c0b2f7Stbbdev strings_for_itt[i].itt_str_handle = __itt_string_handle_create( strings_for_itt[i].str ); 7251c0b2f7Stbbdev #endif 7351c0b2f7Stbbdev } 7451c0b2f7Stbbdev } 7551c0b2f7Stbbdev 7651c0b2f7Stbbdev static void ITT_init() { 7751c0b2f7Stbbdev ITT_init_domains(); 7851c0b2f7Stbbdev ITT_init_strings(); 7951c0b2f7Stbbdev } 8051c0b2f7Stbbdev 8151c0b2f7Stbbdev /** Thread-unsafe lazy one-time initialization of tools interop. 8251c0b2f7Stbbdev Used by both dummy handlers and general TBB one-time initialization routine. **/ 8351c0b2f7Stbbdev void ITT_DoUnsafeOneTimeInitialization () { 8451c0b2f7Stbbdev // Double check ITT_InitializationDone is necessary because the first check 8551c0b2f7Stbbdev // in ITT_DoOneTimeInitialization is not guarded with the __TBB_InitOnce lock. 8651c0b2f7Stbbdev if ( !ITT_InitializationDone ) { 8751c0b2f7Stbbdev ITT_Present = (__TBB_load_ittnotify()!=0); 8851c0b2f7Stbbdev if (ITT_Present) ITT_init(); 8951c0b2f7Stbbdev ITT_InitializationDone = true; 9051c0b2f7Stbbdev } 9151c0b2f7Stbbdev } 9251c0b2f7Stbbdev 9351c0b2f7Stbbdev /** Thread-safe lazy one-time initialization of tools interop. 9451c0b2f7Stbbdev Used by dummy handlers only. **/ 9551c0b2f7Stbbdev extern "C" 9651c0b2f7Stbbdev void ITT_DoOneTimeInitialization() { 9751c0b2f7Stbbdev if ( !ITT_InitializationDone ) { 9851c0b2f7Stbbdev __TBB_InitOnce::lock(); 9951c0b2f7Stbbdev ITT_DoUnsafeOneTimeInitialization(); 10051c0b2f7Stbbdev __TBB_InitOnce::unlock(); 10151c0b2f7Stbbdev } 10251c0b2f7Stbbdev } 10351c0b2f7Stbbdev 10451c0b2f7Stbbdev void create_itt_sync(void* ptr, const tchar* objtype, const tchar* objname) { 10551c0b2f7Stbbdev ITT_SYNC_CREATE(ptr, objtype, objname); 10651c0b2f7Stbbdev } 10751c0b2f7Stbbdev 10851c0b2f7Stbbdev void call_itt_notify(int t, void *ptr) { 10951c0b2f7Stbbdev switch (t) { 11051c0b2f7Stbbdev case 0: ITT_NOTIFY(sync_prepare, ptr); break; 11151c0b2f7Stbbdev case 1: ITT_NOTIFY(sync_cancel, ptr); break; 11251c0b2f7Stbbdev case 2: ITT_NOTIFY(sync_acquired, ptr); break; 11351c0b2f7Stbbdev case 3: ITT_NOTIFY(sync_releasing, ptr); break; 11451c0b2f7Stbbdev case 4: ITT_NOTIFY(sync_destroy, ptr); break; 11551c0b2f7Stbbdev } 11651c0b2f7Stbbdev } 11751c0b2f7Stbbdev 11851c0b2f7Stbbdev void itt_set_sync_name(void* obj, const tchar* name) { 11951c0b2f7Stbbdev __itt_sync_rename(obj, name); 12051c0b2f7Stbbdev } 12151c0b2f7Stbbdev 12251c0b2f7Stbbdev const __itt_id itt_null_id = { 0, 0, 0 }; 12351c0b2f7Stbbdev 12451c0b2f7Stbbdev static inline __itt_domain* get_itt_domain(d1::itt_domain_enum idx) { 12551c0b2f7Stbbdev if (tbb_domains[idx] == NULL) { 12651c0b2f7Stbbdev ITT_DoOneTimeInitialization(); 12751c0b2f7Stbbdev } 12851c0b2f7Stbbdev return tbb_domains[idx]; 12951c0b2f7Stbbdev } 13051c0b2f7Stbbdev 13151c0b2f7Stbbdev static inline void itt_id_make(__itt_id* id, void* addr, unsigned long long extra) { 13251c0b2f7Stbbdev *id = __itt_id_make(addr, extra); 13351c0b2f7Stbbdev } 13451c0b2f7Stbbdev 13551c0b2f7Stbbdev static inline void itt_id_create(const __itt_domain* domain, __itt_id id) { 13651c0b2f7Stbbdev __itt_id_create(domain, id); 13751c0b2f7Stbbdev } 13851c0b2f7Stbbdev 13951c0b2f7Stbbdev void itt_make_task_group(d1::itt_domain_enum domain, void* group, unsigned long long group_extra, 14051c0b2f7Stbbdev void* parent, unsigned long long parent_extra, string_resource_index name_index) { 14151c0b2f7Stbbdev if (__itt_domain* d = get_itt_domain(domain)) { 14251c0b2f7Stbbdev __itt_id group_id = itt_null_id; 14351c0b2f7Stbbdev __itt_id parent_id = itt_null_id; 14451c0b2f7Stbbdev itt_id_make(&group_id, group, group_extra); 14551c0b2f7Stbbdev itt_id_create(d, group_id); 14651c0b2f7Stbbdev if (parent) { 14751c0b2f7Stbbdev itt_id_make(&parent_id, parent, parent_extra); 14851c0b2f7Stbbdev } 14951c0b2f7Stbbdev __itt_string_handle* n = ITT_get_string_handle(name_index); 15051c0b2f7Stbbdev __itt_task_group(d, group_id, parent_id, n); 15151c0b2f7Stbbdev } 15251c0b2f7Stbbdev } 15351c0b2f7Stbbdev 15451c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_metadata_str_add(d1::itt_domain_enum domain, void *addr, unsigned long long addr_extra, 15551c0b2f7Stbbdev string_resource_index key, const char *value ) { 15651c0b2f7Stbbdev if ( __itt_domain *d = get_itt_domain( domain ) ) { 15751c0b2f7Stbbdev __itt_id id = itt_null_id; 15851c0b2f7Stbbdev itt_id_make( &id, addr, addr_extra ); 15951c0b2f7Stbbdev __itt_string_handle *k = ITT_get_string_handle(key); 16051c0b2f7Stbbdev size_t value_length = strlen( value ); 16151c0b2f7Stbbdev #if _WIN32||_WIN64 16251c0b2f7Stbbdev __itt_metadata_str_addA(d, id, k, value, value_length); 16351c0b2f7Stbbdev #else 16451c0b2f7Stbbdev __itt_metadata_str_add(d, id, k, value, value_length); 16551c0b2f7Stbbdev #endif 16651c0b2f7Stbbdev } 16751c0b2f7Stbbdev } 16851c0b2f7Stbbdev 16951c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_metadata_ptr_add(d1::itt_domain_enum domain, void *addr, unsigned long long addr_extra, 17051c0b2f7Stbbdev string_resource_index key, void *value ) { 17151c0b2f7Stbbdev if ( __itt_domain *d = get_itt_domain( domain ) ) { 17251c0b2f7Stbbdev __itt_id id = itt_null_id; 17351c0b2f7Stbbdev itt_id_make( &id, addr, addr_extra ); 17451c0b2f7Stbbdev __itt_string_handle *k = ITT_get_string_handle(key); 17551c0b2f7Stbbdev #if __TBB_x86_32 17651c0b2f7Stbbdev __itt_metadata_add(d, id, k, __itt_metadata_u32, 1, value); 17751c0b2f7Stbbdev #else 17851c0b2f7Stbbdev __itt_metadata_add(d, id, k, __itt_metadata_u64, 1, value); 17951c0b2f7Stbbdev #endif 18051c0b2f7Stbbdev } 18151c0b2f7Stbbdev } 18251c0b2f7Stbbdev 18351c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_relation_add(d1::itt_domain_enum domain, void *addr0, unsigned long long addr0_extra, 18451c0b2f7Stbbdev itt_relation relation, void *addr1, unsigned long long addr1_extra ) { 18551c0b2f7Stbbdev if ( __itt_domain *d = get_itt_domain( domain ) ) { 18651c0b2f7Stbbdev __itt_id id0 = itt_null_id; 18751c0b2f7Stbbdev __itt_id id1 = itt_null_id; 18851c0b2f7Stbbdev itt_id_make( &id0, addr0, addr0_extra ); 18951c0b2f7Stbbdev itt_id_make( &id1, addr1, addr1_extra ); 19051c0b2f7Stbbdev __itt_relation_add( d, id0, (__itt_relation)relation, id1 ); 19151c0b2f7Stbbdev } 19251c0b2f7Stbbdev } 19351c0b2f7Stbbdev 19451c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_task_begin(d1::itt_domain_enum domain, void* task, unsigned long long task_extra, 19551c0b2f7Stbbdev void* parent, unsigned long long parent_extra, string_resource_index name_index) { 19651c0b2f7Stbbdev if (__itt_domain* d = get_itt_domain(domain)) { 19751c0b2f7Stbbdev __itt_id task_id = itt_null_id; 19851c0b2f7Stbbdev __itt_id parent_id = itt_null_id; 19951c0b2f7Stbbdev if (task) { 20051c0b2f7Stbbdev itt_id_make(&task_id, task, task_extra); 20151c0b2f7Stbbdev } 20251c0b2f7Stbbdev if (parent) { 20351c0b2f7Stbbdev itt_id_make(&parent_id, parent, parent_extra); 20451c0b2f7Stbbdev } 20551c0b2f7Stbbdev __itt_string_handle* n = ITT_get_string_handle(name_index); 20651c0b2f7Stbbdev __itt_task_begin(d, task_id, parent_id, n); 20751c0b2f7Stbbdev } 20851c0b2f7Stbbdev } 20951c0b2f7Stbbdev 21051c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_task_end(d1::itt_domain_enum domain) { 21151c0b2f7Stbbdev if (__itt_domain* d = get_itt_domain(domain)) { 21251c0b2f7Stbbdev __itt_task_end(d); 21351c0b2f7Stbbdev } 21451c0b2f7Stbbdev } 21551c0b2f7Stbbdev 21651c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_region_begin(d1::itt_domain_enum domain, void *region, unsigned long long region_extra, 21751c0b2f7Stbbdev void *parent, unsigned long long parent_extra, string_resource_index /* name_index */ ) { 21851c0b2f7Stbbdev if ( __itt_domain *d = get_itt_domain( domain ) ) { 21951c0b2f7Stbbdev __itt_id region_id = itt_null_id; 22051c0b2f7Stbbdev __itt_id parent_id = itt_null_id; 22151c0b2f7Stbbdev itt_id_make( ®ion_id, region, region_extra ); 22251c0b2f7Stbbdev if ( parent ) { 22351c0b2f7Stbbdev itt_id_make( &parent_id, parent, parent_extra ); 22451c0b2f7Stbbdev } 22551c0b2f7Stbbdev __itt_region_begin( d, region_id, parent_id, NULL ); 22651c0b2f7Stbbdev } 22751c0b2f7Stbbdev } 22851c0b2f7Stbbdev 22951c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_region_end(d1::itt_domain_enum domain, void *region, unsigned long long region_extra ) { 23051c0b2f7Stbbdev if ( __itt_domain *d = get_itt_domain( domain ) ) { 23151c0b2f7Stbbdev __itt_id region_id = itt_null_id; 23251c0b2f7Stbbdev itt_id_make( ®ion_id, region, region_extra ); 23351c0b2f7Stbbdev __itt_region_end( d, region_id ); 23451c0b2f7Stbbdev } 23551c0b2f7Stbbdev } 23651c0b2f7Stbbdev 23751c0b2f7Stbbdev #else 23851c0b2f7Stbbdev void create_itt_sync(void* /*ptr*/, const tchar* /*objtype*/, const tchar* /*objname*/) {} 23951c0b2f7Stbbdev void call_itt_notify(int /*t*/, void* /*ptr*/) {} 24051c0b2f7Stbbdev void itt_set_sync_name(void* /*obj*/, const tchar* /*name*/) {} 24151c0b2f7Stbbdev void itt_make_task_group(d1::itt_domain_enum /*domain*/, void* /*group*/, unsigned long long /*group_extra*/, 24251c0b2f7Stbbdev void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/) {} 24351c0b2f7Stbbdev void itt_metadata_str_add(d1::itt_domain_enum /*domain*/, void* /*addr*/, unsigned long long /*addr_extra*/, 24451c0b2f7Stbbdev string_resource_index /*key*/, const char* /*value*/ ) { } 24551c0b2f7Stbbdev void itt_metadata_ptr_add(d1::itt_domain_enum /*domain*/, void * /*addr*/, unsigned long long /*addr_extra*/, 24651c0b2f7Stbbdev string_resource_index /*key*/, void * /*value*/ ) {} 24751c0b2f7Stbbdev void itt_relation_add(d1::itt_domain_enum /*domain*/, void* /*addr0*/, unsigned long long /*addr0_extra*/, 24851c0b2f7Stbbdev itt_relation /*relation*/, void* /*addr1*/, unsigned long long /*addr1_extra*/ ) { } 24951c0b2f7Stbbdev void itt_task_begin(d1::itt_domain_enum /*domain*/, void* /*task*/, unsigned long long /*task_extra*/, 25051c0b2f7Stbbdev void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/ ) { } 25151c0b2f7Stbbdev void itt_task_end(d1::itt_domain_enum /*domain*/ ) { } 25251c0b2f7Stbbdev void itt_region_begin(d1::itt_domain_enum /*domain*/, void* /*region*/, unsigned long long /*region_extra*/, 25351c0b2f7Stbbdev void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/ ) { } 25451c0b2f7Stbbdev void itt_region_end(d1::itt_domain_enum /*domain*/, void* /*region*/, unsigned long long /*region_extra*/ ) { } 25551c0b2f7Stbbdev #endif /* __TBB_USE_ITT_NOTIFY */ 25651c0b2f7Stbbdev 25751c0b2f7Stbbdev const tchar 25851c0b2f7Stbbdev *SyncType_Scheduler = _T("%Constant") 25951c0b2f7Stbbdev ; 26051c0b2f7Stbbdev const tchar 26151c0b2f7Stbbdev *SyncObj_ContextsList = _T("TBB Scheduler") 26251c0b2f7Stbbdev ; 26351c0b2f7Stbbdev } // namespace r1 26451c0b2f7Stbbdev } // namespace detail 26551c0b2f7Stbbdev } // namespace tbb 266