Jump to content

Sample Code to invoke managed code inside profiling API


sirp

Recommended Posts


ProfilerCallback.cpp
// This is the function that will invoke the managed code through COM interop on another thread// this function creates the CCW object// [in] this pointer
DWORD WINAPI CreateManagedStub(LPVOID lpParam)
{
_ManagedStub * pIManagedStub = NULL;
HRESULT hr = CoCreateInstance(CLSID_ManagedStub, NULL, CLSCTX_INPROC_SERVER, IID__ManagedStub, (void **)&pIManagedStub);
if (FAILED(hr))
{
printf("Fail to CoCreateInstance on ManagedStub class 0x%x\n", hr);
return 1;
}
if (pIManagedStub == NULL)
{
printf("pIManagedStub is null 0x%x\n", hr);
return 1;
} // we have the managed instance now.
((CProfilerCallback*)lpParam)->m_pIManagedStub = pIManagedStub;
return 0;
}// this function is the actual caller to the managed world.
// this function can be used to get a managed dynamic method token back
// [in] this pointer; method token; assembly name
// [out] delegate type name
DWORD WINAPI ManagedPreStub(LPVOID lpParam)
{
PMYDATA pData = (PMYDATA)lpParam;
LPWSTR delegateName = NULL;
if (pData->thisObj->m_pIManagedStub == NULL)
{
printf("pData->thisObj->m_pIManagedStub is null");
return 1;
}
HRESULT hr = pData->thisObj->m_pIManagedStub->PreStub(pData->assemblyName, pData->methodTk, &delegateName);
if (FAILED(hr))
{
printf("Fail to Call PreStub 0x%x\n", hr);
}
wcscpy_s(pData->delegateName, (wchar_t*)delegateName);
return 0;}......// Profiler callback functionHRESULT CProfilerCallback::JITCompilationstarted(UINT functionId,
BOOL fIsSafeToBlock)
{
HANDLE hThread = NULL;
DWORD dwThreadId;
/////////////////////////////////////////////////////////
// We dont want to continue on JITCompilationstarted if the thread is for the "managed code" we are to call from this callback. // We store these thread ids in our skip thread hashtable // 1. if the JITCompilationstarted is on one of the skipping thread, avoid following steps.
DWORD currentThreadId = GetCurrentThreadId();
if (m_SkipJCHashTable->PLookup(currentThreadId))
return S_OK; // create the ManagedStub object
if (m_pIManagedStub==NULL) // if it is already created, no need to create twice
{
hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateManagedStub, this, 0, &dwThreadId); // add the thread Id to skip pool so that JITCompilationstarted will do nothing on that thread. m_SkipJCHashTable->SetAt(dwThreadId, 0);
if (hThread != NULL)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
m_SkipJCHashTable->RemoveKey(dwThreadId);
}.... ///////////////////////////////////////////////////////
// try to define a managed dynamic method and get the dynamic method method token
// prepare the parameters to be passed in
PMYDATA pData = (PMYDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA)); if( pData == NULL )
goto exit; pData->assemblyName = wszAssemblyName;
pData->methodTk = tkMethod;
pData->thisObj = this; ProfilerPrintf("Working on asm %ws func %ws.", wszAssemblyName, wszFunctionName); hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ManagedPreStub, pData, 0, &dwThreadId);
m_SkipJCHashTable->SetAt(dwThreadId, 0);
if (hThread != NULL)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
m_SkipJCHashTable->RemoveKey(dwThreadId); // we free up the memory here instead of in the thread because we want some return value back.
wchar_t wszDelegateName[512]; if (pData->delegateName == NULL)
return S_OK;
// copy the return value out
wcsncpy_s(wszDelegateName, _countof(pData->delegateName), pData->delegateName, _countof(pData->delegateName)); HeapFree(GetProcessHeap(), 0, pData);...We have these definitions in ProfilerCallback.h:private: CMap<DWORD, DWORD, int, int> * m_SkipJCHashTable; ... Enjoy!
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...