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