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