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