xref: /oneTBB/include/tbb/profiling.h (revision 51c0b2f7)
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