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