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