1*51c0b2f7Stbbdev /* 2*51c0b2f7Stbbdev Copyright (c) 2005-2020 Intel Corporation 3*51c0b2f7Stbbdev 4*51c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License"); 5*51c0b2f7Stbbdev you may not use this file except in compliance with the License. 6*51c0b2f7Stbbdev You may obtain a copy of the License at 7*51c0b2f7Stbbdev 8*51c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0 9*51c0b2f7Stbbdev 10*51c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software 11*51c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS, 12*51c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*51c0b2f7Stbbdev See the License for the specific language governing permissions and 14*51c0b2f7Stbbdev limitations under the License. 15*51c0b2f7Stbbdev */ 16*51c0b2f7Stbbdev 17*51c0b2f7Stbbdev #ifndef __TBB_profiling_H 18*51c0b2f7Stbbdev #define __TBB_profiling_H 19*51c0b2f7Stbbdev 20*51c0b2f7Stbbdev #include "detail/_config.h" 21*51c0b2f7Stbbdev #include <cstdint> 22*51c0b2f7Stbbdev 23*51c0b2f7Stbbdev #include <string> 24*51c0b2f7Stbbdev 25*51c0b2f7Stbbdev namespace tbb { 26*51c0b2f7Stbbdev namespace detail { 27*51c0b2f7Stbbdev inline namespace d0 { 28*51c0b2f7Stbbdev // include list of index names 29*51c0b2f7Stbbdev #define TBB_STRING_RESOURCE(index_name,str) index_name, 30*51c0b2f7Stbbdev enum string_resource_index : std::uintptr_t { 31*51c0b2f7Stbbdev #include "detail/_string_resource.h" 32*51c0b2f7Stbbdev NUM_STRINGS 33*51c0b2f7Stbbdev }; 34*51c0b2f7Stbbdev #undef TBB_STRING_RESOURCE 35*51c0b2f7Stbbdev 36*51c0b2f7Stbbdev enum itt_relation 37*51c0b2f7Stbbdev { 38*51c0b2f7Stbbdev __itt_relation_is_unknown = 0, 39*51c0b2f7Stbbdev __itt_relation_is_dependent_on, /**< "A is dependent on B" means that A cannot start until B completes */ 40*51c0b2f7Stbbdev __itt_relation_is_sibling_of, /**< "A is sibling of B" means that A and B were created as a group */ 41*51c0b2f7Stbbdev __itt_relation_is_parent_of, /**< "A is parent of B" means that A created B */ 42*51c0b2f7Stbbdev __itt_relation_is_continuation_of, /**< "A is continuation of B" means that A assumes the dependencies of B */ 43*51c0b2f7Stbbdev __itt_relation_is_child_of, /**< "A is child of B" means that A was created by B (inverse of is_parent_of) */ 44*51c0b2f7Stbbdev __itt_relation_is_continued_by, /**< "A is continued by B" means that B assumes the dependencies of A (inverse of is_continuation_of) */ 45*51c0b2f7Stbbdev __itt_relation_is_predecessor_to /**< "A is predecessor to B" means that B cannot start until A completes (inverse of is_dependent_on) */ 46*51c0b2f7Stbbdev }; 47*51c0b2f7Stbbdev 48*51c0b2f7Stbbdev //! Unicode support 49*51c0b2f7Stbbdev #if (_WIN32||_WIN64) && !__MINGW32__ 50*51c0b2f7Stbbdev //! Unicode character type. Always wchar_t on Windows. 51*51c0b2f7Stbbdev using tchar = wchar_t; 52*51c0b2f7Stbbdev #else /* !WIN */ 53*51c0b2f7Stbbdev using tchar = char; 54*51c0b2f7Stbbdev #endif /* !WIN */ 55*51c0b2f7Stbbdev 56*51c0b2f7Stbbdev } // namespace d0 57*51c0b2f7Stbbdev } // namespace detail 58*51c0b2f7Stbbdev } // namespace tbb 59*51c0b2f7Stbbdev 60*51c0b2f7Stbbdev #include <atomic> 61*51c0b2f7Stbbdev #if _WIN32||_WIN64 62*51c0b2f7Stbbdev #include <stdlib.h> /* mbstowcs_s */ 63*51c0b2f7Stbbdev #endif 64*51c0b2f7Stbbdev // Need these to work regardless of tools support 65*51c0b2f7Stbbdev namespace tbb { 66*51c0b2f7Stbbdev namespace detail { 67*51c0b2f7Stbbdev namespace d1 { 68*51c0b2f7Stbbdev enum notify_type {prepare=0, cancel, acquired, releasing, destroy}; 69*51c0b2f7Stbbdev enum itt_domain_enum { ITT_DOMAIN_FLOW=0, ITT_DOMAIN_MAIN=1, ITT_DOMAIN_ALGO=2, ITT_NUM_DOMAINS }; 70*51c0b2f7Stbbdev } // namespace d1 71*51c0b2f7Stbbdev 72*51c0b2f7Stbbdev namespace r1 { 73*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC call_itt_notify(int t, void* ptr); 74*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC create_itt_sync(void* ptr, const tchar* objtype, const tchar* objname); 75*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_make_task_group(d1::itt_domain_enum domain, void* group, unsigned long long group_extra, 76*51c0b2f7Stbbdev void* parent, unsigned long long parent_extra, string_resource_index name_index); 77*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_task_begin(d1::itt_domain_enum domain, void* task, unsigned long long task_extra, 78*51c0b2f7Stbbdev void* parent, unsigned long long parent_extra, string_resource_index name_index); 79*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_task_end(d1::itt_domain_enum domain); 80*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_set_sync_name(void* obj, const tchar* name); 81*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_metadata_str_add(d1::itt_domain_enum domain, void* addr, unsigned long long addr_extra, 82*51c0b2f7Stbbdev string_resource_index key, const char* value); 83*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_metadata_ptr_add(d1::itt_domain_enum domain, void* addr, unsigned long long addr_extra, 84*51c0b2f7Stbbdev string_resource_index key, void* value); 85*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_relation_add(d1::itt_domain_enum domain, void* addr0, unsigned long long addr0_extra, 86*51c0b2f7Stbbdev itt_relation relation, void* addr1, unsigned long long addr1_extra); 87*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_region_begin(d1::itt_domain_enum domain, void* region, unsigned long long region_extra, 88*51c0b2f7Stbbdev void* parent, unsigned long long parent_extra, string_resource_index /* name_index */); 89*51c0b2f7Stbbdev void __TBB_EXPORTED_FUNC itt_region_end(d1::itt_domain_enum domain, void* region, unsigned long long region_extra); 90*51c0b2f7Stbbdev } // namespace r1 91*51c0b2f7Stbbdev 92*51c0b2f7Stbbdev namespace d1 { 93*51c0b2f7Stbbdev #if TBB_USE_PROFILING_TOOLS && (_WIN32||_WIN64) && !__MINGW32__ 94*51c0b2f7Stbbdev inline std::size_t multibyte_to_widechar(wchar_t* wcs, const char* mbs, std::size_t bufsize) { 95*51c0b2f7Stbbdev std::size_t len; 96*51c0b2f7Stbbdev mbstowcs_s(&len, wcs, bufsize, mbs, _TRUNCATE); 97*51c0b2f7Stbbdev return len; // mbstowcs_s counts null terminator 98*51c0b2f7Stbbdev } 99*51c0b2f7Stbbdev #endif 100*51c0b2f7Stbbdev 101*51c0b2f7Stbbdev #if TBB_USE_PROFILING_TOOLS 102*51c0b2f7Stbbdev inline void create_itt_sync(void *ptr, const char *objtype, const char *objname) { 103*51c0b2f7Stbbdev #if (_WIN32||_WIN64) && !__MINGW32__ 104*51c0b2f7Stbbdev std::size_t len_type = multibyte_to_widechar(nullptr, objtype, 0); 105*51c0b2f7Stbbdev wchar_t *type = new wchar_t[len_type]; 106*51c0b2f7Stbbdev multibyte_to_widechar(type, objtype, len_type); 107*51c0b2f7Stbbdev std::size_t len_name = multibyte_to_widechar(nullptr, objname, 0); 108*51c0b2f7Stbbdev wchar_t *name = new wchar_t[len_name]; 109*51c0b2f7Stbbdev multibyte_to_widechar(name, objname, len_name); 110*51c0b2f7Stbbdev #else // WIN 111*51c0b2f7Stbbdev const char *type = objtype; 112*51c0b2f7Stbbdev const char *name = objname; 113*51c0b2f7Stbbdev #endif 114*51c0b2f7Stbbdev r1::create_itt_sync(ptr, type, name); 115*51c0b2f7Stbbdev 116*51c0b2f7Stbbdev #if (_WIN32||_WIN64) && !__MINGW32__ 117*51c0b2f7Stbbdev delete[] type; 118*51c0b2f7Stbbdev delete[] name; 119*51c0b2f7Stbbdev #endif // WIN 120*51c0b2f7Stbbdev } 121*51c0b2f7Stbbdev 122*51c0b2f7Stbbdev // Distinguish notifications on task for reducing overheads 123*51c0b2f7Stbbdev #if TBB_USE_PROFILING_TOOLS == 2 124*51c0b2f7Stbbdev inline void call_itt_task_notify(d1::notify_type t, void *ptr) { 125*51c0b2f7Stbbdev r1::call_itt_notify((int)t, ptr); 126*51c0b2f7Stbbdev } 127*51c0b2f7Stbbdev #else 128*51c0b2f7Stbbdev inline void call_itt_task_notify(d1::notify_type, void *) {} 129*51c0b2f7Stbbdev #endif // TBB_USE_PROFILING_TOOLS 130*51c0b2f7Stbbdev 131*51c0b2f7Stbbdev inline void call_itt_notify(d1::notify_type t, void *ptr) { 132*51c0b2f7Stbbdev r1::call_itt_notify((int)t, ptr); 133*51c0b2f7Stbbdev } 134*51c0b2f7Stbbdev 135*51c0b2f7Stbbdev #if (_WIN32||_WIN64) && !__MINGW32__ 136*51c0b2f7Stbbdev inline void itt_set_sync_name(void* obj, const wchar_t* name) { 137*51c0b2f7Stbbdev r1::itt_set_sync_name(obj, name); 138*51c0b2f7Stbbdev } 139*51c0b2f7Stbbdev inline void itt_set_sync_name(void* obj, const char* name) { 140*51c0b2f7Stbbdev std::size_t len_name = multibyte_to_widechar(nullptr, name, 0); 141*51c0b2f7Stbbdev wchar_t *obj_name = new wchar_t[len_name]; 142*51c0b2f7Stbbdev multibyte_to_widechar(obj_name, name, len_name); 143*51c0b2f7Stbbdev r1::itt_set_sync_name(obj, obj_name); 144*51c0b2f7Stbbdev delete[] obj_name; 145*51c0b2f7Stbbdev } 146*51c0b2f7Stbbdev #else 147*51c0b2f7Stbbdev inline void itt_set_sync_name( void* obj, const char* name) { 148*51c0b2f7Stbbdev r1::itt_set_sync_name(obj, name); 149*51c0b2f7Stbbdev } 150*51c0b2f7Stbbdev #endif //WIN 151*51c0b2f7Stbbdev 152*51c0b2f7Stbbdev inline void itt_make_task_group(itt_domain_enum domain, void* group, unsigned long long group_extra, 153*51c0b2f7Stbbdev void* parent, unsigned long long parent_extra, string_resource_index name_index) { 154*51c0b2f7Stbbdev r1::itt_make_task_group(domain, group, group_extra, parent, parent_extra, name_index); 155*51c0b2f7Stbbdev } 156*51c0b2f7Stbbdev 157*51c0b2f7Stbbdev inline void itt_metadata_str_add( itt_domain_enum domain, void *addr, unsigned long long addr_extra, 158*51c0b2f7Stbbdev string_resource_index key, const char *value ) { 159*51c0b2f7Stbbdev r1::itt_metadata_str_add( domain, addr, addr_extra, key, value ); 160*51c0b2f7Stbbdev } 161*51c0b2f7Stbbdev 162*51c0b2f7Stbbdev inline void register_node_addr(itt_domain_enum domain, void *addr, unsigned long long addr_extra, 163*51c0b2f7Stbbdev string_resource_index key, void *value) { 164*51c0b2f7Stbbdev r1::itt_metadata_ptr_add(domain, addr, addr_extra, key, value); 165*51c0b2f7Stbbdev } 166*51c0b2f7Stbbdev 167*51c0b2f7Stbbdev inline void itt_relation_add( itt_domain_enum domain, void *addr0, unsigned long long addr0_extra, 168*51c0b2f7Stbbdev itt_relation relation, void *addr1, unsigned long long addr1_extra ) { 169*51c0b2f7Stbbdev r1::itt_relation_add( domain, addr0, addr0_extra, relation, addr1, addr1_extra ); 170*51c0b2f7Stbbdev } 171*51c0b2f7Stbbdev 172*51c0b2f7Stbbdev inline void itt_task_begin( itt_domain_enum domain, void *task, unsigned long long task_extra, 173*51c0b2f7Stbbdev void *parent, unsigned long long parent_extra, string_resource_index name_index ) { 174*51c0b2f7Stbbdev r1::itt_task_begin( domain, task, task_extra, parent, parent_extra, name_index ); 175*51c0b2f7Stbbdev } 176*51c0b2f7Stbbdev 177*51c0b2f7Stbbdev inline void itt_task_end( itt_domain_enum domain ) { 178*51c0b2f7Stbbdev r1::itt_task_end( domain ); 179*51c0b2f7Stbbdev } 180*51c0b2f7Stbbdev 181*51c0b2f7Stbbdev inline void itt_region_begin( itt_domain_enum domain, void *region, unsigned long long region_extra, 182*51c0b2f7Stbbdev void *parent, unsigned long long parent_extra, string_resource_index name_index ) { 183*51c0b2f7Stbbdev r1::itt_region_begin( domain, region, region_extra, parent, parent_extra, name_index ); 184*51c0b2f7Stbbdev } 185*51c0b2f7Stbbdev 186*51c0b2f7Stbbdev inline void itt_region_end( itt_domain_enum domain, void *region, unsigned long long region_extra ) { 187*51c0b2f7Stbbdev r1::itt_region_end( domain, region, region_extra ); 188*51c0b2f7Stbbdev } 189*51c0b2f7Stbbdev #else 190*51c0b2f7Stbbdev inline void create_itt_sync(void* /*ptr*/, const char* /*objtype*/, const char* /*objname*/) {} 191*51c0b2f7Stbbdev 192*51c0b2f7Stbbdev inline void call_itt_notify(notify_type /*t*/, void* /*ptr*/) {} 193*51c0b2f7Stbbdev 194*51c0b2f7Stbbdev inline void call_itt_task_notify(notify_type /*t*/, void* /*ptr*/) {} 195*51c0b2f7Stbbdev #endif // TBB_USE_PROFILING_TOOLS 196*51c0b2f7Stbbdev 197*51c0b2f7Stbbdev #if TBB_USE_PROFILING_TOOLS && !(TBB_USE_PROFILING_TOOLS == 2) 198*51c0b2f7Stbbdev class event { 199*51c0b2f7Stbbdev /** This class supports user event traces through itt. 200*51c0b2f7Stbbdev Common use-case is tagging data flow graph tasks (data-id) 201*51c0b2f7Stbbdev and visualization by Intel Advisor Flow Graph Analyzer (FGA) **/ 202*51c0b2f7Stbbdev // TODO: Replace implementation by itt user event api. 203*51c0b2f7Stbbdev 204*51c0b2f7Stbbdev const std::string my_name; 205*51c0b2f7Stbbdev 206*51c0b2f7Stbbdev static void emit_trace(const std::string &input) { 207*51c0b2f7Stbbdev itt_metadata_str_add( ITT_DOMAIN_FLOW, NULL, FLOW_NULL, USER_EVENT, ( "FGA::DATAID::" + input ).c_str() ); 208*51c0b2f7Stbbdev } 209*51c0b2f7Stbbdev 210*51c0b2f7Stbbdev public: 211*51c0b2f7Stbbdev event(const std::string &input) 212*51c0b2f7Stbbdev : my_name( input ) 213*51c0b2f7Stbbdev { } 214*51c0b2f7Stbbdev 215*51c0b2f7Stbbdev void emit() { 216*51c0b2f7Stbbdev emit_trace(my_name); 217*51c0b2f7Stbbdev } 218*51c0b2f7Stbbdev 219*51c0b2f7Stbbdev static void emit(const std::string &description) { 220*51c0b2f7Stbbdev emit_trace(description); 221*51c0b2f7Stbbdev } 222*51c0b2f7Stbbdev 223*51c0b2f7Stbbdev }; 224*51c0b2f7Stbbdev #else // TBB_USE_PROFILING_TOOLS && !(TBB_USE_PROFILING_TOOLS == 2) 225*51c0b2f7Stbbdev // Using empty struct if user event tracing is disabled: 226*51c0b2f7Stbbdev struct event { 227*51c0b2f7Stbbdev event(const std::string &) { } 228*51c0b2f7Stbbdev 229*51c0b2f7Stbbdev void emit() { } 230*51c0b2f7Stbbdev 231*51c0b2f7Stbbdev static void emit(const std::string &) { } 232*51c0b2f7Stbbdev }; 233*51c0b2f7Stbbdev #endif // TBB_USE_PROFILING_TOOLS && !(TBB_USE_PROFILING_TOOLS == 2) 234*51c0b2f7Stbbdev } // namespace d1 235*51c0b2f7Stbbdev } // namespace detail 236*51c0b2f7Stbbdev 237*51c0b2f7Stbbdev namespace profiling { 238*51c0b2f7Stbbdev using detail::d1::event; 239*51c0b2f7Stbbdev } 240*51c0b2f7Stbbdev } // namespace tbb 241*51c0b2f7Stbbdev 242*51c0b2f7Stbbdev 243*51c0b2f7Stbbdev #endif /* __TBB_profiling_H */ 244