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