| 1 | /* |
| 2 | Copyright (c) 2005-2021 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 , |
| 76 | void* parent, unsigned long long , 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 , |
| 78 | void* parent, unsigned long long , 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 , |
| 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 , |
| 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 , |
| 86 | itt_relation relation, void* addr1, unsigned long long ); |
| 87 | TBB_EXPORT void __TBB_EXPORTED_FUNC itt_region_begin(d1::itt_domain_enum domain, void* region, unsigned long long , |
| 88 | void* parent, unsigned long long , 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 ); |
| 90 | } // namespace r1 |
| 91 | |
| 92 | namespace d1 { |
| 93 | #if TBB_USE_PROFILING_TOOLS && (_WIN32||_WIN64) |
| 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 |
| 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, objtype: type, objname: 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 |
| 124 | inline void call_itt_task_notify(d1::notify_type t, void *ptr) { |
| 125 | r1::call_itt_notify(t: (int)t, ptr); |
| 126 | } |
| 127 | #else |
| 128 | inline void call_itt_task_notify(d1::notify_type, void *) {} |
| 129 | #endif // TBB_USE_PROFILING_TOOLS |
| 130 | |
| 131 | inline void call_itt_notify(d1::notify_type t, void *ptr) { |
| 132 | r1::call_itt_notify(t: (int)t, ptr); |
| 133 | } |
| 134 | |
| 135 | #if (_WIN32||_WIN64) && !__MINGW32__ |
| 136 | inline void itt_set_sync_name(void* obj, const wchar_t* name) { |
| 137 | r1::itt_set_sync_name(obj, name); |
| 138 | } |
| 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 |
| 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 | |
| 152 | inline void itt_make_task_group(itt_domain_enum domain, void* group, unsigned long long , |
| 153 | void* parent, unsigned long long , string_resource_index name_index) { |
| 154 | r1::itt_make_task_group(domain, group, group_extra, parent, parent_extra, name_index); |
| 155 | } |
| 156 | |
| 157 | inline void itt_metadata_str_add( itt_domain_enum domain, void *addr, unsigned long long , |
| 158 | string_resource_index key, const char *value ) { |
| 159 | r1::itt_metadata_str_add( domain, addr, addr_extra, key, value ); |
| 160 | } |
| 161 | |
| 162 | inline void register_node_addr(itt_domain_enum domain, void *addr, unsigned long long , |
| 163 | string_resource_index key, void *value) { |
| 164 | r1::itt_metadata_ptr_add(domain, addr, addr_extra, key, value); |
| 165 | } |
| 166 | |
| 167 | inline void itt_relation_add( itt_domain_enum domain, void *addr0, unsigned long long , |
| 168 | itt_relation relation, void *addr1, unsigned long long ) { |
| 169 | r1::itt_relation_add( domain, addr0, addr0_extra, relation, addr1, addr1_extra ); |
| 170 | } |
| 171 | |
| 172 | inline void itt_task_begin( itt_domain_enum domain, void *task, unsigned long long , |
| 173 | void *parent, unsigned long long , string_resource_index name_index ) { |
| 174 | r1::itt_task_begin( domain, task, task_extra, parent, parent_extra, name_index ); |
| 175 | } |
| 176 | |
| 177 | inline void itt_task_end( itt_domain_enum domain ) { |
| 178 | r1::itt_task_end( domain ); |
| 179 | } |
| 180 | |
| 181 | inline void itt_region_begin( itt_domain_enum domain, void *region, unsigned long long , |
| 182 | void *parent, unsigned long long , string_resource_index name_index ) { |
| 183 | r1::itt_region_begin( domain, region, region_extra, parent, parent_extra, name_index ); |
| 184 | } |
| 185 | |
| 186 | inline void itt_region_end( itt_domain_enum domain, void *region, unsigned long long ) { |
| 187 | r1::itt_region_end( domain, region, region_extra ); |
| 188 | } |
| 189 | #else |
| 190 | inline void create_itt_sync(void* /*ptr*/, const char* /*objtype*/, const char* /*objname*/) {} |
| 191 | |
| 192 | inline void call_itt_notify(notify_type /*t*/, void* /*ptr*/) {} |
| 193 | |
| 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 | |
| 206 | static void emit_trace(const std::string &input) { |
| 207 | itt_metadata_str_add( ITT_DOMAIN_FLOW, NULL, FLOW_NULL, USER_EVENT, ( "FGA::DATAID::" + input ).c_str() ); |
| 208 | } |
| 209 | |
| 210 | public: |
| 211 | event(const std::string &input) |
| 212 | : my_name( input ) |
| 213 | { } |
| 214 | |
| 215 | void emit() { |
| 216 | emit_trace(my_name); |
| 217 | } |
| 218 | |
| 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 { |
| 227 | event(const std::string &) { } |
| 228 | |
| 229 | void emit() { } |
| 230 | |
| 231 | 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 | |