xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/IntelJITProfiling/jitprofiling.c (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric /*===-- jitprofiling.c - JIT (Just-In-Time) Profiling API----------*- C -*-===*
2*0fca6ea1SDimitry Andric  *
3*0fca6ea1SDimitry Andric  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric  * See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric  *
7*0fca6ea1SDimitry Andric  *===----------------------------------------------------------------------===*
8*0fca6ea1SDimitry Andric  *
9*0fca6ea1SDimitry Andric  * This file provides Intel(R) Performance Analyzer JIT (Just-In-Time)
10*0fca6ea1SDimitry Andric  * Profiling API implementation.
11*0fca6ea1SDimitry Andric  *
12*0fca6ea1SDimitry Andric  * NOTE: This file comes in a style different from the rest of LLVM
13*0fca6ea1SDimitry Andric  * source base since  this is a piece of code shared from Intel(R)
14*0fca6ea1SDimitry Andric  * products.  Please do not reformat / re-style this code to make
15*0fca6ea1SDimitry Andric  * subsequent merges and contributions from the original source base eaiser.
16*0fca6ea1SDimitry Andric  *
17*0fca6ea1SDimitry Andric  *===----------------------------------------------------------------------===*/
18*0fca6ea1SDimitry Andric #include "ittnotify_config.h"
19*0fca6ea1SDimitry Andric 
20*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
21*0fca6ea1SDimitry Andric #include <windows.h>
22*0fca6ea1SDimitry Andric #pragma optimize("", off)
23*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
24*0fca6ea1SDimitry Andric #include <dlfcn.h>
25*0fca6ea1SDimitry Andric #include <pthread.h>
26*0fca6ea1SDimitry Andric #include <stdint.h>
27*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
28*0fca6ea1SDimitry Andric #include <stdlib.h>
29*0fca6ea1SDimitry Andric 
30*0fca6ea1SDimitry Andric #include "jitprofiling.h"
31*0fca6ea1SDimitry Andric 
32*0fca6ea1SDimitry Andric static const char rcsid[] = "\n@(#) $Revision: 243501 $\n";
33*0fca6ea1SDimitry Andric 
34*0fca6ea1SDimitry Andric #define DLL_ENVIRONMENT_VAR             "VS_PROFILER"
35*0fca6ea1SDimitry Andric 
36*0fca6ea1SDimitry Andric #ifndef NEW_DLL_ENVIRONMENT_VAR
37*0fca6ea1SDimitry Andric #if ITT_ARCH==ITT_ARCH_IA32
38*0fca6ea1SDimitry Andric #define NEW_DLL_ENVIRONMENT_VAR	        "INTEL_JIT_PROFILER32"
39*0fca6ea1SDimitry Andric #else
40*0fca6ea1SDimitry Andric #define NEW_DLL_ENVIRONMENT_VAR	        "INTEL_JIT_PROFILER64"
41*0fca6ea1SDimitry Andric #endif
42*0fca6ea1SDimitry Andric #endif /* NEW_DLL_ENVIRONMENT_VAR */
43*0fca6ea1SDimitry Andric 
44*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
45*0fca6ea1SDimitry Andric #define DEFAULT_DLLNAME                 "JitPI.dll"
46*0fca6ea1SDimitry Andric HINSTANCE m_libHandle = NULL;
47*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
48*0fca6ea1SDimitry Andric #define DEFAULT_DLLNAME                 "libJitPI.so"
49*0fca6ea1SDimitry Andric void* m_libHandle = NULL;
50*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
51*0fca6ea1SDimitry Andric 
52*0fca6ea1SDimitry Andric /* default location of JIT profiling agent on Android */
53*0fca6ea1SDimitry Andric #define ANDROID_JIT_AGENT_PATH  "/data/intel/libittnotify.so"
54*0fca6ea1SDimitry Andric 
55*0fca6ea1SDimitry Andric /* the function pointers */
56*0fca6ea1SDimitry Andric typedef unsigned int(*TPInitialize)(void);
57*0fca6ea1SDimitry Andric static TPInitialize FUNC_Initialize=NULL;
58*0fca6ea1SDimitry Andric 
59*0fca6ea1SDimitry Andric typedef unsigned int(*TPNotify)(unsigned int, void*);
60*0fca6ea1SDimitry Andric static TPNotify FUNC_NotifyEvent=NULL;
61*0fca6ea1SDimitry Andric 
62*0fca6ea1SDimitry Andric static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING;
63*0fca6ea1SDimitry Andric 
64*0fca6ea1SDimitry Andric /* end collector dll part. */
65*0fca6ea1SDimitry Andric 
66*0fca6ea1SDimitry Andric /* loadiJIT_Funcs() : this function is called just in the beginning
67*0fca6ea1SDimitry Andric  *  and is responsible to load the functions from BistroJavaCollector.dll
68*0fca6ea1SDimitry Andric  * result:
69*0fca6ea1SDimitry Andric  *  on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1
70*0fca6ea1SDimitry Andric  *  on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0
71*0fca6ea1SDimitry Andric  */
72*0fca6ea1SDimitry Andric static int loadiJIT_Funcs(void);
73*0fca6ea1SDimitry Andric 
74*0fca6ea1SDimitry Andric /* global representing whether the BistroJavaCollector can't be loaded */
75*0fca6ea1SDimitry Andric static int iJIT_DLL_is_missing = 0;
76*0fca6ea1SDimitry Andric 
77*0fca6ea1SDimitry Andric /* Virtual stack - the struct is used as a virtual stack for each thread.
78*0fca6ea1SDimitry Andric  * Every thread initializes with a stack of size INIT_TOP_STACK.
79*0fca6ea1SDimitry Andric  * Every method entry decreases from the current stack point,
80*0fca6ea1SDimitry Andric  * and when a thread stack reaches its top of stack (return from the global
81*0fca6ea1SDimitry Andric  * function), the top of stack and the current stack increase. Notice that
82*0fca6ea1SDimitry Andric  * when returning from a function the stack pointer is the address of
83*0fca6ea1SDimitry Andric  * the function return.
84*0fca6ea1SDimitry Andric */
85*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
86*0fca6ea1SDimitry Andric static DWORD threadLocalStorageHandle = 0;
87*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
88*0fca6ea1SDimitry Andric static pthread_key_t threadLocalStorageHandle = (pthread_key_t)0;
89*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
90*0fca6ea1SDimitry Andric 
91*0fca6ea1SDimitry Andric #define INIT_TOP_Stack 10000
92*0fca6ea1SDimitry Andric 
93*0fca6ea1SDimitry Andric typedef struct
94*0fca6ea1SDimitry Andric {
95*0fca6ea1SDimitry Andric     unsigned int TopStack;
96*0fca6ea1SDimitry Andric     unsigned int CurrentStack;
97*0fca6ea1SDimitry Andric } ThreadStack, *pThreadStack;
98*0fca6ea1SDimitry Andric 
99*0fca6ea1SDimitry Andric /* end of virtual stack. */
100*0fca6ea1SDimitry Andric 
101*0fca6ea1SDimitry Andric /*
102*0fca6ea1SDimitry Andric  * The function for reporting virtual-machine related events to VTune.
103*0fca6ea1SDimitry Andric  * Note: when reporting iJVM_EVENT_TYPE_ENTER_NIDS, there is no need to fill
104*0fca6ea1SDimitry Andric  * in the stack_id field in the iJIT_Method_NIDS structure, as VTune fills it.
105*0fca6ea1SDimitry Andric  * The return value in iJVM_EVENT_TYPE_ENTER_NIDS &&
106*0fca6ea1SDimitry Andric  * iJVM_EVENT_TYPE_LEAVE_NIDS events will be 0 in case of failure.
107*0fca6ea1SDimitry Andric  * in iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event
108*0fca6ea1SDimitry Andric  * it will be -1 if EventSpecificData == 0 otherwise it will be 0.
109*0fca6ea1SDimitry Andric */
110*0fca6ea1SDimitry Andric 
111*0fca6ea1SDimitry Andric ITT_EXTERN_C int JITAPI
112*0fca6ea1SDimitry Andric iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData)
113*0fca6ea1SDimitry Andric {
114*0fca6ea1SDimitry Andric     int ReturnValue;
115*0fca6ea1SDimitry Andric 
116*0fca6ea1SDimitry Andric     /*
117*0fca6ea1SDimitry Andric      * This section is for debugging outside of VTune.
118*0fca6ea1SDimitry Andric      * It creates the environment variables that indicates call graph mode.
119*0fca6ea1SDimitry Andric      * If running outside of VTune remove the remark.
120*0fca6ea1SDimitry Andric      *
121*0fca6ea1SDimitry Andric      *
122*0fca6ea1SDimitry Andric      * static int firstTime = 1;
123*0fca6ea1SDimitry Andric      * char DoCallGraph[12] = "DoCallGraph";
124*0fca6ea1SDimitry Andric      * if (firstTime)
125*0fca6ea1SDimitry Andric      * {
126*0fca6ea1SDimitry Andric      * firstTime = 0;
127*0fca6ea1SDimitry Andric      * SetEnvironmentVariable( "BISTRO_COLLECTORS_DO_CALLGRAPH", DoCallGraph);
128*0fca6ea1SDimitry Andric      * }
129*0fca6ea1SDimitry Andric      *
130*0fca6ea1SDimitry Andric      * end of section.
131*0fca6ea1SDimitry Andric     */
132*0fca6ea1SDimitry Andric 
133*0fca6ea1SDimitry Andric     /* initialization part - the functions have not been loaded yet. This part
134*0fca6ea1SDimitry Andric      *        will load the functions, and check if we are in Call Graph mode.
135*0fca6ea1SDimitry Andric      *        (for special treatment).
136*0fca6ea1SDimitry Andric      */
137*0fca6ea1SDimitry Andric     if (!FUNC_NotifyEvent)
138*0fca6ea1SDimitry Andric     {
139*0fca6ea1SDimitry Andric         if (iJIT_DLL_is_missing)
140*0fca6ea1SDimitry Andric             return 0;
141*0fca6ea1SDimitry Andric 
142*0fca6ea1SDimitry Andric         /* load the Function from the DLL */
143*0fca6ea1SDimitry Andric         if (!loadiJIT_Funcs())
144*0fca6ea1SDimitry Andric             return 0;
145*0fca6ea1SDimitry Andric 
146*0fca6ea1SDimitry Andric         /* Call Graph initialization. */
147*0fca6ea1SDimitry Andric     }
148*0fca6ea1SDimitry Andric 
149*0fca6ea1SDimitry Andric     /* If the event is method entry/exit, check that in the current mode
150*0fca6ea1SDimitry Andric      * VTune is allowed to receive it
151*0fca6ea1SDimitry Andric      */
152*0fca6ea1SDimitry Andric     if ((event_type == iJVM_EVENT_TYPE_ENTER_NIDS ||
153*0fca6ea1SDimitry Andric          event_type == iJVM_EVENT_TYPE_LEAVE_NIDS) &&
154*0fca6ea1SDimitry Andric         (executionMode != iJIT_CALLGRAPH_ON))
155*0fca6ea1SDimitry Andric     {
156*0fca6ea1SDimitry Andric         return 0;
157*0fca6ea1SDimitry Andric     }
158*0fca6ea1SDimitry Andric     /* This section is performed when method enter event occurs.
159*0fca6ea1SDimitry Andric      * It updates the virtual stack, or creates it if this is the first
160*0fca6ea1SDimitry Andric      * method entry in the thread. The stack pointer is decreased.
161*0fca6ea1SDimitry Andric      */
162*0fca6ea1SDimitry Andric     if (event_type == iJVM_EVENT_TYPE_ENTER_NIDS)
163*0fca6ea1SDimitry Andric     {
164*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
165*0fca6ea1SDimitry Andric         pThreadStack threadStack =
166*0fca6ea1SDimitry Andric             (pThreadStack)TlsGetValue (threadLocalStorageHandle);
167*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
168*0fca6ea1SDimitry Andric         pThreadStack threadStack =
169*0fca6ea1SDimitry Andric             (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
170*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
171*0fca6ea1SDimitry Andric 
172*0fca6ea1SDimitry Andric         /* check for use of reserved method IDs */
173*0fca6ea1SDimitry Andric         if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
174*0fca6ea1SDimitry Andric             return 0;
175*0fca6ea1SDimitry Andric 
176*0fca6ea1SDimitry Andric         if (!threadStack)
177*0fca6ea1SDimitry Andric         {
178*0fca6ea1SDimitry Andric             /* initialize the stack. */
179*0fca6ea1SDimitry Andric             threadStack = (pThreadStack) calloc (sizeof(ThreadStack), 1);
180*0fca6ea1SDimitry Andric             threadStack->TopStack = INIT_TOP_Stack;
181*0fca6ea1SDimitry Andric             threadStack->CurrentStack = INIT_TOP_Stack;
182*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
183*0fca6ea1SDimitry Andric             TlsSetValue(threadLocalStorageHandle,(void*)threadStack);
184*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
185*0fca6ea1SDimitry Andric             pthread_setspecific(threadLocalStorageHandle,(void*)threadStack);
186*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
187*0fca6ea1SDimitry Andric         }
188*0fca6ea1SDimitry Andric 
189*0fca6ea1SDimitry Andric         /* decrease the stack. */
190*0fca6ea1SDimitry Andric         ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
191*0fca6ea1SDimitry Andric             (threadStack->CurrentStack)--;
192*0fca6ea1SDimitry Andric     }
193*0fca6ea1SDimitry Andric 
194*0fca6ea1SDimitry Andric     /* This section is performed when method leave event occurs
195*0fca6ea1SDimitry Andric      * It updates the virtual stack.
196*0fca6ea1SDimitry Andric      *    Increases the stack pointer.
197*0fca6ea1SDimitry Andric      *    If the stack pointer reached the top (left the global function)
198*0fca6ea1SDimitry Andric      *        increase the pointer and the top pointer.
199*0fca6ea1SDimitry Andric      */
200*0fca6ea1SDimitry Andric     if (event_type == iJVM_EVENT_TYPE_LEAVE_NIDS)
201*0fca6ea1SDimitry Andric     {
202*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
203*0fca6ea1SDimitry Andric         pThreadStack threadStack =
204*0fca6ea1SDimitry Andric            (pThreadStack)TlsGetValue (threadLocalStorageHandle);
205*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
206*0fca6ea1SDimitry Andric         pThreadStack threadStack =
207*0fca6ea1SDimitry Andric             (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
208*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
209*0fca6ea1SDimitry Andric 
210*0fca6ea1SDimitry Andric         /* check for use of reserved method IDs */
211*0fca6ea1SDimitry Andric         if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
212*0fca6ea1SDimitry Andric             return 0;
213*0fca6ea1SDimitry Andric 
214*0fca6ea1SDimitry Andric         if (!threadStack)
215*0fca6ea1SDimitry Andric         {
216*0fca6ea1SDimitry Andric             /* Error: first report in this thread is method exit */
217*0fca6ea1SDimitry Andric             exit (1);
218*0fca6ea1SDimitry Andric         }
219*0fca6ea1SDimitry Andric 
220*0fca6ea1SDimitry Andric         ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
221*0fca6ea1SDimitry Andric             ++(threadStack->CurrentStack) + 1;
222*0fca6ea1SDimitry Andric 
223*0fca6ea1SDimitry Andric         if (((piJIT_Method_NIDS) EventSpecificData)->stack_id
224*0fca6ea1SDimitry Andric                > threadStack->TopStack)
225*0fca6ea1SDimitry Andric             ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
226*0fca6ea1SDimitry Andric                 (unsigned int)-1;
227*0fca6ea1SDimitry Andric     }
228*0fca6ea1SDimitry Andric 
229*0fca6ea1SDimitry Andric     if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED)
230*0fca6ea1SDimitry Andric     {
231*0fca6ea1SDimitry Andric         /* check for use of reserved method IDs */
232*0fca6ea1SDimitry Andric         if ( ((piJIT_Method_Load) EventSpecificData)->method_id <= 999 )
233*0fca6ea1SDimitry Andric             return 0;
234*0fca6ea1SDimitry Andric     }
235*0fca6ea1SDimitry Andric 
236*0fca6ea1SDimitry Andric     ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
237*0fca6ea1SDimitry Andric 
238*0fca6ea1SDimitry Andric     return ReturnValue;
239*0fca6ea1SDimitry Andric }
240*0fca6ea1SDimitry Andric 
241*0fca6ea1SDimitry Andric /* The new mode call back routine */
242*0fca6ea1SDimitry Andric ITT_EXTERN_C void JITAPI
243*0fca6ea1SDimitry Andric iJIT_RegisterCallbackEx(void *userdata, iJIT_ModeChangedEx
244*0fca6ea1SDimitry Andric                         NewModeCallBackFuncEx)
245*0fca6ea1SDimitry Andric {
246*0fca6ea1SDimitry Andric     /* is it already missing... or the load of functions from the DLL failed */
247*0fca6ea1SDimitry Andric     if (iJIT_DLL_is_missing || !loadiJIT_Funcs())
248*0fca6ea1SDimitry Andric     {
249*0fca6ea1SDimitry Andric         /* then do not bother with notifications */
250*0fca6ea1SDimitry Andric         NewModeCallBackFuncEx(userdata, iJIT_NO_NOTIFICATIONS);
251*0fca6ea1SDimitry Andric         /* Error: could not load JIT functions. */
252*0fca6ea1SDimitry Andric         return;
253*0fca6ea1SDimitry Andric     }
254*0fca6ea1SDimitry Andric     /* nothing to do with the callback */
255*0fca6ea1SDimitry Andric }
256*0fca6ea1SDimitry Andric 
257*0fca6ea1SDimitry Andric /*
258*0fca6ea1SDimitry Andric  * This function allows the user to query in which mode, if at all,
259*0fca6ea1SDimitry Andric  *VTune is running
260*0fca6ea1SDimitry Andric  */
261*0fca6ea1SDimitry Andric ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive(void)
262*0fca6ea1SDimitry Andric {
263*0fca6ea1SDimitry Andric     if (!iJIT_DLL_is_missing)
264*0fca6ea1SDimitry Andric     {
265*0fca6ea1SDimitry Andric         loadiJIT_Funcs();
266*0fca6ea1SDimitry Andric     }
267*0fca6ea1SDimitry Andric 
268*0fca6ea1SDimitry Andric     return executionMode;
269*0fca6ea1SDimitry Andric }
270*0fca6ea1SDimitry Andric 
271*0fca6ea1SDimitry Andric /* this function loads the collector dll (BistroJavaCollector)
272*0fca6ea1SDimitry Andric  * and the relevant functions.
273*0fca6ea1SDimitry Andric  * on success: all functions load,     iJIT_DLL_is_missing = 0, return value = 1
274*0fca6ea1SDimitry Andric  * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0
275*0fca6ea1SDimitry Andric  */
276*0fca6ea1SDimitry Andric static int loadiJIT_Funcs(void)
277*0fca6ea1SDimitry Andric {
278*0fca6ea1SDimitry Andric     static int bDllWasLoaded = 0;
279*0fca6ea1SDimitry Andric     char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */
280*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
281*0fca6ea1SDimitry Andric     DWORD dNameLength = 0;
282*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
283*0fca6ea1SDimitry Andric 
284*0fca6ea1SDimitry Andric     if(bDllWasLoaded)
285*0fca6ea1SDimitry Andric     {
286*0fca6ea1SDimitry Andric         /* dll was already loaded, no need to do it for the second time */
287*0fca6ea1SDimitry Andric         return 1;
288*0fca6ea1SDimitry Andric     }
289*0fca6ea1SDimitry Andric 
290*0fca6ea1SDimitry Andric     /* Assumes that the DLL will not be found */
291*0fca6ea1SDimitry Andric     iJIT_DLL_is_missing = 1;
292*0fca6ea1SDimitry Andric     FUNC_NotifyEvent = NULL;
293*0fca6ea1SDimitry Andric 
294*0fca6ea1SDimitry Andric     if (m_libHandle)
295*0fca6ea1SDimitry Andric     {
296*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
297*0fca6ea1SDimitry Andric         FreeLibrary(m_libHandle);
298*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
299*0fca6ea1SDimitry Andric         dlclose(m_libHandle);
300*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
301*0fca6ea1SDimitry Andric         m_libHandle = NULL;
302*0fca6ea1SDimitry Andric     }
303*0fca6ea1SDimitry Andric 
304*0fca6ea1SDimitry Andric     /* Try to get the dll name from the environment */
305*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
306*0fca6ea1SDimitry Andric     dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0);
307*0fca6ea1SDimitry Andric     if (dNameLength)
308*0fca6ea1SDimitry Andric     {
309*0fca6ea1SDimitry Andric         DWORD envret = 0;
310*0fca6ea1SDimitry Andric         dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
311*0fca6ea1SDimitry Andric         envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR,
312*0fca6ea1SDimitry Andric                                          dllName, dNameLength);
313*0fca6ea1SDimitry Andric         if (envret)
314*0fca6ea1SDimitry Andric         {
315*0fca6ea1SDimitry Andric             /* Try to load the dll from the PATH... */
316*0fca6ea1SDimitry Andric             m_libHandle = LoadLibraryExA(dllName,
317*0fca6ea1SDimitry Andric                                          NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
318*0fca6ea1SDimitry Andric         }
319*0fca6ea1SDimitry Andric         free(dllName);
320*0fca6ea1SDimitry Andric     } else {
321*0fca6ea1SDimitry Andric         /* Try to use old VS_PROFILER variable */
322*0fca6ea1SDimitry Andric         dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0);
323*0fca6ea1SDimitry Andric         if (dNameLength)
324*0fca6ea1SDimitry Andric         {
325*0fca6ea1SDimitry Andric             DWORD envret = 0;
326*0fca6ea1SDimitry Andric             dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
327*0fca6ea1SDimitry Andric             envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR,
328*0fca6ea1SDimitry Andric                                              dllName, dNameLength);
329*0fca6ea1SDimitry Andric             if (envret)
330*0fca6ea1SDimitry Andric             {
331*0fca6ea1SDimitry Andric                 /* Try to load the dll from the PATH... */
332*0fca6ea1SDimitry Andric                 m_libHandle = LoadLibraryA(dllName);
333*0fca6ea1SDimitry Andric             }
334*0fca6ea1SDimitry Andric             free(dllName);
335*0fca6ea1SDimitry Andric         }
336*0fca6ea1SDimitry Andric     }
337*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
338*0fca6ea1SDimitry Andric     dllName = getenv(NEW_DLL_ENVIRONMENT_VAR);
339*0fca6ea1SDimitry Andric     if (!dllName)
340*0fca6ea1SDimitry Andric         dllName = getenv(DLL_ENVIRONMENT_VAR);
341*0fca6ea1SDimitry Andric #ifdef ANDROID
342*0fca6ea1SDimitry Andric     if (!dllName)
343*0fca6ea1SDimitry Andric         dllName = ANDROID_JIT_AGENT_PATH;
344*0fca6ea1SDimitry Andric #endif
345*0fca6ea1SDimitry Andric     if (dllName)
346*0fca6ea1SDimitry Andric     {
347*0fca6ea1SDimitry Andric         /* Try to load the dll from the PATH... */
348*0fca6ea1SDimitry Andric         m_libHandle = dlopen(dllName, RTLD_LAZY);
349*0fca6ea1SDimitry Andric     }
350*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
351*0fca6ea1SDimitry Andric 
352*0fca6ea1SDimitry Andric     if (!m_libHandle)
353*0fca6ea1SDimitry Andric     {
354*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
355*0fca6ea1SDimitry Andric         m_libHandle = LoadLibraryA(DEFAULT_DLLNAME);
356*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
357*0fca6ea1SDimitry Andric         m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY);
358*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
359*0fca6ea1SDimitry Andric     }
360*0fca6ea1SDimitry Andric 
361*0fca6ea1SDimitry Andric     /* if the dll wasn't loaded - exit. */
362*0fca6ea1SDimitry Andric     if (!m_libHandle)
363*0fca6ea1SDimitry Andric     {
364*0fca6ea1SDimitry Andric         iJIT_DLL_is_missing = 1; /* don't try to initialize
365*0fca6ea1SDimitry Andric                                   * JIT agent the second time
366*0fca6ea1SDimitry Andric                                   */
367*0fca6ea1SDimitry Andric         return 0;
368*0fca6ea1SDimitry Andric     }
369*0fca6ea1SDimitry Andric 
370*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
371*0fca6ea1SDimitry Andric     FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent");
372*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
373*0fca6ea1SDimitry Andric     FUNC_NotifyEvent = (TPNotify)(intptr_t)dlsym(m_libHandle, "NotifyEvent");
374*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
375*0fca6ea1SDimitry Andric     if (!FUNC_NotifyEvent)
376*0fca6ea1SDimitry Andric     {
377*0fca6ea1SDimitry Andric         FUNC_Initialize = NULL;
378*0fca6ea1SDimitry Andric         return 0;
379*0fca6ea1SDimitry Andric     }
380*0fca6ea1SDimitry Andric 
381*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
382*0fca6ea1SDimitry Andric     FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize");
383*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
384*0fca6ea1SDimitry Andric     FUNC_Initialize = (TPInitialize)(intptr_t)dlsym(m_libHandle, "Initialize");
385*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
386*0fca6ea1SDimitry Andric     if (!FUNC_Initialize)
387*0fca6ea1SDimitry Andric     {
388*0fca6ea1SDimitry Andric         FUNC_NotifyEvent = NULL;
389*0fca6ea1SDimitry Andric         return 0;
390*0fca6ea1SDimitry Andric     }
391*0fca6ea1SDimitry Andric 
392*0fca6ea1SDimitry Andric     executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize();
393*0fca6ea1SDimitry Andric 
394*0fca6ea1SDimitry Andric     bDllWasLoaded = 1;
395*0fca6ea1SDimitry Andric     iJIT_DLL_is_missing = 0; /* DLL is ok. */
396*0fca6ea1SDimitry Andric 
397*0fca6ea1SDimitry Andric     /*
398*0fca6ea1SDimitry Andric      * Call Graph mode: init the thread local storage
399*0fca6ea1SDimitry Andric      * (need to store the virtual stack there).
400*0fca6ea1SDimitry Andric      */
401*0fca6ea1SDimitry Andric     if ( executionMode == iJIT_CALLGRAPH_ON )
402*0fca6ea1SDimitry Andric     {
403*0fca6ea1SDimitry Andric         /* Allocate a thread local storage slot for the thread "stack" */
404*0fca6ea1SDimitry Andric         if (!threadLocalStorageHandle)
405*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
406*0fca6ea1SDimitry Andric             threadLocalStorageHandle = TlsAlloc();
407*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
408*0fca6ea1SDimitry Andric         pthread_key_create(&threadLocalStorageHandle, NULL);
409*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
410*0fca6ea1SDimitry Andric     }
411*0fca6ea1SDimitry Andric 
412*0fca6ea1SDimitry Andric     return 1;
413*0fca6ea1SDimitry Andric }
414*0fca6ea1SDimitry Andric 
415*0fca6ea1SDimitry Andric /*
416*0fca6ea1SDimitry Andric  * This function should be called by the user whenever a thread ends,
417*0fca6ea1SDimitry Andric  * to free the thread "virtual stack" storage
418*0fca6ea1SDimitry Andric  */
419*0fca6ea1SDimitry Andric ITT_EXTERN_C void JITAPI FinalizeThread(void)
420*0fca6ea1SDimitry Andric {
421*0fca6ea1SDimitry Andric     if (threadLocalStorageHandle)
422*0fca6ea1SDimitry Andric     {
423*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
424*0fca6ea1SDimitry Andric         pThreadStack threadStack =
425*0fca6ea1SDimitry Andric             (pThreadStack)TlsGetValue (threadLocalStorageHandle);
426*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
427*0fca6ea1SDimitry Andric         pThreadStack threadStack =
428*0fca6ea1SDimitry Andric             (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
429*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
430*0fca6ea1SDimitry Andric         if (threadStack)
431*0fca6ea1SDimitry Andric         {
432*0fca6ea1SDimitry Andric             free (threadStack);
433*0fca6ea1SDimitry Andric             threadStack = NULL;
434*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
435*0fca6ea1SDimitry Andric             TlsSetValue (threadLocalStorageHandle, threadStack);
436*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
437*0fca6ea1SDimitry Andric             pthread_setspecific(threadLocalStorageHandle, threadStack);
438*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
439*0fca6ea1SDimitry Andric         }
440*0fca6ea1SDimitry Andric     }
441*0fca6ea1SDimitry Andric }
442*0fca6ea1SDimitry Andric 
443*0fca6ea1SDimitry Andric /*
444*0fca6ea1SDimitry Andric  * This function should be called by the user when the process ends,
445*0fca6ea1SDimitry Andric  * to free the local storage index
446*0fca6ea1SDimitry Andric */
447*0fca6ea1SDimitry Andric ITT_EXTERN_C void JITAPI FinalizeProcess(void)
448*0fca6ea1SDimitry Andric {
449*0fca6ea1SDimitry Andric     if (m_libHandle)
450*0fca6ea1SDimitry Andric     {
451*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
452*0fca6ea1SDimitry Andric         FreeLibrary(m_libHandle);
453*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
454*0fca6ea1SDimitry Andric         dlclose(m_libHandle);
455*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
456*0fca6ea1SDimitry Andric         m_libHandle = NULL;
457*0fca6ea1SDimitry Andric     }
458*0fca6ea1SDimitry Andric 
459*0fca6ea1SDimitry Andric     if (threadLocalStorageHandle)
460*0fca6ea1SDimitry Andric #if ITT_PLATFORM==ITT_PLATFORM_WIN
461*0fca6ea1SDimitry Andric         TlsFree (threadLocalStorageHandle);
462*0fca6ea1SDimitry Andric #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
463*0fca6ea1SDimitry Andric     pthread_key_delete(threadLocalStorageHandle);
464*0fca6ea1SDimitry Andric #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
465*0fca6ea1SDimitry Andric }
466*0fca6ea1SDimitry Andric 
467*0fca6ea1SDimitry Andric /*
468*0fca6ea1SDimitry Andric  * This function should be called by the user for any method once.
469*0fca6ea1SDimitry Andric  * The function will return a unique method ID, the user should maintain
470*0fca6ea1SDimitry Andric  * the ID for each method
471*0fca6ea1SDimitry Andric  */
472*0fca6ea1SDimitry Andric ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID(void)
473*0fca6ea1SDimitry Andric {
474*0fca6ea1SDimitry Andric     static unsigned int methodID = 0x100000;
475*0fca6ea1SDimitry Andric 
476*0fca6ea1SDimitry Andric     if (methodID == 0)
477*0fca6ea1SDimitry Andric         return 0;  /* ERROR : this is not a valid value */
478*0fca6ea1SDimitry Andric 
479*0fca6ea1SDimitry Andric     return methodID++;
480*0fca6ea1SDimitry Andric }
481