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 | |