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