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