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( &region_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( &region_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