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