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