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
iJIT_NotifyEvent(iJIT_JVM_EVENT event_type,void * EventSpecificData)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
iJIT_RegisterCallbackEx(void * userdata,iJIT_ModeChangedEx NewModeCallBackFuncEx)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 */
iJIT_IsProfilingActive(void)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 */
loadiJIT_Funcs(void)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 */
FinalizeThread(void)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 */
FinalizeProcess(void)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 */
iJIT_GetNewMethodID(void)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