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 #ifndef _FGT_GRAPH_TRACE_IMPL_H
18 #define _FGT_GRAPH_TRACE_IMPL_H
19 
20 #include "../profiling.h"
21 #if (_MSC_VER >= 1900)
22     #include <intrin.h>
23 #endif
24 
25 namespace tbb {
26 namespace detail {
27 namespace d1 {
28 
29 template< typename T > class sender;
30 template< typename T > class receiver;
31 
32 #if TBB_USE_PROFILING_TOOLS
33     #if __TBB_FLOW_TRACE_CODEPTR
34         #if (_MSC_VER >= 1900)
35             #define CODEPTR() (_ReturnAddress())
36         #elif __TBB_GCC_VERSION >= 40800
37             #define CODEPTR() ( __builtin_return_address(0))
38         #else
39             #define CODEPTR() nullptr
40         #endif
41     #else
42         #define CODEPTR() nullptr
43     #endif /* __TBB_FLOW_TRACE_CODEPTR */
44 
fgt_alias_port(void * node,void * p,bool visible)45 static inline void fgt_alias_port(void *node, void *p, bool visible) {
46     if(visible)
47         itt_relation_add( ITT_DOMAIN_FLOW, node, FLOW_NODE, __itt_relation_is_parent_of, p, FLOW_NODE );
48     else
49         itt_relation_add( ITT_DOMAIN_FLOW, p, FLOW_NODE, __itt_relation_is_child_of, node, FLOW_NODE );
50 }
51 
fgt_composite(void * codeptr,void * node,void * graph)52 static inline void fgt_composite ( void* codeptr, void *node, void *graph ) {
53     itt_make_task_group( ITT_DOMAIN_FLOW, node, FLOW_NODE, graph, FLOW_GRAPH, FLOW_COMPOSITE_NODE );
54     suppress_unused_warning( codeptr );
55 #if __TBB_FLOW_TRACE_CODEPTR
56     if (codeptr != nullptr) {
57         register_node_addr(ITT_DOMAIN_FLOW, node, FLOW_NODE, CODE_ADDRESS, &codeptr);
58     }
59 #endif
60 }
61 
fgt_internal_alias_input_port(void * node,void * p,string_resource_index name_index)62 static inline void fgt_internal_alias_input_port( void *node, void *p, string_resource_index name_index ) {
63     itt_make_task_group( ITT_DOMAIN_FLOW, p, FLOW_INPUT_PORT, node, FLOW_NODE, name_index );
64     itt_relation_add( ITT_DOMAIN_FLOW, node, FLOW_NODE, __itt_relation_is_parent_of, p, FLOW_INPUT_PORT );
65 }
66 
fgt_internal_alias_output_port(void * node,void * p,string_resource_index name_index)67 static inline void fgt_internal_alias_output_port( void *node, void *p, string_resource_index name_index ) {
68     itt_make_task_group( ITT_DOMAIN_FLOW, p, FLOW_OUTPUT_PORT, node, FLOW_NODE, name_index );
69     itt_relation_add( ITT_DOMAIN_FLOW, node, FLOW_NODE, __itt_relation_is_parent_of, p, FLOW_OUTPUT_PORT );
70 }
71 
72 template<typename InputType>
alias_input_port(void * node,receiver<InputType> * port,string_resource_index name_index)73 void alias_input_port(void *node, receiver<InputType>* port, string_resource_index name_index) {
74     // TODO: Make fgt_internal_alias_input_port a function template?
75     fgt_internal_alias_input_port( node, port, name_index);
76 }
77 
78 template < typename PortsTuple, int N >
79 struct fgt_internal_input_alias_helper {
alias_portfgt_internal_input_alias_helper80     static void alias_port( void *node, PortsTuple &ports ) {
81         alias_input_port( node, &(std::get<N-1>(ports)), static_cast<string_resource_index>(FLOW_INPUT_PORT_0 + N - 1) );
82         fgt_internal_input_alias_helper<PortsTuple, N-1>::alias_port( node, ports );
83     }
84 };
85 
86 template < typename PortsTuple >
87 struct fgt_internal_input_alias_helper<PortsTuple, 0> {
88     static void alias_port( void * /* node */, PortsTuple & /* ports */ ) { }
89 };
90 
91 template<typename OutputType>
92 void alias_output_port(void *node, sender<OutputType>* port, string_resource_index name_index) {
93     // TODO: Make fgt_internal_alias_output_port a function template?
94     fgt_internal_alias_output_port( node, static_cast<void *>(port), name_index);
95 }
96 
97 template < typename PortsTuple, int N >
98 struct fgt_internal_output_alias_helper {
99     static void alias_port( void *node, PortsTuple &ports ) {
100         alias_output_port( node, &(std::get<N-1>(ports)), static_cast<string_resource_index>(FLOW_OUTPUT_PORT_0 + N - 1) );
101         fgt_internal_output_alias_helper<PortsTuple, N-1>::alias_port( node, ports );
102     }
103 };
104 
105 template < typename PortsTuple >
106 struct fgt_internal_output_alias_helper<PortsTuple, 0> {
107     static void alias_port( void * /*node*/, PortsTuple &/*ports*/ ) {
108     }
109 };
110 
111 static inline void fgt_internal_create_input_port( void *node, void *p, string_resource_index name_index ) {
112     itt_make_task_group( ITT_DOMAIN_FLOW, p, FLOW_INPUT_PORT, node, FLOW_NODE, name_index );
113 }
114 
115 static inline void fgt_internal_create_output_port( void* codeptr, void *node, void *p, string_resource_index name_index ) {
116     itt_make_task_group(ITT_DOMAIN_FLOW, p, FLOW_OUTPUT_PORT, node, FLOW_NODE, name_index);
117     suppress_unused_warning( codeptr );
118 #if __TBB_FLOW_TRACE_CODEPTR
119     if (codeptr != nullptr) {
120         register_node_addr(ITT_DOMAIN_FLOW, node, FLOW_NODE, CODE_ADDRESS, &codeptr);
121     }
122 #endif
123 }
124 
125 template<typename InputType>
126 void register_input_port(void *node, receiver<InputType>* port, string_resource_index name_index) {
127     // TODO: Make fgt_internal_create_input_port a function template?
128     fgt_internal_create_input_port(node, static_cast<void*>(port), name_index);
129 }
130 
131 template < typename PortsTuple, int N >
132 struct fgt_internal_input_helper {
133     static void register_port( void *node, PortsTuple &ports ) {
134         register_input_port( node, &(std::get<N-1>(ports)), static_cast<string_resource_index>(FLOW_INPUT_PORT_0 + N - 1) );
135         fgt_internal_input_helper<PortsTuple, N-1>::register_port( node, ports );
136     }
137 };
138 
139 template < typename PortsTuple >
140 struct fgt_internal_input_helper<PortsTuple, 1> {
141     static void register_port( void *node, PortsTuple &ports ) {
142         register_input_port( node, &(std::get<0>(ports)), FLOW_INPUT_PORT_0 );
143     }
144 };
145 
146 template<typename OutputType>
147 void register_output_port(void* codeptr, void *node, sender<OutputType>* port, string_resource_index name_index) {
148     // TODO: Make fgt_internal_create_output_port a function template?
149     fgt_internal_create_output_port( codeptr, node, static_cast<void *>(port), name_index);
150 }
151 
152 template < typename PortsTuple, int N >
153 struct fgt_internal_output_helper {
154     static void register_port( void* codeptr, void *node, PortsTuple &ports ) {
155         register_output_port( codeptr, node, &(std::get<N-1>(ports)), static_cast<string_resource_index>(FLOW_OUTPUT_PORT_0 + N - 1) );
156         fgt_internal_output_helper<PortsTuple, N-1>::register_port( codeptr, node, ports );
157     }
158 };
159 
160 template < typename PortsTuple >
161 struct fgt_internal_output_helper<PortsTuple,1> {
162     static void register_port( void* codeptr, void *node, PortsTuple &ports ) {
163         register_output_port( codeptr, node, &(std::get<0>(ports)), FLOW_OUTPUT_PORT_0 );
164     }
165 };
166 
167 template< typename NodeType >
168 void fgt_multioutput_node_desc( const NodeType *node, const char *desc ) {
169     void *addr =  (void *)( static_cast< receiver< typename NodeType::input_type > * >(const_cast< NodeType *>(node)) );
170     itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAME, desc );
171 }
172 
173 template< typename NodeType >
174 void fgt_multiinput_multioutput_node_desc( const NodeType *node, const char *desc ) {
175     void *addr =  const_cast<NodeType *>(node);
176     itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAME, desc );
177 }
178 
179 template< typename NodeType >
180 static inline void fgt_node_desc( const NodeType *node, const char *desc ) {
181     void *addr =  (void *)( static_cast< sender< typename NodeType::output_type > * >(const_cast< NodeType *>(node)) );
182     itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAME, desc );
183 }
184 
185 static inline void fgt_graph_desc( const void *g, const char *desc ) {
186     void *addr = const_cast< void *>(g);
187     itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_GRAPH, FLOW_OBJECT_NAME, desc );
188 }
189 
190 static inline void fgt_body( void *node, void *body ) {
191     itt_relation_add( ITT_DOMAIN_FLOW, body, FLOW_BODY, __itt_relation_is_child_of, node, FLOW_NODE );
192 }
193 
194 template< int N, typename PortsTuple >
195 static inline void fgt_multioutput_node(void* codeptr, string_resource_index t, void *g, void *input_port, PortsTuple &ports ) {
196     itt_make_task_group( ITT_DOMAIN_FLOW, input_port, FLOW_NODE, g, FLOW_GRAPH, t );
197     fgt_internal_create_input_port( input_port, input_port, FLOW_INPUT_PORT_0 );
198     fgt_internal_output_helper<PortsTuple, N>::register_port(codeptr, input_port, ports );
199 }
200 
201 template< int N, typename PortsTuple >
202 static inline void fgt_multioutput_node_with_body( void* codeptr, string_resource_index t, void *g, void *input_port, PortsTuple &ports, void *body ) {
203     itt_make_task_group( ITT_DOMAIN_FLOW, input_port, FLOW_NODE, g, FLOW_GRAPH, t );
204     fgt_internal_create_input_port( input_port, input_port, FLOW_INPUT_PORT_0 );
205     fgt_internal_output_helper<PortsTuple, N>::register_port( codeptr, input_port, ports );
206     fgt_body( input_port, body );
207 }
208 
209 template< int N, typename PortsTuple >
210 static inline void fgt_multiinput_node( void* codeptr, string_resource_index t, void *g, PortsTuple &ports, void *output_port) {
211     itt_make_task_group( ITT_DOMAIN_FLOW, output_port, FLOW_NODE, g, FLOW_GRAPH, t );
212     fgt_internal_create_output_port( codeptr, output_port, output_port, FLOW_OUTPUT_PORT_0 );
213     fgt_internal_input_helper<PortsTuple, N>::register_port( output_port, ports );
214 }
215 
216 static inline void fgt_multiinput_multioutput_node( void* codeptr, string_resource_index t, void *n, void *g ) {
217     itt_make_task_group( ITT_DOMAIN_FLOW, n, FLOW_NODE, g, FLOW_GRAPH, t );
218     suppress_unused_warning( codeptr );
219 #if __TBB_FLOW_TRACE_CODEPTR
220     if (codeptr != nullptr) {
221         register_node_addr(ITT_DOMAIN_FLOW, n, FLOW_NODE, CODE_ADDRESS, &codeptr);
222     }
223 #endif
224 }
225 
226 static inline void fgt_node( void* codeptr, string_resource_index t, void *g, void *output_port ) {
227     itt_make_task_group( ITT_DOMAIN_FLOW, output_port, FLOW_NODE, g, FLOW_GRAPH, t );
228     fgt_internal_create_output_port( codeptr, output_port, output_port, FLOW_OUTPUT_PORT_0 );
229 }
230 
231 static void fgt_node_with_body( void* codeptr, string_resource_index t, void *g, void *output_port, void *body ) {
232     itt_make_task_group( ITT_DOMAIN_FLOW, output_port, FLOW_NODE, g, FLOW_GRAPH, t );
233     fgt_internal_create_output_port(codeptr, output_port, output_port, FLOW_OUTPUT_PORT_0 );
234     fgt_body( output_port, body );
235 }
236 
237 static inline void fgt_node( void* codeptr, string_resource_index t, void *g, void *input_port, void *output_port ) {
238     fgt_node( codeptr, t, g, output_port );
239     fgt_internal_create_input_port( output_port, input_port, FLOW_INPUT_PORT_0 );
240 }
241 
242 static inline void  fgt_node_with_body( void* codeptr, string_resource_index t, void *g, void *input_port, void *output_port, void *body ) {
243     fgt_node_with_body( codeptr, t, g, output_port, body );
244     fgt_internal_create_input_port( output_port, input_port, FLOW_INPUT_PORT_0 );
245 }
246 
247 
248 static inline void  fgt_node( void* codeptr, string_resource_index t, void *g, void *input_port, void *decrement_port, void *output_port ) {
249     fgt_node( codeptr, t, g, input_port, output_port );
250     fgt_internal_create_input_port( output_port, decrement_port, FLOW_INPUT_PORT_1 );
251 }
252 
253 static inline void fgt_make_edge( void *output_port, void *input_port ) {
254     itt_relation_add( ITT_DOMAIN_FLOW, output_port, FLOW_OUTPUT_PORT, __itt_relation_is_predecessor_to, input_port, FLOW_INPUT_PORT);
255 }
256 
257 static inline void fgt_remove_edge( void *output_port, void *input_port ) {
258     itt_relation_add( ITT_DOMAIN_FLOW, output_port, FLOW_OUTPUT_PORT, __itt_relation_is_sibling_of, input_port, FLOW_INPUT_PORT);
259 }
260 
261 static inline void fgt_graph( void *g ) {
262     itt_make_task_group( ITT_DOMAIN_FLOW, g, FLOW_GRAPH, nullptr, FLOW_NULL, FLOW_GRAPH );
263 }
264 
265 static inline void fgt_begin_body( void *body ) {
266     itt_task_begin( ITT_DOMAIN_FLOW, body, FLOW_BODY, nullptr, FLOW_NULL, FLOW_BODY );
267 }
268 
269 static inline void fgt_end_body( void * ) {
270     itt_task_end( ITT_DOMAIN_FLOW );
271 }
272 
273 static inline void fgt_async_try_put_begin( void *node, void *port ) {
274     itt_task_begin( ITT_DOMAIN_FLOW, port, FLOW_OUTPUT_PORT, node, FLOW_NODE, FLOW_OUTPUT_PORT );
275 }
276 
277 static inline void fgt_async_try_put_end( void *, void * ) {
278     itt_task_end( ITT_DOMAIN_FLOW );
279 }
280 
281 static inline void fgt_async_reserve( void *node, void *graph ) {
282     itt_region_begin( ITT_DOMAIN_FLOW, node, FLOW_NODE, graph, FLOW_GRAPH, FLOW_NULL );
283 }
284 
285 static inline void fgt_async_commit( void *node, void * /*graph*/) {
286     itt_region_end( ITT_DOMAIN_FLOW, node, FLOW_NODE );
287 }
288 
289 static inline void fgt_reserve_wait( void *graph ) {
290     itt_region_begin( ITT_DOMAIN_FLOW, graph, FLOW_GRAPH, nullptr, FLOW_NULL, FLOW_NULL );
291 }
292 
293 static inline void fgt_release_wait( void *graph ) {
294     itt_region_end( ITT_DOMAIN_FLOW, graph, FLOW_GRAPH );
295 }
296 
297 #else // TBB_USE_PROFILING_TOOLS
298 
299 #define CODEPTR() nullptr
300 
301 static inline void fgt_alias_port(void * /*node*/, void * /*p*/, bool /*visible*/ ) { }
302 
303 static inline void fgt_composite ( void* /*codeptr*/, void * /*node*/, void * /*graph*/ ) { }
304 
305 static inline void fgt_graph( void * /*g*/ ) { }
306 
307 template< typename NodeType >
308 static inline void fgt_multioutput_node_desc( const NodeType * /*node*/, const char * /*desc*/ ) { }
309 
310 template< typename NodeType >
311 static inline void fgt_node_desc( const NodeType * /*node*/, const char * /*desc*/ ) { }
312 
313 static inline void fgt_graph_desc( const void * /*g*/, const char * /*desc*/ ) { }
314 
315 template< int N, typename PortsTuple >
316 static inline void fgt_multioutput_node( void* /*codeptr*/, string_resource_index /*t*/, void * /*g*/, void * /*input_port*/, PortsTuple & /*ports*/ ) { }
317 
318 template< int N, typename PortsTuple >
319 static inline void fgt_multioutput_node_with_body( void* /*codeptr*/, string_resource_index /*t*/, void * /*g*/, void * /*input_port*/, PortsTuple & /*ports*/, void * /*body*/ ) { }
320 
321 template< int N, typename PortsTuple >
322 static inline void fgt_multiinput_node( void* /*codeptr*/, string_resource_index /*t*/, void * /*g*/, PortsTuple & /*ports*/, void * /*output_port*/ ) { }
323 
324 static inline void fgt_multiinput_multioutput_node( void* /*codeptr*/, string_resource_index /*t*/, void * /*node*/, void * /*graph*/ ) { }
325 
326 static inline void fgt_node( void* /*codeptr*/, string_resource_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*output_port*/ ) { }
327 static inline void  fgt_node( void* /*codeptr*/, string_resource_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*decrement_port*/, void * /*output_port*/ ) { }
328 
329 static inline void fgt_node_with_body( void* /*codeptr*/, string_resource_index /*t*/, void * /*g*/, void * /*output_port*/, void * /*body*/ ) { }
330 static inline void fgt_node_with_body( void* /*codeptr*/, string_resource_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*output_port*/, void * /*body*/ ) { }
331 
332 static inline void fgt_make_edge( void * /*output_port*/, void * /*input_port*/ ) { }
333 static inline void fgt_remove_edge( void * /*output_port*/, void * /*input_port*/ ) { }
334 
335 static inline void fgt_begin_body( void * /*body*/ ) { }
336 static inline void fgt_end_body( void *  /*body*/) { }
337 
338 static inline void fgt_async_try_put_begin( void * /*node*/, void * /*port*/ ) { }
339 static inline void fgt_async_try_put_end( void * /*node*/ , void * /*port*/ ) { }
340 static inline void fgt_async_reserve( void * /*node*/, void * /*graph*/ ) { }
341 static inline void fgt_async_commit( void * /*node*/, void * /*graph*/ ) { }
342 static inline void fgt_reserve_wait( void * /*graph*/ ) { }
343 static inline void fgt_release_wait( void * /*graph*/ ) { }
344 
345 template< typename NodeType >
346 void fgt_multiinput_multioutput_node_desc( const NodeType * /*node*/, const char * /*desc*/ ) { }
347 
348 template < typename PortsTuple, int N >
349 struct fgt_internal_input_alias_helper {
350     static void alias_port( void * /*node*/, PortsTuple & /*ports*/ ) { }
351 };
352 
353 template < typename PortsTuple, int N >
354 struct fgt_internal_output_alias_helper {
355     static void alias_port( void * /*node*/, PortsTuple & /*ports*/ ) { }
356 };
357 
358 #endif // TBB_USE_PROFILING_TOOLS
359 
360 } // d1
361 } // namespace detail
362 } // namespace tbb
363 
364 #endif // _FGT_GRAPH_TRACE_IMPL_H
365