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
25namespace tbb {
26namespace detail {
27inline 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
65namespace tbb {
66namespace detail {
67namespace 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
72namespace 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
92namespace 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 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
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
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
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
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
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 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
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
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)
198class 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
210public:
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:
226struct 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
237namespace profiling {
238 using detail::d1::event;
239}
240} // namespace tbb
241
242
243#endif /* __TBB_profiling_H */
244

source code of include/oneapi/tbb/profiling.h