1 /*
2     Copyright (c) 2005-2020 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 "ittnotify_config.h"
18 
19 #if ITT_PLATFORM==ITT_PLATFORM_WIN
20 #define PATH_MAX 512
21 #else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
22 #include <limits.h>
23 #include <dlfcn.h>
24 #include <errno.h>
25 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <string.h>
30 
31 #define INTEL_NO_MACRO_BODY
32 #define INTEL_ITTNOTIFY_API_PRIVATE
33 #include "ittnotify.h"
34 #include "legacy/ittnotify.h"
35 
36 #include "disable_warnings.h"
37 
38 static const char api_version[] = API_VERSION "\0\n@(#) $Revision$\n";
39 
40 #define _N_(n) ITT_JOIN(INTEL_ITTNOTIFY_PREFIX,n)
41 
42 #if ITT_OS==ITT_OS_WIN
43 static const char* ittnotify_lib_name = "libittnotify.dll";
44 #elif ITT_OS==ITT_OS_LINUX || ITT_OS==ITT_OS_FREEBSD
45 static const char* ittnotify_lib_name = "libittnotify.so";
46 #elif ITT_OS==ITT_OS_MAC
47 static const char* ittnotify_lib_name = "libittnotify.dylib";
48 #else
49 #error Unsupported or unknown OS.
50 #endif
51 
52 #ifdef __ANDROID__
53 #include <android/log.h>
54 #include <stdio.h>
55 #include <unistd.h>
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <fcntl.h>
59 #include <linux/limits.h>
60 
61 #ifdef ITT_ANDROID_LOG
62     #define ITT_ANDROID_LOG_TAG   "INTEL_VTUNE_USERAPI"
63     #define ITT_ANDROID_LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, ITT_ANDROID_LOG_TAG, __VA_ARGS__))
64     #define ITT_ANDROID_LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, ITT_ANDROID_LOG_TAG, __VA_ARGS__))
65     #define ITT_ANDROID_LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR,ITT_ANDROID_LOG_TAG, __VA_ARGS__))
66     #define ITT_ANDROID_LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG,ITT_ANDROID_LOG_TAG, __VA_ARGS__))
67 #else
68     #define ITT_ANDROID_LOGI(...)
69     #define ITT_ANDROID_LOGW(...)
70     #define ITT_ANDROID_LOGE(...)
71     #define ITT_ANDROID_LOGD(...)
72 #endif
73 
74 /* default location of userapi collector on Android */
75 #define ANDROID_ITTNOTIFY_DEFAULT_PATH_MASK(x)  "/data/data/com.intel.vtune/perfrun/lib" \
76                                                 #x "/runtime/libittnotify.so"
77 
78 #if ITT_ARCH==ITT_ARCH_IA32 || ITT_ARCH==ITT_ARCH_ARM
79 #define ANDROID_ITTNOTIFY_DEFAULT_PATH  ANDROID_ITTNOTIFY_DEFAULT_PATH_MASK(32)
80 #else
81 #define ANDROID_ITTNOTIFY_DEFAULT_PATH  ANDROID_ITTNOTIFY_DEFAULT_PATH_MASK(64)
82 #endif
83 
84 #endif
85 
86 
87 #ifndef LIB_VAR_NAME
88 #if ITT_ARCH==ITT_ARCH_IA32 || ITT_ARCH==ITT_ARCH_ARM
89 #define LIB_VAR_NAME INTEL_LIBITTNOTIFY32
90 #else
91 #define LIB_VAR_NAME INTEL_LIBITTNOTIFY64
92 #endif
93 #endif /* LIB_VAR_NAME */
94 
95 #define ITT_MUTEX_INIT_AND_LOCK(p) {                                 \
96     if (PTHREAD_SYMBOLS)                                             \
97     {                                                                \
98         if (!p.mutex_initialized)                                    \
99         {                                                            \
100             if (__itt_interlocked_increment(&p.atomic_counter) == 1) \
101             {                                                        \
102                 __itt_mutex_init(&p.mutex);                          \
103                 p.mutex_initialized = 1;                             \
104             }                                                        \
105             else                                                     \
106                 while (!p.mutex_initialized)                         \
107                     __itt_thread_yield();                            \
108         }                                                            \
109         __itt_mutex_lock(&p.mutex);                                  \
110     }                                                                \
111 }
112 
113 const int _N_(err) = 0;
114 
115 typedef int (__itt_init_ittlib_t)(const char*, __itt_group_id);
116 
117 /* this define used to control initialization function name. */
118 #ifndef __itt_init_ittlib_name
119 ITT_EXTERN_C int _N_(init_ittlib)(const char*, __itt_group_id);
120 static __itt_init_ittlib_t* __itt_init_ittlib_ptr = _N_(init_ittlib);
121 #define __itt_init_ittlib_name __itt_init_ittlib_ptr
122 #endif /* __itt_init_ittlib_name */
123 
124 typedef void (__itt_fini_ittlib_t)(void);
125 
126 /* this define used to control finalization function name. */
127 #ifndef __itt_fini_ittlib_name
128 ITT_EXTERN_C void _N_(fini_ittlib)(void);
129 static __itt_fini_ittlib_t* __itt_fini_ittlib_ptr = _N_(fini_ittlib);
130 #define __itt_fini_ittlib_name __itt_fini_ittlib_ptr
131 #endif /* __itt_fini_ittlib_name */
132 
133 extern __itt_global _N_(_ittapi_global);
134 
135 /* building pointers to imported funcs */
136 #undef ITT_STUBV
137 #undef ITT_STUB
138 #define ITT_STUB(api,type,name,args,params,ptr,group,format)   \
139 static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args;\
140 typedef type api ITT_JOIN(_N_(name),_t) args;                  \
141 ITT_EXTERN_C_BEGIN ITT_JOIN(_N_(name),_t)* ITTNOTIFY_NAME(name) = ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)); ITT_EXTERN_C_END \
142 static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args \
143 {                                                              \
144     if (!_N_(_ittapi_global).api_initialized && _N_(_ittapi_global).thread_list == NULL) \
145         __itt_init_ittlib_name(NULL, __itt_group_all);         \
146     if (ITTNOTIFY_NAME(name) && ITTNOTIFY_NAME(name) != ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init))) \
147         return ITTNOTIFY_NAME(name) params;                    \
148     else                                                       \
149         return (type)0;                                        \
150 }
151 
152 #define ITT_STUBV(api,type,name,args,params,ptr,group,format)  \
153 static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args;\
154 typedef type api ITT_JOIN(_N_(name),_t) args;                  \
155 ITT_EXTERN_C_BEGIN ITT_JOIN(_N_(name),_t)* ITTNOTIFY_NAME(name) = ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)); ITT_EXTERN_C_END \
156 static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args \
157 {                                                              \
158     if (!_N_(_ittapi_global).api_initialized && _N_(_ittapi_global).thread_list == NULL) \
159         __itt_init_ittlib_name(NULL, __itt_group_all);         \
160     if (ITTNOTIFY_NAME(name) && ITTNOTIFY_NAME(name) != ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init))) \
161         ITTNOTIFY_NAME(name) params;                           \
162     else                                                       \
163         return;                                                \
164 }
165 
166 #undef __ITT_INTERNAL_INIT
167 #include "ittnotify_static.h"
168 
169 #undef ITT_STUB
170 #undef ITT_STUBV
171 #define ITT_STUB(api,type,name,args,params,ptr,group,format)   \
172 static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args;\
173 typedef type api ITT_JOIN(_N_(name),_t) args;                  \
174 ITT_EXTERN_C_BEGIN ITT_JOIN(_N_(name),_t)* ITTNOTIFY_NAME(name) = ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)); ITT_EXTERN_C_END
175 
176 #define ITT_STUBV(api,type,name,args,params,ptr,group,format)  \
177 static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args;\
178 typedef type api ITT_JOIN(_N_(name),_t) args;                  \
179 ITT_EXTERN_C_BEGIN ITT_JOIN(_N_(name),_t)* ITTNOTIFY_NAME(name) = ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)); ITT_EXTERN_C_END
180 
181 #define __ITT_INTERNAL_INIT
182 #include "ittnotify_static.h"
183 #undef __ITT_INTERNAL_INIT
184 
185 ITT_GROUP_LIST(group_list);
186 
187 #pragma pack(push, 8)
188 
189 typedef struct ___itt_group_alias
190 {
191     const char*    env_var;
192     __itt_group_id groups;
193 } __itt_group_alias;
194 
195 static __itt_group_alias group_alias[] = {
196     { "KMP_FOR_TPROFILE", (__itt_group_id)(__itt_group_control | __itt_group_thread | __itt_group_sync  | __itt_group_mark) },
197     { "KMP_FOR_TCHECK",   (__itt_group_id)(__itt_group_control | __itt_group_thread | __itt_group_sync  | __itt_group_fsync | __itt_group_mark | __itt_group_suppress) },
198     { NULL,               (__itt_group_none) },
199     { api_version,        (__itt_group_none) } /* !!! Just to avoid unused code elimination !!! */
200 };
201 
202 #pragma pack(pop)
203 
204 #if ITT_PLATFORM==ITT_PLATFORM_WIN
205 #pragma warning(push)
206 #pragma warning(disable: 4054) /* warning C4054: 'type cast' : from function pointer 'XXX' to data pointer 'void *' */
207 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
208 
209 static __itt_api_info api_list[] = {
210 /* Define functions with static implementation */
211 #undef ITT_STUB
212 #undef ITT_STUBV
213 #define ITT_STUB(api,type,name,args,params,nameindll,group,format) { ITT_TO_STR(ITT_JOIN(__itt_,nameindll)), (void**)(void*)&ITTNOTIFY_NAME(name), (void*)(size_t)&ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)), (void*)(size_t)&ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)), (__itt_group_id)(group)},
214 #define ITT_STUBV ITT_STUB
215 #define __ITT_INTERNAL_INIT
216 #include "ittnotify_static.h"
217 #undef __ITT_INTERNAL_INIT
218 /* Define functions without static implementation */
219 #undef ITT_STUB
220 #undef ITT_STUBV
221 #define ITT_STUB(api,type,name,args,params,nameindll,group,format) {ITT_TO_STR(ITT_JOIN(__itt_,nameindll)), (void**)(void*)&ITTNOTIFY_NAME(name), (void*)(size_t)&ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)), NULL, (__itt_group_id)(group)},
222 #define ITT_STUBV ITT_STUB
223 #include "ittnotify_static.h"
224     {NULL, NULL, NULL, NULL, __itt_group_none}
225 };
226 
227 #if ITT_PLATFORM==ITT_PLATFORM_WIN
228 #pragma warning(pop)
229 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
230 
231 static const char dll_path[PATH_MAX] = { 0 };
232 
233 /* static part descriptor which handles. all notification api attributes. */
234 __itt_global _N_(_ittapi_global) = {
235     ITT_MAGIC,                                     /* identification info */
236     ITT_MAJOR, ITT_MINOR, API_VERSION_BUILD,       /* version info */
237     0,                                             /* api_initialized */
238     0,                                             /* mutex_initialized */
239     0,                                             /* atomic_counter */
240     MUTEX_INITIALIZER,                             /* mutex */
241     NULL,                                          /* dynamic library handle */
242     NULL,                                          /* error_handler */
243     (const char**)&dll_path,                       /* dll_path_ptr */
244     (__itt_api_info*)&api_list,                    /* api_list_ptr */
245     NULL,                                          /* next __itt_global */
246     NULL,                                          /* thread_list */
247     NULL,                                          /* domain_list */
248     NULL,                                          /* string_list */
249     __itt_collection_normal,                       /* collection state */
250     NULL,                                          /* counter_list */
251     0                                              /* ipt_collect_events */
252 };
253 
254 typedef void (__itt_api_init_t)(__itt_global*, __itt_group_id);
255 typedef void (__itt_api_fini_t)(__itt_global*);
256 
257 /* ========================================================================= */
258 
259 #ifdef ITT_NOTIFY_EXT_REPORT
260 ITT_EXTERN_C void _N_(error_handler)(__itt_error_code, va_list args);
261 #endif /* ITT_NOTIFY_EXT_REPORT */
262 
263 #if ITT_PLATFORM==ITT_PLATFORM_WIN
264 #pragma warning(push)
265 #pragma warning(disable: 4055) /* warning C4055: 'type cast' : from data pointer 'void *' to function pointer 'XXX' */
266 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
267 
__itt_report_error_impl(int code,...)268 static void __itt_report_error_impl(int code, ...) {
269     va_list args;
270     va_start(args, code);
271     if (_N_(_ittapi_global).error_handler != NULL)
272     {
273         __itt_error_handler_t* handler = (__itt_error_handler_t*)(size_t)_N_(_ittapi_global).error_handler;
274         handler((__itt_error_code)code, args);
275     }
276 #ifdef ITT_NOTIFY_EXT_REPORT
277     _N_(error_handler)(code, args);
278 #endif /* ITT_NOTIFY_EXT_REPORT */
279     va_end(args);
280 }
281 
282 //va_start cannot take enum (__itt_error_code) on clang, so it is necessary to transform it to int
283 #define __itt_report_error(code, ...) \
284                 __itt_report_error_impl((int)code,__VA_ARGS__)
285 
286 
287 #if ITT_PLATFORM==ITT_PLATFORM_WIN
288 #pragma warning(pop)
289 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
290 
291 #if ITT_PLATFORM==ITT_PLATFORM_WIN
ITT_VERSIONIZE(ITT_JOIN (_N_ (domain_createW),_init))292 static __itt_domain* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(domain_createW),_init))(const wchar_t* name)
293 {
294     __itt_domain *h_tail = NULL, *h = NULL;
295 
296     if (name == NULL)
297     {
298         return NULL;
299     }
300 
301     ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
302     if (_N_(_ittapi_global).api_initialized)
303     {
304         if (ITTNOTIFY_NAME(domain_createW) && ITTNOTIFY_NAME(domain_createW) != ITT_VERSIONIZE(ITT_JOIN(_N_(domain_createW),_init)))
305         {
306             __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
307             return ITTNOTIFY_NAME(domain_createW)(name);
308         }
309     }
310     for (h_tail = NULL, h = _N_(_ittapi_global).domain_list; h != NULL; h_tail = h, h = h->next)
311     {
312         if (h->nameW != NULL && !wcscmp(h->nameW, name)) break;
313     }
314     if (h == NULL)
315     {
316         NEW_DOMAIN_W(&_N_(_ittapi_global),h,h_tail,name);
317     }
318     if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
319     return h;
320 }
321 
ITT_VERSIONIZE(ITT_JOIN (_N_ (domain_createA),_init))322 static __itt_domain* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(domain_createA),_init))(const char* name)
323 #else  /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
324 static __itt_domain* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(domain_create),_init))(const char* name)
325 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
326 {
327     __itt_domain *h_tail = NULL, *h = NULL;
328 
329     if (name == NULL)
330     {
331         return NULL;
332     }
333 
334     ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
335     if (_N_(_ittapi_global).api_initialized)
336     {
337 #if ITT_PLATFORM==ITT_PLATFORM_WIN
338         if (ITTNOTIFY_NAME(domain_createA) && ITTNOTIFY_NAME(domain_createA) != ITT_VERSIONIZE(ITT_JOIN(_N_(domain_createA),_init)))
339         {
340             __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
341             return ITTNOTIFY_NAME(domain_createA)(name);
342         }
343 #else
344         if (ITTNOTIFY_NAME(domain_create) && ITTNOTIFY_NAME(domain_create) != ITT_VERSIONIZE(ITT_JOIN(_N_(domain_create),_init)))
345         {
346             if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
347             return ITTNOTIFY_NAME(domain_create)(name);
348         }
349 #endif
350     }
351     for (h_tail = NULL, h = _N_(_ittapi_global).domain_list; h != NULL; h_tail = h, h = h->next)
352     {
353         if (h->nameA != NULL && !__itt_fstrcmp(h->nameA, name)) break;
354     }
355     if (h == NULL)
356     {
357         NEW_DOMAIN_A(&_N_(_ittapi_global),h,h_tail,name);
358     }
359     if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
360     return h;
361 }
362 
363 #if ITT_PLATFORM==ITT_PLATFORM_WIN
ITT_VERSIONIZE(ITT_JOIN (_N_ (string_handle_createW),_init))364 static __itt_string_handle* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_createW),_init))(const wchar_t* name)
365 {
366     __itt_string_handle *h_tail = NULL, *h = NULL;
367 
368     if (name == NULL)
369     {
370         return NULL;
371     }
372 
373     ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
374     if (_N_(_ittapi_global).api_initialized)
375     {
376         if (ITTNOTIFY_NAME(string_handle_createW) && ITTNOTIFY_NAME(string_handle_createW) != ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_createW),_init)))
377         {
378             __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
379             return ITTNOTIFY_NAME(string_handle_createW)(name);
380         }
381     }
382     for (h_tail = NULL, h = _N_(_ittapi_global).string_list; h != NULL; h_tail = h, h = h->next)
383     {
384         if (h->strW != NULL && !wcscmp(h->strW, name)) break;
385     }
386     if (h == NULL)
387     {
388         NEW_STRING_HANDLE_W(&_N_(_ittapi_global),h,h_tail,name);
389     }
390     __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
391     return h;
392 }
393 
ITT_VERSIONIZE(ITT_JOIN (_N_ (string_handle_createA),_init))394 static __itt_string_handle* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_createA),_init))(const char* name)
395 #else  /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
396 static __itt_string_handle* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_create),_init))(const char* name)
397 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
398 {
399     __itt_string_handle *h_tail = NULL, *h = NULL;
400 
401     if (name == NULL)
402     {
403         return NULL;
404     }
405 
406     ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
407     if (_N_(_ittapi_global).api_initialized)
408     {
409 #if ITT_PLATFORM==ITT_PLATFORM_WIN
410         if (ITTNOTIFY_NAME(string_handle_createA) && ITTNOTIFY_NAME(string_handle_createA) != ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_createA),_init)))
411         {
412             __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
413             return ITTNOTIFY_NAME(string_handle_createA)(name);
414         }
415 #else
416         if (ITTNOTIFY_NAME(string_handle_create) && ITTNOTIFY_NAME(string_handle_create) != ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_create),_init)))
417         {
418             if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
419             return ITTNOTIFY_NAME(string_handle_create)(name);
420         }
421 #endif
422     }
423     for (h_tail = NULL, h = _N_(_ittapi_global).string_list; h != NULL; h_tail = h, h = h->next)
424     {
425         if (h->strA != NULL && !__itt_fstrcmp(h->strA, name)) break;
426     }
427     if (h == NULL)
428     {
429         NEW_STRING_HANDLE_A(&_N_(_ittapi_global),h,h_tail,name);
430     }
431     if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
432     return h;
433 }
434 
435 #if ITT_PLATFORM==ITT_PLATFORM_WIN
ITT_VERSIONIZE(ITT_JOIN (_N_ (counter_createW),_init))436 static __itt_counter ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(counter_createW),_init))(const wchar_t *name, const wchar_t *domain)
437 {
438     __itt_counter_info_t *h_tail = NULL, *h = NULL;
439     __itt_metadata_type type = __itt_metadata_u64;
440 
441     if (name == NULL)
442     {
443         return NULL;
444     }
445 
446     ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
447     if (_N_(_ittapi_global).api_initialized)
448     {
449         if (ITTNOTIFY_NAME(counter_createW) && ITTNOTIFY_NAME(counter_createW) != ITT_VERSIONIZE(ITT_JOIN(_N_(counter_createW),_init)))
450         {
451             __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
452             return ITTNOTIFY_NAME(counter_createW)(name, domain);
453         }
454     }
455     for (h_tail = NULL, h = _N_(_ittapi_global).counter_list; h != NULL; h_tail = h, h = h->next)
456     {
457         if (h->nameW != NULL  && h->type == type && !wcscmp(h->nameW, name) && ((h->domainW == NULL && domain == NULL) ||
458             (h->domainW != NULL && domain != NULL && !wcscmp(h->domainW, domain)))) break;
459 
460     }
461     if (h == NULL)
462     {
463         NEW_COUNTER_W(&_N_(_ittapi_global),h,h_tail,name,domain,type);
464     }
465     __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
466     return (__itt_counter)h;
467 }
468 
ITT_VERSIONIZE(ITT_JOIN (_N_ (counter_createA),_init))469 static __itt_counter ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(counter_createA),_init))(const char *name, const char *domain)
470 #else  /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
471 static __itt_counter ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(counter_create),_init))(const char *name, const char *domain)
472 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
473 {
474     __itt_counter_info_t *h_tail = NULL, *h = NULL;
475     __itt_metadata_type type = __itt_metadata_u64;
476 
477     if (name == NULL)
478     {
479         return NULL;
480     }
481 
482     ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
483     if (_N_(_ittapi_global).api_initialized)
484     {
485 #if ITT_PLATFORM==ITT_PLATFORM_WIN
486         if (ITTNOTIFY_NAME(counter_createA) && ITTNOTIFY_NAME(counter_createA) != ITT_VERSIONIZE(ITT_JOIN(_N_(counter_createA),_init)))
487         {
488     __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
489             return ITTNOTIFY_NAME(counter_createA)(name, domain);
490         }
491 #else
492         if (ITTNOTIFY_NAME(counter_create) && ITTNOTIFY_NAME(counter_create) != ITT_VERSIONIZE(ITT_JOIN(_N_(counter_create),_init)))
493         {
494             if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
495             return ITTNOTIFY_NAME(counter_create)(name, domain);
496         }
497 #endif
498     }
499     for (h_tail = NULL, h = _N_(_ittapi_global).counter_list; h != NULL; h_tail = h, h = h->next)
500     {
501         if (h->nameA != NULL  && h->type == type && !__itt_fstrcmp(h->nameA, name) && ((h->domainA == NULL && domain == NULL) ||
502             (h->domainA != NULL && domain != NULL && !__itt_fstrcmp(h->domainA, domain)))) break;
503     }
504     if (h == NULL)
505     {
506        NEW_COUNTER_A(&_N_(_ittapi_global),h,h_tail,name,domain,type);
507     }
508     if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
509     return (__itt_counter)h;
510 }
511 
512 #if ITT_PLATFORM==ITT_PLATFORM_WIN
ITT_VERSIONIZE(ITT_JOIN (_N_ (counter_create_typedW),_init))513 static __itt_counter ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(counter_create_typedW),_init))(const wchar_t *name, const wchar_t *domain, __itt_metadata_type type)
514 {
515     __itt_counter_info_t *h_tail = NULL, *h = NULL;
516 
517     if (name == NULL)
518     {
519         return NULL;
520     }
521 
522     ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
523     if (_N_(_ittapi_global).api_initialized)
524     {
525         if (ITTNOTIFY_NAME(counter_create_typedW) && ITTNOTIFY_NAME(counter_create_typedW) != ITT_VERSIONIZE(ITT_JOIN(_N_(counter_create_typedW),_init)))
526         {
527             __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
528             return ITTNOTIFY_NAME(counter_create_typedW)(name, domain, type);
529         }
530     }
531     for (h_tail = NULL, h = _N_(_ittapi_global).counter_list; h != NULL; h_tail = h, h = h->next)
532     {
533         if (h->nameW != NULL  && h->type == type && !wcscmp(h->nameW, name) && ((h->domainW == NULL && domain == NULL) ||
534             (h->domainW != NULL && domain != NULL && !wcscmp(h->domainW, domain)))) break;
535 
536     }
537     if (h == NULL)
538     {
539         NEW_COUNTER_W(&_N_(_ittapi_global),h,h_tail,name,domain,type);
540     }
541     __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
542     return (__itt_counter)h;
543 }
544 
ITT_VERSIONIZE(ITT_JOIN (_N_ (counter_create_typedA),_init))545 static __itt_counter ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(counter_create_typedA),_init))(const char *name, const char *domain, __itt_metadata_type type)
546 #else  /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
547 static __itt_counter ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(counter_create_typed),_init))(const char *name, const char *domain, __itt_metadata_type type)
548 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
549 {
550     __itt_counter_info_t *h_tail = NULL, *h = NULL;
551 
552     if (name == NULL)
553     {
554         return NULL;
555     }
556 
557     ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
558     if (_N_(_ittapi_global).api_initialized)
559     {
560 #if ITT_PLATFORM==ITT_PLATFORM_WIN
561         if (ITTNOTIFY_NAME(counter_create_typedA) && ITTNOTIFY_NAME(counter_create_typedA) != ITT_VERSIONIZE(ITT_JOIN(_N_(counter_create_typedA),_init)))
562         {
563             __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
564             return ITTNOTIFY_NAME(counter_create_typedA)(name, domain, type);
565         }
566 #else
567         if (ITTNOTIFY_NAME(counter_create_typed) && ITTNOTIFY_NAME(counter_create_typed) != ITT_VERSIONIZE(ITT_JOIN(_N_(counter_create_typed),_init)))
568         {
569             if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
570             return ITTNOTIFY_NAME(counter_create_typed)(name, domain, type);
571         }
572 #endif
573     }
574     for (h_tail = NULL, h = _N_(_ittapi_global).counter_list; h != NULL; h_tail = h, h = h->next)
575     {
576         if (h->nameA != NULL  && h->type == type && !__itt_fstrcmp(h->nameA, name) && ((h->domainA == NULL && domain == NULL) ||
577             (h->domainA != NULL && domain != NULL && !__itt_fstrcmp(h->domainA, domain)))) break;
578     }
579     if (h == NULL)
580     {
581        NEW_COUNTER_A(&_N_(_ittapi_global),h,h_tail,name,domain,type);
582     }
583     if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
584     return (__itt_counter)h;
585 }
586 
587 /* -------------------------------------------------------------------------- */
588 
ITT_VERSIONIZE(ITT_JOIN (_N_ (pause),_init))589 static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(pause),_init))(void)
590 {
591     if (!_N_(_ittapi_global).api_initialized && _N_(_ittapi_global).thread_list == NULL)
592     {
593         __itt_init_ittlib_name(NULL, __itt_group_all);
594     }
595     if (ITTNOTIFY_NAME(pause) && ITTNOTIFY_NAME(pause) != ITT_VERSIONIZE(ITT_JOIN(_N_(pause),_init)))
596     {
597         ITTNOTIFY_NAME(pause)();
598     }
599     else
600     {
601         _N_(_ittapi_global).state = __itt_collection_paused;
602     }
603 }
604 
ITT_VERSIONIZE(ITT_JOIN (_N_ (resume),_init))605 static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(resume),_init))(void)
606 {
607     if (!_N_(_ittapi_global).api_initialized && _N_(_ittapi_global).thread_list == NULL)
608     {
609         __itt_init_ittlib_name(NULL, __itt_group_all);
610     }
611     if (ITTNOTIFY_NAME(resume) && ITTNOTIFY_NAME(resume) != ITT_VERSIONIZE(ITT_JOIN(_N_(resume),_init)))
612     {
613         ITTNOTIFY_NAME(resume)();
614     }
615     else
616     {
617         _N_(_ittapi_global).state = __itt_collection_normal;
618     }
619 }
620 
621 #if ITT_PLATFORM==ITT_PLATFORM_WIN
ITT_VERSIONIZE(ITT_JOIN (_N_ (thread_set_nameW),_init))622 static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameW),_init))(const wchar_t* name)
623 {
624     if (!_N_(_ittapi_global).api_initialized && _N_(_ittapi_global).thread_list == NULL)
625     {
626         __itt_init_ittlib_name(NULL, __itt_group_all);
627     }
628     if (ITTNOTIFY_NAME(thread_set_nameW) && ITTNOTIFY_NAME(thread_set_nameW) != ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameW),_init)))
629     {
630         ITTNOTIFY_NAME(thread_set_nameW)(name);
631     }
632 }
633 
ITT_VERSIONIZE(ITT_JOIN (_N_ (thr_name_setW),_init))634 static int ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thr_name_setW),_init))(const wchar_t* name, int namelen)
635 {
636     (void)namelen;
637     ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameW),_init))(name);
638     return 0;
639 }
640 
ITT_VERSIONIZE(ITT_JOIN (_N_ (thread_set_nameA),_init))641 static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameA),_init))(const char* name)
642 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
643 static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_name),_init))(const char* name)
644 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
645 {
646     if (!_N_(_ittapi_global).api_initialized && _N_(_ittapi_global).thread_list == NULL)
647     {
648         __itt_init_ittlib_name(NULL, __itt_group_all);
649     }
650 #if ITT_PLATFORM==ITT_PLATFORM_WIN
651     if (ITTNOTIFY_NAME(thread_set_nameA) && ITTNOTIFY_NAME(thread_set_nameA) != ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameA),_init)))
652     {
653         ITTNOTIFY_NAME(thread_set_nameA)(name);
654     }
655 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
656     if (ITTNOTIFY_NAME(thread_set_name) && ITTNOTIFY_NAME(thread_set_name) != ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_name),_init)))
657     {
658         ITTNOTIFY_NAME(thread_set_name)(name);
659     }
660 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
661 }
662 
663 #if ITT_PLATFORM==ITT_PLATFORM_WIN
ITT_VERSIONIZE(ITT_JOIN (_N_ (thr_name_setA),_init))664 static int ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thr_name_setA),_init))(const char* name, int namelen)
665 {
666     (void)namelen;
667     ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameA),_init))(name);
668     return 0;
669 }
670 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
ITT_VERSIONIZE(ITT_JOIN (_N_ (thr_name_set),_init))671 static int ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thr_name_set),_init))(const char* name, int namelen)
672 {
673     (void)namelen;
674     ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_name),_init))(name);
675     return 0;
676 }
677 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
678 
ITT_VERSIONIZE(ITT_JOIN (_N_ (thread_ignore),_init))679 static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thread_ignore),_init))(void)
680 {
681     if (!_N_(_ittapi_global).api_initialized && _N_(_ittapi_global).thread_list == NULL)
682     {
683         __itt_init_ittlib_name(NULL, __itt_group_all);
684     }
685     if (ITTNOTIFY_NAME(thread_ignore) && ITTNOTIFY_NAME(thread_ignore) != ITT_VERSIONIZE(ITT_JOIN(_N_(thread_ignore),_init)))
686     {
687         ITTNOTIFY_NAME(thread_ignore)();
688     }
689 }
690 
ITT_VERSIONIZE(ITT_JOIN (_N_ (thr_ignore),_init))691 static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thr_ignore),_init))(void)
692 {
693     ITT_VERSIONIZE(ITT_JOIN(_N_(thread_ignore),_init))();
694 }
695 
ITT_VERSIONIZE(ITT_JOIN (_N_ (enable_attach),_init))696 static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(enable_attach),_init))(void)
697 {
698 #ifdef __ANDROID__
699     /*
700      * if LIB_VAR_NAME env variable were set before then stay previous value
701      * else set default path
702     */
703     setenv(ITT_TO_STR(LIB_VAR_NAME), ANDROID_ITTNOTIFY_DEFAULT_PATH, 0);
704 #endif
705 }
706 
707 /* -------------------------------------------------------------------------- */
708 
__itt_fsplit(const char * s,const char * sep,const char ** out,int * len)709 static const char* __itt_fsplit(const char* s, const char* sep, const char** out, int* len)
710 {
711     int i;
712     int j;
713 
714     if (!s || !sep || !out || !len)
715         return NULL;
716 
717     for (i = 0; s[i]; i++)
718     {
719         int b = 0;
720         for (j = 0; sep[j]; j++)
721             if (s[i] == sep[j])
722             {
723                 b = 1;
724                 break;
725             }
726         if (!b)
727             break;
728     }
729 
730     if (!s[i])
731         return NULL;
732 
733     *len = 0;
734     *out = &s[i];
735 
736     for (; s[i]; i++, (*len)++)
737     {
738         int b = 0;
739         for (j = 0; sep[j]; j++)
740             if (s[i] == sep[j])
741             {
742                 b = 1;
743                 break;
744             }
745         if (b)
746             break;
747     }
748 
749     for (; s[i]; i++)
750     {
751         int b = 0;
752         for (j = 0; sep[j]; j++)
753             if (s[i] == sep[j])
754             {
755                 b = 1;
756                 break;
757             }
758         if (!b)
759             break;
760     }
761 
762     return &s[i];
763 }
764 
765 /* This function return value of env variable that placed into static buffer.
766  * !!! The same static buffer is used for subsequent calls. !!!
767  * This was done to avoid dynamic allocation for few calls.
768  * Actually we need this function only four times.
769  */
__itt_get_env_var(const char * name)770 static const char* __itt_get_env_var(const char* name)
771 {
772 #define MAX_ENV_VALUE_SIZE 4086
773     static char  env_buff[MAX_ENV_VALUE_SIZE];
774     static char* env_value = (char*)env_buff;
775 
776     if (name != NULL)
777     {
778 #if ITT_PLATFORM==ITT_PLATFORM_WIN
779         size_t max_len = MAX_ENV_VALUE_SIZE - (size_t)(env_value - env_buff);
780         DWORD rc = GetEnvironmentVariableA(name, env_value, (DWORD)max_len);
781         if (rc >= max_len)
782             __itt_report_error(__itt_error_env_too_long, name, (size_t)rc - 1, (size_t)(max_len - 1));
783         else if (rc > 0)
784         {
785             const char* ret = (const char*)env_value;
786             env_value += rc + 1;
787             return ret;
788         }
789         else
790         {
791             /* If environment variable is empty, GetEnvirornmentVariables()
792              * returns zero (number of characters (not including terminating null),
793              * and GetLastError() returns ERROR_SUCCESS. */
794             DWORD err = GetLastError();
795             if (err == ERROR_SUCCESS)
796                 return env_value;
797 
798             if (err != ERROR_ENVVAR_NOT_FOUND)
799                 __itt_report_error(__itt_error_cant_read_env, name, (int)err);
800         }
801 #else  /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
802         char* env = getenv(name);
803         if (env != NULL)
804         {
805             size_t len = __itt_fstrnlen(env, MAX_ENV_VALUE_SIZE);
806             size_t max_len = MAX_ENV_VALUE_SIZE - (size_t)(env_value - env_buff);
807             if (len < max_len)
808             {
809                 const char* ret = (const char*)env_value;
810                 __itt_fstrcpyn(env_value, max_len, env, len + 1);
811                 env_value += len + 1;
812                 return ret;
813             } else
814                 __itt_report_error(__itt_error_env_too_long, name, (size_t)len, (size_t)(max_len - 1));
815         }
816 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
817     }
818     return NULL;
819 }
820 
__itt_get_lib_name(void)821 static const char* __itt_get_lib_name(void)
822 {
823     const char* lib_name = __itt_get_env_var(ITT_TO_STR(LIB_VAR_NAME));
824 
825 #ifdef __ANDROID__
826     if (lib_name == NULL)
827     {
828 
829 #if ITT_ARCH==ITT_ARCH_IA32 || ITT_ARCH==ITT_ARCH_ARM
830         const char* const marker_filename = "com.intel.itt.collector_lib_32";
831 #else
832         const char* const marker_filename = "com.intel.itt.collector_lib_64";
833 #endif
834 
835         char system_wide_marker_filename[PATH_MAX] = {0};
836         int itt_marker_file_fd = -1;
837         ssize_t res = 0;
838 
839         res = snprintf(system_wide_marker_filename, PATH_MAX - 1, "%s%s", "/data/local/tmp/", marker_filename);
840         if (res < 0)
841         {
842             ITT_ANDROID_LOGE("Unable to concatenate marker file string.");
843             return lib_name;
844         }
845         itt_marker_file_fd = open(system_wide_marker_filename, O_RDONLY);
846 
847         if (itt_marker_file_fd == -1)
848         {
849             const pid_t my_pid = getpid();
850             char cmdline_path[PATH_MAX] = {0};
851             char package_name[PATH_MAX] = {0};
852             char app_sandbox_file[PATH_MAX] = {0};
853             int cmdline_fd = 0;
854 
855             ITT_ANDROID_LOGI("Unable to open system-wide marker file.");
856             res = snprintf(cmdline_path, PATH_MAX - 1, "/proc/%d/cmdline", my_pid);
857             if (res < 0)
858             {
859                 ITT_ANDROID_LOGE("Unable to get cmdline path string.");
860                 return lib_name;
861             }
862 
863             ITT_ANDROID_LOGI("CMD file: %s\n", cmdline_path);
864             cmdline_fd = open(cmdline_path, O_RDONLY);
865             if (cmdline_fd == -1)
866             {
867                 ITT_ANDROID_LOGE("Unable to open %s file!", cmdline_path);
868                 return lib_name;
869             }
870             res = read(cmdline_fd, package_name, PATH_MAX - 1);
871             if (res == -1)
872             {
873                 ITT_ANDROID_LOGE("Unable to read %s file!", cmdline_path);
874                 res = close(cmdline_fd);
875                 if (res == -1)
876                 {
877                     ITT_ANDROID_LOGE("Unable to close %s file!", cmdline_path);
878                 }
879                 return lib_name;
880             }
881             res = close(cmdline_fd);
882             if (res == -1)
883             {
884                 ITT_ANDROID_LOGE("Unable to close %s file!", cmdline_path);
885                 return lib_name;
886             }
887             ITT_ANDROID_LOGI("Package name: %s\n", package_name);
888             res = snprintf(app_sandbox_file, PATH_MAX - 1, "/data/data/%s/%s", package_name, marker_filename);
889             if (res < 0)
890             {
891                 ITT_ANDROID_LOGE("Unable to concatenate marker file string.");
892                 return lib_name;
893             }
894 
895             ITT_ANDROID_LOGI("Lib marker file name: %s\n", app_sandbox_file);
896             itt_marker_file_fd = open(app_sandbox_file, O_RDONLY);
897             if (itt_marker_file_fd == -1)
898             {
899                 ITT_ANDROID_LOGE("Unable to open app marker file!");
900                 return lib_name;
901             }
902         }
903 
904         {
905             char itt_lib_name[PATH_MAX] = {0};
906 
907             res = read(itt_marker_file_fd, itt_lib_name, PATH_MAX - 1);
908             if (res == -1)
909             {
910                 ITT_ANDROID_LOGE("Unable to read %s file!", itt_marker_file_fd);
911                 res = close(itt_marker_file_fd);
912                 if (res == -1)
913                 {
914                     ITT_ANDROID_LOGE("Unable to close %s file!", itt_marker_file_fd);
915                 }
916                 return lib_name;
917             }
918             ITT_ANDROID_LOGI("ITT Lib path: %s", itt_lib_name);
919             res = close(itt_marker_file_fd);
920             if (res == -1)
921             {
922                 ITT_ANDROID_LOGE("Unable to close %s file!", itt_marker_file_fd);
923                 return lib_name;
924             }
925             ITT_ANDROID_LOGI("Set env %s to %s", ITT_TO_STR(LIB_VAR_NAME), itt_lib_name);
926             res = setenv(ITT_TO_STR(LIB_VAR_NAME), itt_lib_name, 0);
927             if (res == -1)
928             {
929                 ITT_ANDROID_LOGE("Unable to set env var!");
930                 return lib_name;
931             }
932             lib_name = __itt_get_env_var(ITT_TO_STR(LIB_VAR_NAME));
933             ITT_ANDROID_LOGI("ITT Lib path from env: %s", lib_name);
934         }
935     }
936 #endif
937 
938     return lib_name;
939 }
940 
941 /* Avoid clashes with std::min, reported by tbb team */
942 #define __itt_min(a,b) ((a) < (b) ? (a) : (b))
943 
__itt_get_groups(void)944 static __itt_group_id __itt_get_groups(void)
945 {
946     int i;
947     __itt_group_id res = __itt_group_none;
948     const char* var_name  = "INTEL_ITTNOTIFY_GROUPS";
949     const char* group_str = __itt_get_env_var(var_name);
950 
951     if (group_str != NULL)
952     {
953         int len;
954         char gr[255];
955         const char* chunk;
956         while ((group_str = __itt_fsplit(group_str, ",; ", &chunk, &len)) != NULL)
957         {
958             int min_len = __itt_min(len, (int)(sizeof(gr) - 1));
959             __itt_fstrcpyn(gr, sizeof(gr) - 1, chunk,  min_len);
960             gr[min_len] = 0;
961 
962             for (i = 0; group_list[i].name != NULL; i++)
963             {
964                 if (!__itt_fstrcmp(gr, group_list[i].name))
965                 {
966                     res = (__itt_group_id)(res | group_list[i].id);
967                     break;
968                 }
969             }
970         }
971         /* TODO: !!! Workaround for bug with warning for unknown group !!!
972          * Should be fixed in new initialization scheme.
973          * Now the following groups should be set always. */
974         for (i = 0; group_list[i].id != __itt_group_none; i++)
975             if (group_list[i].id != __itt_group_all &&
976                 group_list[i].id > __itt_group_splitter_min &&
977                 group_list[i].id < __itt_group_splitter_max)
978                 res = (__itt_group_id)(res | group_list[i].id);
979         return res;
980     }
981     else
982     {
983         for (i = 0; group_alias[i].env_var != NULL; i++)
984             if (__itt_get_env_var(group_alias[i].env_var) != NULL)
985                 return group_alias[i].groups;
986     }
987 
988     return res;
989 }
990 
991 #undef __itt_min
992 
__itt_lib_version(lib_t lib)993 static int __itt_lib_version(lib_t lib)
994 {
995     if (lib == NULL)
996         return 0;
997     if (__itt_get_proc(lib, "__itt_api_init"))
998         return 2;
999     if (__itt_get_proc(lib, "__itt_api_version"))
1000         return 1;
1001     return 0;
1002 }
1003 
1004 /* It's not used right now! Comment it out to avoid warnings.
1005 static void __itt_reinit_all_pointers(void)
1006 {
1007     register int i;
1008     // Fill all pointers with initial stubs
1009     for (i = 0; _N_(_ittapi_global).api_list_ptr[i].name != NULL; i++)
1010         *_N_(_ittapi_global).api_list_ptr[i].func_ptr = _N_(_ittapi_global).api_list_ptr[i].init_func;
1011 }
1012 */
1013 
__itt_nullify_all_pointers(void)1014 static void __itt_nullify_all_pointers(void)
1015 {
1016     int i;
1017     /* Nulify all pointers except domain_create, string_handle_create  and counter_create */
1018     for (i = 0; _N_(_ittapi_global).api_list_ptr[i].name != NULL; i++)
1019         *_N_(_ittapi_global).api_list_ptr[i].func_ptr = _N_(_ittapi_global).api_list_ptr[i].null_func;
1020 }
1021 
1022 #if ITT_PLATFORM==ITT_PLATFORM_WIN
1023 #pragma warning(push)
1024 #pragma warning(disable: 4054) /* warning C4054: 'type cast' : from function pointer 'XXX' to data pointer 'void *' */
1025 #pragma warning(disable: 4055) /* warning C4055: 'type cast' : from data pointer 'void *' to function pointer 'XXX' */
1026 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
1027 
_N_(fini_ittlib)1028 ITT_EXTERN_C void _N_(fini_ittlib)(void)
1029 {
1030     __itt_api_fini_t* __itt_api_fini_ptr = NULL;
1031     static volatile TIDT current_thread = 0;
1032 
1033     if (_N_(_ittapi_global).api_initialized)
1034     {
1035         ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
1036         if (_N_(_ittapi_global).api_initialized)
1037         {
1038             if (current_thread == 0)
1039             {
1040                 if (PTHREAD_SYMBOLS) current_thread = __itt_thread_id();
1041                 if (_N_(_ittapi_global).lib != NULL)
1042                 {
1043                     __itt_api_fini_ptr = (__itt_api_fini_t*)(size_t)__itt_get_proc(_N_(_ittapi_global).lib, "__itt_api_fini");
1044                 }
1045                 if (__itt_api_fini_ptr)
1046                 {
1047                     __itt_api_fini_ptr(&_N_(_ittapi_global));
1048                 }
1049 
1050                 __itt_nullify_all_pointers();
1051 
1052  /* TODO: !!! not safe !!! don't support unload so far.
1053   *             if (_N_(_ittapi_global).lib != NULL)
1054   *                 __itt_unload_lib(_N_(_ittapi_global).lib);
1055   *             _N_(_ittapi_global).lib = NULL;
1056   */
1057                 _N_(_ittapi_global).api_initialized = 0;
1058                 current_thread = 0;
1059             }
1060         }
1061         if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
1062     }
1063 }
1064 
_N_(init_ittlib)1065 ITT_EXTERN_C int _N_(init_ittlib)(const char* lib_name, __itt_group_id init_groups)
1066 {
1067     int i;
1068     __itt_group_id groups;
1069 #ifdef ITT_COMPLETE_GROUP
1070     __itt_group_id zero_group = __itt_group_none;
1071 #endif /* ITT_COMPLETE_GROUP */
1072     static volatile TIDT current_thread = 0;
1073 
1074     if (!_N_(_ittapi_global).api_initialized)
1075     {
1076 #ifndef ITT_SIMPLE_INIT
1077         ITT_MUTEX_INIT_AND_LOCK(_N_(_ittapi_global));
1078 #endif /* ITT_SIMPLE_INIT */
1079 
1080         if (!_N_(_ittapi_global).api_initialized)
1081         {
1082             if (current_thread == 0)
1083             {
1084                 if (PTHREAD_SYMBOLS) current_thread = __itt_thread_id();
1085                 if (lib_name == NULL)
1086                 {
1087                     lib_name = __itt_get_lib_name();
1088                 }
1089                 groups = __itt_get_groups();
1090                 if (DL_SYMBOLS && (groups != __itt_group_none || lib_name != NULL))
1091                 {
1092                     _N_(_ittapi_global).lib = __itt_load_lib((lib_name == NULL) ? ittnotify_lib_name : lib_name);
1093 
1094                     if (_N_(_ittapi_global).lib != NULL)
1095                     {
1096                         __itt_api_init_t* __itt_api_init_ptr;
1097                         int lib_version = __itt_lib_version(_N_(_ittapi_global).lib);
1098 
1099                         switch (lib_version) {
1100                         case 0:
1101                             groups = __itt_group_legacy;
1102                             /* Falls through */
1103                         case 1:
1104                             /* Fill all pointers from dynamic library */
1105                             for (i = 0; _N_(_ittapi_global).api_list_ptr[i].name != NULL; i++)
1106                             {
1107                                 if (_N_(_ittapi_global).api_list_ptr[i].group & groups & init_groups)
1108                                 {
1109                                     *_N_(_ittapi_global).api_list_ptr[i].func_ptr = (void*)__itt_get_proc(_N_(_ittapi_global).lib, _N_(_ittapi_global).api_list_ptr[i].name);
1110                                     if (*_N_(_ittapi_global).api_list_ptr[i].func_ptr == NULL)
1111                                     {
1112                                         /* Restore pointers for function with static implementation */
1113                                         *_N_(_ittapi_global).api_list_ptr[i].func_ptr = _N_(_ittapi_global).api_list_ptr[i].null_func;
1114                                         __itt_report_error(__itt_error_no_symbol, lib_name, _N_(_ittapi_global).api_list_ptr[i].name);
1115 #ifdef ITT_COMPLETE_GROUP
1116                                         zero_group = (__itt_group_id)(zero_group | _N_(_ittapi_global).api_list_ptr[i].group);
1117 #endif /* ITT_COMPLETE_GROUP */
1118                                     }
1119                                 }
1120                                 else
1121                                     *_N_(_ittapi_global).api_list_ptr[i].func_ptr = _N_(_ittapi_global).api_list_ptr[i].null_func;
1122                             }
1123 
1124                             if (groups == __itt_group_legacy)
1125                             {
1126                                 /* Compatibility with legacy tools */
1127                                 ITTNOTIFY_NAME(thread_ignore)  = ITTNOTIFY_NAME(thr_ignore);
1128 #if ITT_PLATFORM==ITT_PLATFORM_WIN
1129                                 ITTNOTIFY_NAME(sync_createA)   = ITTNOTIFY_NAME(sync_set_nameA);
1130                                 ITTNOTIFY_NAME(sync_createW)   = ITTNOTIFY_NAME(sync_set_nameW);
1131 #else  /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
1132                                 ITTNOTIFY_NAME(sync_create)    = ITTNOTIFY_NAME(sync_set_name);
1133 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
1134                                 ITTNOTIFY_NAME(sync_prepare)   = ITTNOTIFY_NAME(notify_sync_prepare);
1135                                 ITTNOTIFY_NAME(sync_cancel)    = ITTNOTIFY_NAME(notify_sync_cancel);
1136                                 ITTNOTIFY_NAME(sync_acquired)  = ITTNOTIFY_NAME(notify_sync_acquired);
1137                                 ITTNOTIFY_NAME(sync_releasing) = ITTNOTIFY_NAME(notify_sync_releasing);
1138                             }
1139 
1140 #ifdef ITT_COMPLETE_GROUP
1141                             for (i = 0; _N_(_ittapi_global).api_list_ptr[i].name != NULL; i++)
1142                                 if (_N_(_ittapi_global).api_list_ptr[i].group & zero_group)
1143                                     *_N_(_ittapi_global).api_list_ptr[i].func_ptr = _N_(_ittapi_global).api_list_ptr[i].null_func;
1144 #endif /* ITT_COMPLETE_GROUP */
1145                             break;
1146                         case 2:
1147                             __itt_api_init_ptr = (__itt_api_init_t*)(size_t)__itt_get_proc(_N_(_ittapi_global).lib, "__itt_api_init");
1148                             if (__itt_api_init_ptr)
1149                                 __itt_api_init_ptr(&_N_(_ittapi_global), init_groups);
1150                             break;
1151                         }
1152                     }
1153                     else
1154                     {
1155                         __itt_nullify_all_pointers();
1156 
1157 #if ITT_PLATFORM==ITT_PLATFORM_WIN
1158                         int error = __itt_system_error();
1159 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
1160                         const char* error = dlerror();
1161 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
1162                         __itt_report_error(__itt_error_no_module, lib_name, error);
1163                     }
1164                 }
1165                 else
1166                 {
1167                     __itt_nullify_all_pointers();
1168                 }
1169                 _N_(_ittapi_global).api_initialized = 1;
1170                 current_thread = 0;
1171                 /* !!! Just to avoid unused code elimination !!! */
1172                 if (__itt_fini_ittlib_ptr == _N_(fini_ittlib)) current_thread = 0;
1173             }
1174         }
1175 
1176 #ifndef ITT_SIMPLE_INIT
1177         if (PTHREAD_SYMBOLS) __itt_mutex_unlock(&_N_(_ittapi_global).mutex);
1178 #endif /* ITT_SIMPLE_INIT */
1179     }
1180 
1181     /* Evaluating if any function ptr is non empty and it's in init_groups */
1182     for (i = 0; _N_(_ittapi_global).api_list_ptr[i].name != NULL; i++)
1183     {
1184         if (*_N_(_ittapi_global).api_list_ptr[i].func_ptr != _N_(_ittapi_global).api_list_ptr[i].null_func &&
1185             _N_(_ittapi_global).api_list_ptr[i].group & init_groups)
1186         {
1187             return 1;
1188         }
1189     }
1190     return 0;
1191 }
1192 
_N_(set_error_handler)1193 ITT_EXTERN_C __itt_error_handler_t* _N_(set_error_handler)(__itt_error_handler_t* handler)
1194 {
1195     __itt_error_handler_t* prev = (__itt_error_handler_t*)(size_t)_N_(_ittapi_global).error_handler;
1196     _N_(_ittapi_global).error_handler = (void*)(size_t)handler;
1197     return prev;
1198 }
1199 
1200 #if ITT_PLATFORM==ITT_PLATFORM_WIN
1201 #pragma warning(pop)
1202 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
1203 
1204 /** __itt_mark_pt_region functions marks region of interest
1205  * region parameter defines different regions.
1206  * 0 <= region < 8 */
1207 
1208 #if defined(ITT_API_IPT_SUPPORT) && (ITT_PLATFORM==ITT_PLATFORM_WIN || ITT_PLATFORM==ITT_PLATFORM_POSIX) && !defined(__ANDROID__)
1209 void __itt_pt_mark(__itt_pt_region region);
1210 void __itt_pt_mark_event(__itt_pt_region region);
1211 #endif
1212 
_N_(mark_pt_region_begin)1213 ITT_EXTERN_C void _N_(mark_pt_region_begin)(__itt_pt_region region)
1214 {
1215 #if defined(ITT_API_IPT_SUPPORT) && (ITT_PLATFORM==ITT_PLATFORM_WIN || ITT_PLATFORM==ITT_PLATFORM_POSIX) && !defined(__ANDROID__)
1216     if (_N_(_ittapi_global).ipt_collect_events == 1)
1217     {
1218         __itt_pt_mark_event(2*region);
1219     }
1220     else
1221     {
1222         __itt_pt_mark(2*region);
1223     }
1224 #else
1225     (void)region;
1226 #endif
1227 }
1228 
_N_(mark_pt_region_end)1229 ITT_EXTERN_C void _N_(mark_pt_region_end)(__itt_pt_region region)
1230 {
1231 #if defined(ITT_API_IPT_SUPPORT) && (ITT_PLATFORM==ITT_PLATFORM_WIN || ITT_PLATFORM==ITT_PLATFORM_POSIX) && !defined(__ANDROID__)
1232     if (_N_(_ittapi_global).ipt_collect_events == 1)
1233     {
1234         __itt_pt_mark_event(2*region + 1);
1235     }
1236     else
1237     {
1238         __itt_pt_mark(2*region + 1);
1239     }
1240 #else
1241      (void)region;
1242 #endif
1243 }
1244 
1245