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