1 /* 2 Copyright (c) 2005-2022 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 #include "oneapi/tbb/detail/_template_helpers.h" 19 20 #include "main.h" 21 #include "itt_notify.h" 22 23 #include "oneapi/tbb/profiling.h" 24 25 #include <string.h> 26 27 namespace tbb { 28 namespace detail { 29 namespace r1 { 30 31 #if __TBB_USE_ITT_NOTIFY 32 bool ITT_Present; 33 static std::atomic<bool> ITT_InitializationDone; 34 35 static __itt_domain *tbb_domains[d1::ITT_NUM_DOMAINS] = {}; 36 37 struct resource_string { 38 const char *str; 39 __itt_string_handle *itt_str_handle; 40 }; 41 42 // 43 // populate resource strings 44 // 45 #define TBB_STRING_RESOURCE( index_name, str ) { str, nullptr }, 46 static resource_string strings_for_itt[] = { 47 #include "oneapi/tbb/detail/_string_resource.h" 48 { "num_resource_strings", nullptr } 49 }; 50 #undef TBB_STRING_RESOURCE 51 52 static __itt_string_handle* ITT_get_string_handle(std::uintptr_t idx) { 53 __TBB_ASSERT(idx < NUM_STRINGS, "string handle out of valid range"); 54 return idx < NUM_STRINGS ? strings_for_itt[idx].itt_str_handle : nullptr; 55 } 56 57 static void ITT_init_domains() { 58 tbb_domains[d1::ITT_DOMAIN_MAIN] = __itt_domain_create( _T("tbb") ); 59 tbb_domains[d1::ITT_DOMAIN_MAIN]->flags = 1; 60 tbb_domains[d1::ITT_DOMAIN_FLOW] = __itt_domain_create( _T("tbb.flow") ); 61 tbb_domains[d1::ITT_DOMAIN_FLOW]->flags = 1; 62 tbb_domains[d1::ITT_DOMAIN_ALGO] = __itt_domain_create( _T("tbb.algorithm") ); 63 tbb_domains[d1::ITT_DOMAIN_ALGO]->flags = 1; 64 } 65 66 static void ITT_init_strings() { 67 for ( std::uintptr_t i = 0; i < NUM_STRINGS; ++i ) { 68 #if _WIN32||_WIN64 69 strings_for_itt[i].itt_str_handle = __itt_string_handle_createA( strings_for_itt[i].str ); 70 #else 71 strings_for_itt[i].itt_str_handle = __itt_string_handle_create( strings_for_itt[i].str ); 72 #endif 73 } 74 } 75 76 static void ITT_init() { 77 ITT_init_domains(); 78 ITT_init_strings(); 79 } 80 81 /** Thread-unsafe lazy one-time initialization of tools interop. 82 Used by both dummy handlers and general TBB one-time initialization routine. **/ 83 void ITT_DoUnsafeOneTimeInitialization () { 84 // Double check ITT_InitializationDone is necessary because the first check 85 // in ITT_DoOneTimeInitialization is not guarded with the __TBB_InitOnce lock. 86 if ( !ITT_InitializationDone ) { 87 ITT_Present = (__TBB_load_ittnotify()!=0); 88 if (ITT_Present) ITT_init(); 89 ITT_InitializationDone = true; 90 } 91 } 92 93 /** Thread-safe lazy one-time initialization of tools interop. 94 Used by dummy handlers only. **/ 95 extern "C" 96 void ITT_DoOneTimeInitialization() { 97 if ( !ITT_InitializationDone ) { 98 __TBB_InitOnce::lock(); 99 ITT_DoUnsafeOneTimeInitialization(); 100 __TBB_InitOnce::unlock(); 101 } 102 } 103 104 void create_itt_sync(void* ptr, const tchar* objtype, const tchar* objname) { 105 ITT_SYNC_CREATE(ptr, objtype, objname); 106 } 107 108 void call_itt_notify(int t, void *ptr) { 109 switch (t) { 110 case 0: ITT_NOTIFY(sync_prepare, ptr); break; 111 case 1: ITT_NOTIFY(sync_cancel, ptr); break; 112 case 2: ITT_NOTIFY(sync_acquired, ptr); break; 113 case 3: ITT_NOTIFY(sync_releasing, ptr); break; 114 case 4: ITT_NOTIFY(sync_destroy, ptr); break; 115 } 116 } 117 118 void itt_set_sync_name(void* obj, const tchar* name) { 119 __itt_sync_rename(obj, name); 120 } 121 122 const __itt_id itt_null_id = { 0, 0, 0 }; 123 124 static inline __itt_domain* get_itt_domain(d1::itt_domain_enum idx) { 125 if (tbb_domains[idx] == nullptr) { 126 ITT_DoOneTimeInitialization(); 127 } 128 return tbb_domains[idx]; 129 } 130 131 static inline void itt_id_make(__itt_id* id, void* addr, unsigned long long extra) { 132 *id = __itt_id_make(addr, extra); 133 } 134 135 static inline void itt_id_create(const __itt_domain* domain, __itt_id id) { 136 __itt_id_create(domain, id); 137 } 138 139 void itt_make_task_group(d1::itt_domain_enum domain, void* group, unsigned long long group_extra, 140 void* parent, unsigned long long parent_extra, string_resource_index name_index) { 141 if (__itt_domain* d = get_itt_domain(domain)) { 142 __itt_id group_id = itt_null_id; 143 __itt_id parent_id = itt_null_id; 144 itt_id_make(&group_id, group, group_extra); 145 itt_id_create(d, group_id); 146 if (parent) { 147 itt_id_make(&parent_id, parent, parent_extra); 148 } 149 __itt_string_handle* n = ITT_get_string_handle(name_index); 150 __itt_task_group(d, group_id, parent_id, n); 151 } 152 } 153 154 void __TBB_EXPORTED_FUNC itt_metadata_str_add(d1::itt_domain_enum domain, void *addr, unsigned long long addr_extra, 155 string_resource_index key, const char *value ) { 156 if ( __itt_domain *d = get_itt_domain( domain ) ) { 157 __itt_id id = itt_null_id; 158 itt_id_make( &id, addr, addr_extra ); 159 __itt_string_handle *k = ITT_get_string_handle(key); 160 size_t value_length = strlen( value ); 161 #if _WIN32||_WIN64 162 __itt_metadata_str_addA(d, id, k, value, value_length); 163 #else 164 __itt_metadata_str_add(d, id, k, value, value_length); 165 #endif 166 } 167 } 168 169 void __TBB_EXPORTED_FUNC itt_metadata_ptr_add(d1::itt_domain_enum domain, void *addr, unsigned long long addr_extra, 170 string_resource_index key, void *value ) { 171 if ( __itt_domain *d = get_itt_domain( domain ) ) { 172 __itt_id id = itt_null_id; 173 itt_id_make( &id, addr, addr_extra ); 174 __itt_string_handle *k = ITT_get_string_handle(key); 175 #if __TBB_x86_32 176 __itt_metadata_add(d, id, k, __itt_metadata_u32, 1, value); 177 #else 178 __itt_metadata_add(d, id, k, __itt_metadata_u64, 1, value); 179 #endif 180 } 181 } 182 183 void __TBB_EXPORTED_FUNC itt_relation_add(d1::itt_domain_enum domain, void *addr0, unsigned long long addr0_extra, 184 itt_relation relation, void *addr1, unsigned long long addr1_extra ) { 185 if ( __itt_domain *d = get_itt_domain( domain ) ) { 186 __itt_id id0 = itt_null_id; 187 __itt_id id1 = itt_null_id; 188 itt_id_make( &id0, addr0, addr0_extra ); 189 itt_id_make( &id1, addr1, addr1_extra ); 190 __itt_relation_add( d, id0, (__itt_relation)relation, id1 ); 191 } 192 } 193 194 void __TBB_EXPORTED_FUNC itt_task_begin(d1::itt_domain_enum domain, void* task, unsigned long long task_extra, 195 void* parent, unsigned long long parent_extra, string_resource_index name_index) { 196 if (__itt_domain* d = get_itt_domain(domain)) { 197 __itt_id task_id = itt_null_id; 198 __itt_id parent_id = itt_null_id; 199 if (task) { 200 itt_id_make(&task_id, task, task_extra); 201 } 202 if (parent) { 203 itt_id_make(&parent_id, parent, parent_extra); 204 } 205 __itt_string_handle* n = ITT_get_string_handle(name_index); 206 __itt_task_begin(d, task_id, parent_id, n); 207 } 208 } 209 210 void __TBB_EXPORTED_FUNC itt_task_end(d1::itt_domain_enum domain) { 211 if (__itt_domain* d = get_itt_domain(domain)) { 212 __itt_task_end(d); 213 } 214 } 215 216 void __TBB_EXPORTED_FUNC itt_region_begin(d1::itt_domain_enum domain, void *region, unsigned long long region_extra, 217 void *parent, unsigned long long parent_extra, string_resource_index /* name_index */ ) { 218 if ( __itt_domain *d = get_itt_domain( domain ) ) { 219 __itt_id region_id = itt_null_id; 220 __itt_id parent_id = itt_null_id; 221 itt_id_make( ®ion_id, region, region_extra ); 222 if ( parent ) { 223 itt_id_make( &parent_id, parent, parent_extra ); 224 } 225 __itt_region_begin( d, region_id, parent_id, nullptr ); 226 } 227 } 228 229 void __TBB_EXPORTED_FUNC itt_region_end(d1::itt_domain_enum domain, void *region, unsigned long long region_extra ) { 230 if ( __itt_domain *d = get_itt_domain( domain ) ) { 231 __itt_id region_id = itt_null_id; 232 itt_id_make( ®ion_id, region, region_extra ); 233 __itt_region_end( d, region_id ); 234 } 235 } 236 237 #else 238 void create_itt_sync(void* /*ptr*/, const tchar* /*objtype*/, const tchar* /*objname*/) {} 239 void call_itt_notify(int /*t*/, void* /*ptr*/) {} 240 void itt_set_sync_name(void* /*obj*/, const tchar* /*name*/) {} 241 void itt_make_task_group(d1::itt_domain_enum /*domain*/, void* /*group*/, unsigned long long /*group_extra*/, 242 void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/) {} 243 void itt_metadata_str_add(d1::itt_domain_enum /*domain*/, void* /*addr*/, unsigned long long /*addr_extra*/, 244 string_resource_index /*key*/, const char* /*value*/ ) { } 245 void itt_metadata_ptr_add(d1::itt_domain_enum /*domain*/, void * /*addr*/, unsigned long long /*addr_extra*/, 246 string_resource_index /*key*/, void * /*value*/ ) {} 247 void itt_relation_add(d1::itt_domain_enum /*domain*/, void* /*addr0*/, unsigned long long /*addr0_extra*/, 248 itt_relation /*relation*/, void* /*addr1*/, unsigned long long /*addr1_extra*/ ) { } 249 void itt_task_begin(d1::itt_domain_enum /*domain*/, void* /*task*/, unsigned long long /*task_extra*/, 250 void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/ ) { } 251 void itt_task_end(d1::itt_domain_enum /*domain*/ ) { } 252 void itt_region_begin(d1::itt_domain_enum /*domain*/, void* /*region*/, unsigned long long /*region_extra*/, 253 void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/ ) { } 254 void itt_region_end(d1::itt_domain_enum /*domain*/, void* /*region*/, unsigned long long /*region_extra*/ ) { } 255 #endif /* __TBB_USE_ITT_NOTIFY */ 256 257 const tchar 258 *SyncType_Scheduler = _T("%Constant") 259 ; 260 const tchar 261 *SyncObj_ContextsList = _T("TBB Scheduler") 262 ; 263 } // namespace r1 264 } // namespace detail 265 } // namespace tbb 266