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 #include "oneapi/tbb/detail/_config.h"
18 #include "oneapi/tbb/detail/_template_helpers.h"
19
20 #include "main.h"
21 #include "itt_notify.h"
22
23 #include "oneapi/tbb/profiling.h"
24
25 #include <string.h>
26
27 namespace tbb {
28 namespace detail {
29 namespace r1 {
30
31 #if __TBB_USE_ITT_NOTIFY
32 bool ITT_Present;
33 static std::atomic<bool> ITT_InitializationDone;
34
35 static __itt_domain *tbb_domains[d1::ITT_NUM_DOMAINS] = {};
36
37 struct resource_string {
38 const char *str;
39 __itt_string_handle *itt_str_handle;
40 };
41
42 //
43 // populate resource strings
44 //
45 #define TBB_STRING_RESOURCE( index_name, str ) { str, nullptr },
46 static resource_string strings_for_itt[] = {
47 #include "oneapi/tbb/detail/_string_resource.h"
48 { "num_resource_strings", nullptr }
49 };
50 #undef TBB_STRING_RESOURCE
51
ITT_get_string_handle(std::uintptr_t idx)52 static __itt_string_handle* ITT_get_string_handle(std::uintptr_t idx) {
53 __TBB_ASSERT(idx < NUM_STRINGS, "string handle out of valid range");
54 return idx < NUM_STRINGS ? strings_for_itt[idx].itt_str_handle : NULL;
55 }
56
ITT_init_domains()57 static void ITT_init_domains() {
58 tbb_domains[d1::ITT_DOMAIN_MAIN] = __itt_domain_create( _T("tbb") );
59 tbb_domains[d1::ITT_DOMAIN_MAIN]->flags = 1;
60 tbb_domains[d1::ITT_DOMAIN_FLOW] = __itt_domain_create( _T("tbb.flow") );
61 tbb_domains[d1::ITT_DOMAIN_FLOW]->flags = 1;
62 tbb_domains[d1::ITT_DOMAIN_ALGO] = __itt_domain_create( _T("tbb.algorithm") );
63 tbb_domains[d1::ITT_DOMAIN_ALGO]->flags = 1;
64 }
65
ITT_init_strings()66 static void ITT_init_strings() {
67 for ( std::uintptr_t i = 0; i < NUM_STRINGS; ++i ) {
68 #if _WIN32||_WIN64
69 strings_for_itt[i].itt_str_handle = __itt_string_handle_createA( strings_for_itt[i].str );
70 #else
71 strings_for_itt[i].itt_str_handle = __itt_string_handle_create( strings_for_itt[i].str );
72 #endif
73 }
74 }
75
ITT_init()76 static void ITT_init() {
77 ITT_init_domains();
78 ITT_init_strings();
79 }
80
81 /** Thread-unsafe lazy one-time initialization of tools interop.
82 Used by both dummy handlers and general TBB one-time initialization routine. **/
ITT_DoUnsafeOneTimeInitialization()83 void ITT_DoUnsafeOneTimeInitialization () {
84 // Double check ITT_InitializationDone is necessary because the first check
85 // in ITT_DoOneTimeInitialization is not guarded with the __TBB_InitOnce lock.
86 if ( !ITT_InitializationDone ) {
87 ITT_Present = (__TBB_load_ittnotify()!=0);
88 if (ITT_Present) ITT_init();
89 ITT_InitializationDone = true;
90 }
91 }
92
93 /** Thread-safe lazy one-time initialization of tools interop.
94 Used by dummy handlers only. **/
95 extern "C"
ITT_DoOneTimeInitialization()96 void ITT_DoOneTimeInitialization() {
97 if ( !ITT_InitializationDone ) {
98 __TBB_InitOnce::lock();
99 ITT_DoUnsafeOneTimeInitialization();
100 __TBB_InitOnce::unlock();
101 }
102 }
103
create_itt_sync(void * ptr,const tchar * objtype,const tchar * objname)104 void create_itt_sync(void* ptr, const tchar* objtype, const tchar* objname) {
105 ITT_SYNC_CREATE(ptr, objtype, objname);
106 }
107
call_itt_notify(int t,void * ptr)108 void call_itt_notify(int t, void *ptr) {
109 switch (t) {
110 case 0: ITT_NOTIFY(sync_prepare, ptr); break;
111 case 1: ITT_NOTIFY(sync_cancel, ptr); break;
112 case 2: ITT_NOTIFY(sync_acquired, ptr); break;
113 case 3: ITT_NOTIFY(sync_releasing, ptr); break;
114 case 4: ITT_NOTIFY(sync_destroy, ptr); break;
115 }
116 }
117
itt_set_sync_name(void * obj,const tchar * name)118 void itt_set_sync_name(void* obj, const tchar* name) {
119 __itt_sync_rename(obj, name);
120 }
121
122 const __itt_id itt_null_id = { 0, 0, 0 };
123
get_itt_domain(d1::itt_domain_enum idx)124 static inline __itt_domain* get_itt_domain(d1::itt_domain_enum idx) {
125 if (tbb_domains[idx] == NULL) {
126 ITT_DoOneTimeInitialization();
127 }
128 return tbb_domains[idx];
129 }
130
itt_id_make(__itt_id * id,void * addr,unsigned long long extra)131 static inline void itt_id_make(__itt_id* id, void* addr, unsigned long long extra) {
132 *id = __itt_id_make(addr, extra);
133 }
134
itt_id_create(const __itt_domain * domain,__itt_id id)135 static inline void itt_id_create(const __itt_domain* domain, __itt_id id) {
136 __itt_id_create(domain, id);
137 }
138
itt_make_task_group(d1::itt_domain_enum domain,void * group,unsigned long long group_extra,void * parent,unsigned long long parent_extra,string_resource_index name_index)139 void itt_make_task_group(d1::itt_domain_enum domain, void* group, unsigned long long group_extra,
140 void* parent, unsigned long long parent_extra, string_resource_index name_index) {
141 if (__itt_domain* d = get_itt_domain(domain)) {
142 __itt_id group_id = itt_null_id;
143 __itt_id parent_id = itt_null_id;
144 itt_id_make(&group_id, group, group_extra);
145 itt_id_create(d, group_id);
146 if (parent) {
147 itt_id_make(&parent_id, parent, parent_extra);
148 }
149 __itt_string_handle* n = ITT_get_string_handle(name_index);
150 __itt_task_group(d, group_id, parent_id, n);
151 }
152 }
153
itt_metadata_str_add(d1::itt_domain_enum domain,void * addr,unsigned long long addr_extra,string_resource_index key,const char * value)154 void __TBB_EXPORTED_FUNC itt_metadata_str_add(d1::itt_domain_enum domain, void *addr, unsigned long long addr_extra,
155 string_resource_index key, const char *value ) {
156 if ( __itt_domain *d = get_itt_domain( domain ) ) {
157 __itt_id id = itt_null_id;
158 itt_id_make( &id, addr, addr_extra );
159 __itt_string_handle *k = ITT_get_string_handle(key);
160 size_t value_length = strlen( value );
161 #if _WIN32||_WIN64
162 __itt_metadata_str_addA(d, id, k, value, value_length);
163 #else
164 __itt_metadata_str_add(d, id, k, value, value_length);
165 #endif
166 }
167 }
168
itt_metadata_ptr_add(d1::itt_domain_enum domain,void * addr,unsigned long long addr_extra,string_resource_index key,void * value)169 void __TBB_EXPORTED_FUNC itt_metadata_ptr_add(d1::itt_domain_enum domain, void *addr, unsigned long long addr_extra,
170 string_resource_index key, void *value ) {
171 if ( __itt_domain *d = get_itt_domain( domain ) ) {
172 __itt_id id = itt_null_id;
173 itt_id_make( &id, addr, addr_extra );
174 __itt_string_handle *k = ITT_get_string_handle(key);
175 #if __TBB_x86_32
176 __itt_metadata_add(d, id, k, __itt_metadata_u32, 1, value);
177 #else
178 __itt_metadata_add(d, id, k, __itt_metadata_u64, 1, value);
179 #endif
180 }
181 }
182
itt_relation_add(d1::itt_domain_enum domain,void * addr0,unsigned long long addr0_extra,itt_relation relation,void * addr1,unsigned long long addr1_extra)183 void __TBB_EXPORTED_FUNC itt_relation_add(d1::itt_domain_enum domain, void *addr0, unsigned long long addr0_extra,
184 itt_relation relation, void *addr1, unsigned long long addr1_extra ) {
185 if ( __itt_domain *d = get_itt_domain( domain ) ) {
186 __itt_id id0 = itt_null_id;
187 __itt_id id1 = itt_null_id;
188 itt_id_make( &id0, addr0, addr0_extra );
189 itt_id_make( &id1, addr1, addr1_extra );
190 __itt_relation_add( d, id0, (__itt_relation)relation, id1 );
191 }
192 }
193
itt_task_begin(d1::itt_domain_enum domain,void * task,unsigned long long task_extra,void * parent,unsigned long long parent_extra,string_resource_index name_index)194 void __TBB_EXPORTED_FUNC itt_task_begin(d1::itt_domain_enum domain, void* task, unsigned long long task_extra,
195 void* parent, unsigned long long parent_extra, string_resource_index name_index) {
196 if (__itt_domain* d = get_itt_domain(domain)) {
197 __itt_id task_id = itt_null_id;
198 __itt_id parent_id = itt_null_id;
199 if (task) {
200 itt_id_make(&task_id, task, task_extra);
201 }
202 if (parent) {
203 itt_id_make(&parent_id, parent, parent_extra);
204 }
205 __itt_string_handle* n = ITT_get_string_handle(name_index);
206 __itt_task_begin(d, task_id, parent_id, n);
207 }
208 }
209
itt_task_end(d1::itt_domain_enum domain)210 void __TBB_EXPORTED_FUNC itt_task_end(d1::itt_domain_enum domain) {
211 if (__itt_domain* d = get_itt_domain(domain)) {
212 __itt_task_end(d);
213 }
214 }
215
itt_region_begin(d1::itt_domain_enum domain,void * region,unsigned long long region_extra,void * parent,unsigned long long parent_extra,string_resource_index)216 void __TBB_EXPORTED_FUNC itt_region_begin(d1::itt_domain_enum domain, void *region, unsigned long long region_extra,
217 void *parent, unsigned long long parent_extra, string_resource_index /* name_index */ ) {
218 if ( __itt_domain *d = get_itt_domain( domain ) ) {
219 __itt_id region_id = itt_null_id;
220 __itt_id parent_id = itt_null_id;
221 itt_id_make( ®ion_id, region, region_extra );
222 if ( parent ) {
223 itt_id_make( &parent_id, parent, parent_extra );
224 }
225 __itt_region_begin( d, region_id, parent_id, NULL );
226 }
227 }
228
itt_region_end(d1::itt_domain_enum domain,void * region,unsigned long long region_extra)229 void __TBB_EXPORTED_FUNC itt_region_end(d1::itt_domain_enum domain, void *region, unsigned long long region_extra ) {
230 if ( __itt_domain *d = get_itt_domain( domain ) ) {
231 __itt_id region_id = itt_null_id;
232 itt_id_make( ®ion_id, region, region_extra );
233 __itt_region_end( d, region_id );
234 }
235 }
236
237 #else
238 void create_itt_sync(void* /*ptr*/, const tchar* /*objtype*/, const tchar* /*objname*/) {}
239 void call_itt_notify(int /*t*/, void* /*ptr*/) {}
240 void itt_set_sync_name(void* /*obj*/, const tchar* /*name*/) {}
241 void itt_make_task_group(d1::itt_domain_enum /*domain*/, void* /*group*/, unsigned long long /*group_extra*/,
242 void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/) {}
243 void itt_metadata_str_add(d1::itt_domain_enum /*domain*/, void* /*addr*/, unsigned long long /*addr_extra*/,
244 string_resource_index /*key*/, const char* /*value*/ ) { }
245 void itt_metadata_ptr_add(d1::itt_domain_enum /*domain*/, void * /*addr*/, unsigned long long /*addr_extra*/,
246 string_resource_index /*key*/, void * /*value*/ ) {}
247 void itt_relation_add(d1::itt_domain_enum /*domain*/, void* /*addr0*/, unsigned long long /*addr0_extra*/,
248 itt_relation /*relation*/, void* /*addr1*/, unsigned long long /*addr1_extra*/ ) { }
249 void itt_task_begin(d1::itt_domain_enum /*domain*/, void* /*task*/, unsigned long long /*task_extra*/,
250 void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/ ) { }
251 void itt_task_end(d1::itt_domain_enum /*domain*/ ) { }
252 void itt_region_begin(d1::itt_domain_enum /*domain*/, void* /*region*/, unsigned long long /*region_extra*/,
253 void* /*parent*/, unsigned long long /*parent_extra*/, string_resource_index /*name_index*/ ) { }
254 void itt_region_end(d1::itt_domain_enum /*domain*/, void* /*region*/, unsigned long long /*region_extra*/ ) { }
255 #endif /* __TBB_USE_ITT_NOTIFY */
256
257 const tchar
258 *SyncType_Scheduler = _T("%Constant")
259 ;
260 const tchar
261 *SyncObj_ContextsList = _T("TBB Scheduler")
262 ;
263 } // namespace r1
264 } // namespace detail
265 } // namespace tbb
266