Imported Upstream version 5.2.0.175

Former-commit-id: bb0468d0f257ff100aa895eb5fe583fb5dfbf900
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-06-07 13:16:24 +00:00
parent 4bdbaf4a88
commit 966bba02bb
8776 changed files with 346420 additions and 149650 deletions

View File

@@ -209,6 +209,10 @@ extern "C" void RhpUniversalTransition_DebugStepTailCall()
{
throw "RhpUniversalTransition_DebugStepTailCall";
}
extern "C" void CCWAddRef()
{
throw "CCWAddRef";
}
void* RtRHeaderWrapper();
@@ -262,7 +266,7 @@ static const pfn c_classlibFunctions[] = {
#endif // !CPPCODEGEN
extern "C" void InitializeModules(void ** modules, int count);
extern "C" void InitializeModules(void* osModule, void ** modules, int count);
#if defined(_WIN32)
extern "C" int __managed__Main(int argc, wchar_t* argv[]);
@@ -282,10 +286,14 @@ int main(int argc, char* argv[])
return -1;
#ifndef CPPCODEGEN
void *osModule;
#if defined(_WIN32)
if (!RhpRegisterCoffModule(GetModuleHandleW(NULL),
osModule = GetModuleHandleW(NULL);
if (!RhpRegisterCoffModule(osModule,
#else // _WIN32
if (!RhpRegisterUnixModule(PalGetModuleHandleFromPointer((void*)&main),
osModule = PalGetModuleHandleFromPointer((void*)&main);
if (!RhpRegisterUnixModule(osModule,
#endif // _WIN32
(void*)&__managedcode_a, (uint32_t)((char *)&__managedcode_z - (char*)&__managedcode_a),
(void **)&c_classlibFunctions, _countof(c_classlibFunctions)))
@@ -300,9 +308,9 @@ int main(int argc, char* argv[])
#endif
#ifndef CPPCODEGEN
InitializeModules(__modules_a, (int)((__modules_z - __modules_a)));
InitializeModules(osModule, __modules_a, (int)((__modules_z - __modules_a)));
#else // !CPPCODEGEN
InitializeModules((void**)RtRHeaderWrapper(), 2);
InitializeModules(nullptr, (void**)RtRHeaderWrapper(), 2);
#endif // !CPPCODEGEN
int retval;

View File

@@ -59,6 +59,21 @@ extern "C"
throw "CoGetApartmentType";
}
void CoUnmarshalInterface()
{
throw "CoUnmarshalInterface";
}
void CoMarshalInterface()
{
throw "CoMarshalInterface";
}
void CoGetMarshalSizeMax()
{
throw "CoGetMarshalSizeMax";
}
void CreateEventExW()
{
throw "CreateEventExW";

View File

@@ -22,7 +22,7 @@ function(clr_unknown_arch)
if (WIN32)
message(FATAL_ERROR "Only AMD64 and I386 are supported")
else()
message(FATAL_ERROR "Only AMD64, ARM64 and ARM are supported")
message(FATAL_ERROR "Only AMD64, ARM64, ARM and ARMEL are supported")
endif()
endfunction()
@@ -32,7 +32,12 @@ elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
add_definitions(-DBIT32=1)
# Because we don't use CMAKE_C_COMPILER/CMAKE_CXX_COMPILER to use clang
# we have to set the triple by adding a compiler argument
add_compile_options(-target armv7-linux-gnueabihf)
if(TOOLCHAIN STREQUAL arm-linux-gnueabi)
add_compile_options(-target armv7-linux-gnueabi)
add_compile_options(-mfloat-abi=softfp)
else ()
add_compile_options(-target armv7-linux-gnueabihf)
endif ()
add_compile_options(-mthumb)
add_compile_options(-mfpu=vfpv3)
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)

View File

@@ -33,9 +33,7 @@ ASM_OFFSET( 4, 8, Array, m_Length)
ASM_OFFSET( 0, 0, EEType, m_usComponentSize)
ASM_OFFSET( 2, 2, EEType, m_usFlags)
ASM_OFFSET( 4, 4, EEType, m_uBaseSize)
#if defined(CORERT)
// If this ever changes, you must update src\ILCompiler.Compiler\src\Compiler\DependencyAnalysis\EETypeNode.cs GetVTableOffset()
// to reflect the updated VTable offset
#if defined(EETYPE_TYPE_MANAGER)
ASM_OFFSET( 18, 20, EEType, m_VTable)
#else
ASM_OFFSET( 14, 18, EEType, m_VTable)

View File

@@ -4,6 +4,8 @@ set(COMMON_RUNTIME_SOURCES
CachedInterfaceDispatch.cpp
Crst.cpp
DebugEventSource.cpp
DebugFuncEval.cpp
DebuggerHook.cpp
dllmain.cpp
eetype.cpp
EHHelpers.cpp
@@ -136,9 +138,12 @@ endif()
list(APPEND RUNTIME_SOURCES_ARCH_ASM
${ARCH_SOURCES_DIR}/AllocFast.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/CallDescrWorker.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/CallingConventionConverterHelpers.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/ExceptionHandling.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/Interlocked.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/PInvoke.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/InteropThunksHelpers.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/StubDispatch.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/UniversalTransition.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/WriteBarriers.${ASM_SUFFIX}
@@ -159,6 +164,7 @@ add_definitions(-DVERIFY_HEAP)
add_definitions(-DCORERT)
add_definitions(-DFEATURE_CACHED_INTERFACE_DISPATCH)
add_definitions(-D_LIB)
add_definitions(-DEETYPE_TYPE_MANAGER)
if(WIN32)
# There is a problem with undefined symbol g_pConfig, windows don't care since it is in template method, but clang does

View File

@@ -1,7 +1,12 @@
#pragma optimize( "", off )
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#ifndef __COMMONMACROS_H__
#define __COMMONMACROS_H__
// Some of our header files are shared with the binder, which needs the _TARGET_* macros defined
#if defined(_TARGET_AMD64_)
#elif defined(_TARGET_X86_)
@@ -229,3 +234,5 @@ typedef int32_t HRESULT;
#define UNREFERENCED_PARAMETER(P) (void)(P)
#endif // !defined(_INC_WINDOWS) && !defined(BINDER)
#endif // GCENV_INCLUDED
#endif // __COMMONMACROS_H__

View File

@@ -97,6 +97,17 @@ void DebugEventSource::SendExceptionFirstPassFrameEnteredEvent(CORDB_ADDRESS ipI
SendRawEvent(&payload);
}
void DebugEventSource::SendCustomEvent(void* payload, int length)
{
if (!EventEnabled(DEBUG_EVENT_TYPE_CUSTOM))
return;
DebugEventPayload rawPayload;
rawPayload.type = DEBUG_EVENT_TYPE_CUSTOM;
rawPayload.Custom.payload = (CORDB_ADDRESS)payload;
rawPayload.Custom.length = length;
SendRawEvent(&rawPayload);
}
//---------------------------------------------------------------------------------------
//
// Sends a raw managed debug event to the debugger.
@@ -201,4 +212,10 @@ COOP_PINVOKE_HELPER(ExceptionEventKind, RhpGetRequestedExceptionEvents, ())
return (ExceptionEventKind)mask;
}
//Called by the C# func eval code to hand shake with the debugger
COOP_PINVOKE_HELPER(void, RhpSendCustomEventToDebugger, (void* payload, int length))
{
DebugEventSource::SendCustomEvent(payload, length);
}
#endif //!DACCESS_COMPILE

View File

@@ -20,6 +20,7 @@ typedef UInt64 CORDB_ADDRESS;
#ifndef DACCESS_COMPILE
struct DebugEventPayload;
class Module;
class DebugEventSource
{
@@ -30,7 +31,7 @@ public:
static void SendExceptionCatchHandlerFoundEvent(CORDB_ADDRESS handlerIP, CORDB_ADDRESS HandlerFrameSP);
static void SendExceptionUnhandledEvent();
static void SendExceptionFirstPassFrameEnteredEvent(CORDB_ADDRESS ipInFrame, CORDB_ADDRESS frameSP);
static void SendCustomEvent(void* payload, int length);
private:
static void SendRawEvent(DebugEventPayload* payload);
};

View File

@@ -0,0 +1,54 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "common.h"
#include "CommonTypes.h"
#include "DebugFuncEval.h"
GVAL_IMPL_INIT(UInt64, g_FuncEvalTarget, 0);
GVAL_IMPL_INIT(UInt32, g_FuncEvalParameterBufferSize, 0);
#ifndef DACCESS_COMPILE
void* DebugFuncEval::GetFuncEvalTarget()
{
return (void*)g_FuncEvalTarget;
}
UInt32 DebugFuncEval::GetFuncEvalParameterBufferSize()
{
return g_FuncEvalParameterBufferSize;
}
/// <summary>
/// Retrieve the global FuncEval target address.
/// </summary>
/// <remarks>
/// During debugging, if a FuncEval is requested,
/// the func eval infrastructure needs to know which function to call, and
/// the C# supporting code will call this API to obtain the FuncEval target address.
/// By that time, the value should have been set through the UpdateFuncEvalTarget() method
/// on the ISosRedhawk7 interface.
/// </remarks>
EXTERN_C REDHAWK_API void* __cdecl RhpGetFuncEvalTargetAddress()
{
return DebugFuncEval::GetFuncEvalTarget();
}
/// <summary>
/// Retrieve the global FuncEval parameter buffer size.
/// </summary>
/// <remarks>
/// During debugging, if a FuncEval is requested,
/// the func eval infrastructure needs to know how much buffer to allocate for the debugger to
/// write the parameter information in. The C# supporting code will call this API to obtain the
/// buffer size. By that time, the value should have been set through the UpdateFuncEvalParameterSize()
/// method on the ISosRedhawk7 interface.
/// </remarks>
EXTERN_C REDHAWK_API UInt32 __cdecl RhpGetFuncEvalParameterBufferSize()
{
return DebugFuncEval::GetFuncEvalParameterBufferSize();
}
#endif //!DACCESS_COMPILE

View File

@@ -0,0 +1,49 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// -----------------------------------------------------------------------------------------------------------
// Support for evaluating expression in the debuggee during debugging
// -----------------------------------------------------------------------------------------------------------
#ifndef __DEBUG_FUNC_EVAL_H__
#define __DEBUG_FUNC_EVAL_H__
#include "common.h"
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#ifndef DACCESS_COMPILE
class DebugFuncEval
{
public:
/// <summary>
/// Retrieve the global FuncEval target address
/// </summary>
/// <remarks>
/// During debugging, if a FuncEval is requested,
/// The func eval infrastructure needs to know which function to call, and
/// It will call this API to obtain the target address.
/// By the time, the value should have been set through the UpdateFuncEvalTarget() method
/// on the ISosRedhawk7 interface.
/// </remarks>
static void* GetFuncEvalTarget();
/// <summary>
/// Retrieve the global FuncEval parameter buffer size.
/// </summary>
/// <remarks>
/// During debugging, if a FuncEval is requested,
/// the func eval infrastructure needs to know how much buffer to allocate for the debugger to
/// write the parameter information in. The C# supporting code will call this API to obtain the
/// buffer size. By that time, the value should have been set through the UpdateFuncEvalParameterSize()
/// method on the ISosRedhawk7 interface.
/// </remarks>
static UInt32 GetFuncEvalParameterBufferSize();
};
#endif //!DACCESS_COMPILE
#endif // __DEBUG_FUNC_EVAL_H__

View File

@@ -0,0 +1,77 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "common.h"
#include "CommonTypes.h"
#include "DebuggerHook.h"
#include "DebugEventSource.h"
GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0);
#ifndef DACCESS_COMPILE
// TODO: Tab to space, overall, just to make sure I will actually do it :)
// TODO: This structure needs to match with DBI
struct FuncEvalParameterCommand
{
// TODO: Consider giving these command code a good enumeration to define what they really are
UInt32 commandCode;
UInt32 unused; /* To make the data structure 64 bit aligned */
UInt64 bufferAddress;
};
// TODO: This structure needs to match with DBI
struct GcProtectionRequest
{
UInt16 type;
UInt16 size;
UInt64 address;
};
/* static */ void DebuggerHook::OnBeforeGcCollection()
{
if (g_numGcProtectionRequests > 0)
{
// The debugger has some request with respect to GC protection.
// Here we are allocating a buffer to store them
GcProtectionRequest* requests = new (nothrow) GcProtectionRequest[g_numGcProtectionRequests];
// TODO: We need to figure out how to communicate this broken promise to the debugger
// Notifying the debugger the buffer is ready to use
FuncEvalParameterCommand command;
command.commandCode = 2;
command.bufferAddress = (uint64_t)requests;
DebugEventSource::SendCustomEvent((void*)&command, sizeof(command));
// ... debugger magic happen here ...
// The debugger has filled the requests array
for (uint32_t i = 0; i < g_numGcProtectionRequests; i++)
{
if (requests[i].type == 1)
{
// If the request requires extra memory, allocate for it
requests[i].address = (uint64_t)new (nothrow) uint8_t[requests[i].size];
}
}
command.commandCode = 3;
DebugEventSource::SendCustomEvent((void*)&command, sizeof(command));
// ... debugger magic happen here again ...
for (uint32_t i = 0; i < g_numGcProtectionRequests; i++)
{
if (requests[i].type == 1)
{
// What shall I do?
}
}
g_numGcProtectionRequests = 0;
}
}
#endif // !DACCESS_COMPILE

View File

@@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// -----------------------------------------------------------------------------------------------------------
// Support for evaluating expression in the debuggee during debugging
// -----------------------------------------------------------------------------------------------------------
#ifndef __DEBUGGER_HOOK_H__
#define __DEBUGGER_HOOK_H__
#include "common.h"
#include "CommonTypes.h"
#ifdef DACCESS_COMPILE
#include "CommonMacros.h"
#endif
#include "daccess.h"
#ifndef DACCESS_COMPILE
class DebuggerHook
{
public:
static void OnBeforeGcCollection();
};
#endif //!DACCESS_COMPILE
#endif // __DEBUGGER_HOOK_H__

View File

@@ -367,14 +367,11 @@ static UIntNative UnwindWriteBarrierToCaller(
#endif
#if defined(_AMD64_) || defined(_X86_)
// simulate a ret instruction
UIntNative sp = pContext->GetSp(); // get the stack pointer
UIntNative adjustedFaultingIP = *(UIntNative *)sp - 5; // call instruction will be 6 bytes - act as if start of call instruction + 1 were the faulting IP
UIntNative sp = pContext->GetSp();
UIntNative adjustedFaultingIP = *(UIntNative *)sp;
pContext->SetSp(sp+sizeof(UIntNative)); // pop the stack
#elif defined(_ARM_)
UIntNative adjustedFaultingIP = pContext->GetLr() - 2; // bl instruction will be 4 bytes - act as if start of call instruction + 2 were the faulting IP
#elif defined(_ARM64_)
PORTABILITY_ASSERT("@TODO: FIXME:ARM64");
UIntNative adjustedFaultingIP = -1;
#elif defined(_ARM_) || defined(_ARM64_)
UIntNative adjustedFaultingIP = pContext->GetLr();
#else
#error "Unknown Architecture"
#endif
@@ -390,11 +387,14 @@ Int32 __stdcall RhpHardwareExceptionHandler(UIntNative faultCode, UIntNative fau
ICodeManager * pCodeManager = GetRuntimeInstance()->FindCodeManagerByAddress((PTR_VOID)faultingIP);
if ((pCodeManager != NULL) || (faultCode == STATUS_ACCESS_VIOLATION && InWriteBarrierHelper(faultingIP)))
{
// Make sure that the OS does not use our internal fault codes
ASSERT(faultCode != STATUS_REDHAWK_NULL_REFERENCE && faultCode != STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE);
if (faultCode == STATUS_ACCESS_VIOLATION)
{
if (faultAddress < NULL_AREA_SIZE)
{
faultCode = STATUS_REDHAWK_NULL_REFERENCE;
faultCode = pCodeManager ? STATUS_REDHAWK_NULL_REFERENCE : STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE;
}
if (pCodeManager == NULL)
@@ -405,7 +405,9 @@ Int32 __stdcall RhpHardwareExceptionHandler(UIntNative faultCode, UIntNative fau
}
else if (faultCode == STATUS_STACK_OVERFLOW)
{
ASSERT_UNCONDITIONALLY("managed stack overflow");
// Do not use ASSERT_UNCONDITIONALLY here. It will crash because of it consumes too much stack.
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
@@ -429,10 +431,16 @@ Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs)
UIntNative faultCode = pExPtrs->ExceptionRecord->ExceptionCode;
if ((pCodeManager != NULL) || (faultCode == STATUS_ACCESS_VIOLATION && InWriteBarrierHelper(faultingIP)))
{
// Make sure that the OS does not use our internal fault codes
ASSERT(faultCode != STATUS_REDHAWK_NULL_REFERENCE && faultCode != STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE);
if (faultCode == STATUS_ACCESS_VIOLATION)
{
if (pExPtrs->ExceptionRecord->ExceptionInformation[1] < NULL_AREA_SIZE)
faultCode = STATUS_REDHAWK_NULL_REFERENCE;
{
faultCode = pCodeManager ? STATUS_REDHAWK_NULL_REFERENCE : STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE;
}
if (pCodeManager == NULL)
{
// we were AV-ing in a write barrier helper - unwind our way to our caller
@@ -441,8 +449,10 @@ Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs)
}
else if (faultCode == STATUS_STACK_OVERFLOW)
{
ASSERT_UNCONDITIONALLY("managed stack overflow");
RhFailFast2(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord);
// Do not use ASSERT_UNCONDITIONALLY here. It will crash because of it consumes too much stack.
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
PalRaiseFailFastException(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord, 0);
}
pExPtrs->ContextRecord->SetIp((UIntNative)&RhpThrowHwEx);
@@ -478,7 +488,7 @@ Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs)
// Generally any form of hardware exception within the runtime itself is considered a fatal error.
// Note this includes the managed code within the runtime.
ASSERT_UNCONDITIONALLY("Hardware exception raised inside the runtime.");
RhFailFast2(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord);
PalRaiseFailFastException(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord, 0);
}
}

View File

@@ -16,6 +16,144 @@
#include "shash.h"
#include "module.h"
#include "regdisplay.h"
#include "StackFrameIterator.h"
#include "thread.h"
#include "threadstore.h"
#include "threadstore.inl"
#include "thread.inl"
GPTR_DECL(Thread, g_pFinalizerThread);
CLREventStatic g_FinalizerEvent;
CLREventStatic g_FinalizerDoneEvent;
// Finalizer method implemented by redhawkm.
extern "C" void __cdecl ProcessFinalizers();
// Unmanaged front-end to the finalizer thread. We require this because at the point the GC creates the
// finalizer thread we're still executing the DllMain for RedhawkU. At that point we can't run managed code
// successfully (in particular module initialization code has not run for RedhawkM). Instead this method waits
// for the first finalization request (by which time everything must be up and running) and kicks off the
// managed portion of the thread at that point.
UInt32 WINAPI FinalizerStart(void* pContext)
{
HANDLE hFinalizerEvent = (HANDLE)pContext;
ThreadStore::AttachCurrentThread();
Thread * pThread = GetThread();
// Disallow gcstress on this thread to work around the current implementation's limitation that it will
// get into an infinite loop if performed on the finalizer thread.
pThread->SetSuppressGcStress();
g_pFinalizerThread = PTR_Thread(pThread);
// Wait for a finalization request.
UInt32 uResult = PalWaitForSingleObjectEx(hFinalizerEvent, INFINITE, FALSE);
ASSERT(uResult == WAIT_OBJECT_0);
// Since we just consumed the request (and the event is auto-reset) we must set the event again so the
// managed finalizer code will immediately start processing the queue when we run it.
UInt32_BOOL fResult = PalSetEvent(hFinalizerEvent);
ASSERT(fResult);
// Run the managed portion of the finalizer. Until we implement (non-process) shutdown this call will
// never return.
ProcessFinalizers();
ASSERT(!"Finalizer thread should never return");
return 0;
}
bool RhStartFinalizerThread()
{
#ifdef APP_LOCAL_RUNTIME
//
// On app-local runtimes, if we're running with the fallback PAL code (meaning we don't have IManagedRuntimeServices)
// then we use the WinRT ThreadPool to create the finalizer thread. This might fail at startup, if the current thread
// hasn't been CoInitialized. So we need to retry this later. We use fFinalizerThreadCreated to track whether we've
// successfully created the finalizer thread yet, and also as a sort of lock to make sure two threads don't try
// to create the finalizer thread at the same time.
//
static volatile Int32 fFinalizerThreadCreated;
if (Interlocked::Exchange(&fFinalizerThreadCreated, 1) != 1)
{
if (!PalStartFinalizerThread(FinalizerStart, (void*)g_FinalizerEvent.GetOSEvent()))
{
// Need to try again another time...
Interlocked::Exchange(&fFinalizerThreadCreated, 0);
}
}
// We always return true, so the GC can start even if we failed.
return true;
#else // APP_LOCAL_RUNTIME
//
// If this isn't an app-local runtime, then the PAL will just call CreateThread directly, which should succeed
// under normal circumstances.
//
if (PalStartFinalizerThread(FinalizerStart, (void*)g_FinalizerEvent.GetOSEvent()))
return true;
else
return false;
#endif // APP_LOCAL_RUNTIME
}
bool RhInitializeFinalization()
{
// Allocate the events the GC expects the finalizer thread to have. The g_FinalizerEvent event is signalled
// by the GC whenever it completes a collection where it found otherwise unreachable finalizable objects.
// The g_FinalizerDoneEvent is set by the finalizer thread every time it wakes up and drains the
// queue of finalizable objects. It's mainly used by GC.WaitForPendingFinalizers().
if (!g_FinalizerEvent.CreateAutoEventNoThrow(false))
return false;
if (!g_FinalizerDoneEvent.CreateManualEventNoThrow(false))
return false;
// Create the finalizer thread itself.
if (!RhStartFinalizerThread())
return false;
return true;
}
void RhEnableFinalization()
{
g_FinalizerEvent.Set();
}
EXTERN_C REDHAWK_API void __cdecl RhWaitForPendingFinalizers(UInt32_BOOL allowReentrantWait)
{
// This must be called via p/invoke rather than RuntimeImport since it blocks and could starve the GC if
// called in cooperative mode.
ASSERT(!GetThread()->IsCurrentThreadInCooperativeMode());
// Can't call this from the finalizer thread itself.
if (GetThread() != g_pFinalizerThread)
{
// Clear any current indication that a finalization pass is finished and wake the finalizer thread up
// (if there's no work to do it'll set the done event immediately).
g_FinalizerDoneEvent.Reset();
g_FinalizerEvent.Set();
#ifdef APP_LOCAL_RUNTIME
// We may have failed to create the finalizer thread at startup.
// Try again now.
RhStartFinalizerThread();
#endif
// Wait for the finalizer thread to get back to us.
g_FinalizerDoneEvent.Wait(INFINITE, false, allowReentrantWait);
}
}
// Block the current thread until at least one object needs to be finalized (returns true) or memory is low
// (returns false and the finalizer thread should initiate a garbage collection).
@@ -39,13 +177,13 @@ EXTERN_C REDHAWK_API UInt32_BOOL __cdecl RhpWaitForFinalizerRequest()
HANDLE lowMemEvent = NULL;
#if 0 // TODO: hook up low memory notification
lowMemEvent = pHeap->GetLowMemoryNotificationEvent();
HANDLE rgWaitHandles[] = { FinalizerThread::GetFinalizerEvent(), lowMemEvent };
HANDLE rgWaitHandles[] = { g_FinalizerEvent.GetOSEvent(), lowMemEvent };
UInt32 cWaitHandles = (fLastEventWasLowMemory || (lowMemEvent == NULL)) ? 1 : 2;
UInt32 uTimeout = fLastEventWasLowMemory ? 2000 : INFINITE;
UInt32 uResult = PalWaitForMultipleObjectsEx(cWaitHandles, rgWaitHandles, FALSE, uTimeout, FALSE);
#else
UInt32 uResult = PalWaitForSingleObjectEx(FinalizerThread::GetFinalizerEvent(), INFINITE, FALSE);
UInt32 uResult = PalWaitForSingleObjectEx(g_FinalizerEvent.GetOSEvent(), INFINITE, FALSE);
#endif
switch (uResult)
@@ -77,7 +215,7 @@ EXTERN_C REDHAWK_API UInt32_BOOL __cdecl RhpWaitForFinalizerRequest()
// Indicate that the current round of finalizations is complete.
EXTERN_C REDHAWK_API void __cdecl RhpSignalFinalizationComplete()
{
FinalizerThread::SignalFinalizationDone(TRUE);
g_FinalizerDoneEvent.Set();
}
//

View File

@@ -25,15 +25,6 @@
#include "threadstore.inl"
#include "thread.inl"
EXTERN_C REDHAWK_API void __cdecl RhWaitForPendingFinalizers(UInt32_BOOL allowReentrantWait)
{
// This must be called via p/invoke rather than RuntimeImport since it blocks and could starve the GC if
// called in cooperative mode.
ASSERT(!GetThread()->IsCurrentThreadInCooperativeMode());
FinalizerThread::Wait(INFINITE, allowReentrantWait);
}
EXTERN_C REDHAWK_API void __cdecl RhpCollect(UInt32 uGeneration, UInt32 uMode)
{
// This must be called via p/invoke rather than RuntimeImport to make the stack crawlable.
@@ -65,6 +56,28 @@ EXTERN_C REDHAWK_API Int64 __cdecl RhpGetGcTotalMemory()
return ret;
}
EXTERN_C REDHAWK_API Int32 __cdecl RhpStartNoGCRegion(Int64 totalSize, Boolean hasLohSize, Int64 lohSize, Boolean disallowFullBlockingGC)
{
Thread *pCurThread = GetThread();
ASSERT(!pCurThread->IsCurrentThreadInCooperativeMode());
pCurThread->SetupHackPInvokeTunnel();
pCurThread->DisablePreemptiveMode();
int result = GCHeapUtilities::GetGCHeap()->StartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC);
pCurThread->EnablePreemptiveMode();
return result;
}
EXTERN_C REDHAWK_API Int32 __cdecl RhpEndNoGCRegion()
{
ASSERT(!GetThread()->IsCurrentThreadInCooperativeMode());
return GCHeapUtilities::GetGCHeap()->EndNoGCRegion();
}
COOP_PINVOKE_HELPER(void, RhSuppressFinalize, (OBJECTREF refObj))
{
if (!refObj->get_EEType()->HasFinalizer())
@@ -99,9 +112,9 @@ COOP_PINVOKE_HELPER(Int32, RhGetGcLatencyMode, ())
return GCHeapUtilities::GetGCHeap()->GetGcLatencyMode();
}
COOP_PINVOKE_HELPER(void, RhSetGcLatencyMode, (Int32 newLatencyMode))
COOP_PINVOKE_HELPER(Int32, RhSetGcLatencyMode, (Int32 newLatencyMode))
{
GCHeapUtilities::GetGCHeap()->SetGcLatencyMode(newLatencyMode);
return GCHeapUtilities::GetGCHeap()->SetGcLatencyMode(newLatencyMode);
}
COOP_PINVOKE_HELPER(Boolean, RhIsServerGc, ())
@@ -153,3 +166,34 @@ COOP_PINVOKE_HELPER(Int64, RhGetLastGCDuration, (Int32 generation))
{
return GCHeapUtilities::GetGCHeap()->GetLastGCDuration(generation);
}
COOP_PINVOKE_HELPER(Boolean, RhRegisterForFullGCNotification, (Int32 maxGenerationThreshold, Int32 largeObjectHeapThreshold))
{
ASSERT(maxGenerationThreshold >= 1 && maxGenerationThreshold <= 99);
ASSERT(largeObjectHeapThreshold >= 1 && largeObjectHeapThreshold <= 99);
return GCHeapUtilities::GetGCHeap()->RegisterForFullGCNotification(maxGenerationThreshold, largeObjectHeapThreshold)
? Boolean_true : Boolean_false;
}
COOP_PINVOKE_HELPER(Boolean, RhCancelFullGCNotification, ())
{
return GCHeapUtilities::GetGCHeap()->CancelFullGCNotification() ? Boolean_true : Boolean_false;
}
COOP_PINVOKE_HELPER(Int32, RhWaitForFullGCApproach, (Int32 millisecondsTimeout))
{
ASSERT(millisecondsTimeout >= -1);
ASSERT(GetThread()->IsCurrentThreadInCooperativeMode());
int timeout = millisecondsTimeout == -1 ? INFINITE : millisecondsTimeout;
return GCHeapUtilities::GetGCHeap()->WaitForFullGCApproach(millisecondsTimeout);
}
COOP_PINVOKE_HELPER(Int32, RhWaitForFullGCComplete, (Int32 millisecondsTimeout))
{
ASSERT(millisecondsTimeout >= -1);
ASSERT(GetThread()->IsCurrentThreadInCooperativeMode());
int timeout = millisecondsTimeout == -1 ? INFINITE : millisecondsTimeout;
return GCHeapUtilities::GetGCHeap()->WaitForFullGCComplete(millisecondsTimeout);
}

View File

@@ -75,6 +75,7 @@ enum class ClasslibFunctionId
FailFast = 1,
UnhandledExceptionHandler = 2,
AppendExceptionStackFrame = 3,
CheckStaticClassConstruction = 4,
};
class ICodeManager

View File

@@ -62,6 +62,15 @@ EXTERN_C REDHAWK_API UInt32_BOOL __cdecl RhYield()
return PalSwitchToThread();
}
EXTERN_C REDHAWK_API void __cdecl RhFlushProcessWriteBuffers()
{
// This must be called via p/invoke -- it's a wait operation and we don't want to block thread suspension on this.
ASSERT_MSG(!ThreadStore::GetCurrentThread()->IsCurrentThreadInCooperativeMode(),
"You must p/invoke to RhFlushProcessWriteBuffers");
PalFlushProcessWriteBuffers();
}
// Return the DispatchMap pointer of a type
COOP_PINVOKE_HELPER(DispatchMap*, RhGetDispatchMapForType, (EEType * pEEType))
{
@@ -75,7 +84,7 @@ COOP_PINVOKE_HELPER(DispatchMap*, RhGetDispatchMapForType, (EEType * pEEType))
// modules are available based on the return count. It is also possible to call this method without an array,
// in which case just the module count is returned (note that it's still possible for the module count to
// increase between calls to this method).
COOP_PINVOKE_HELPER(UInt32, RhGetLoadedModules, (Array * pResultArray))
COOP_PINVOKE_HELPER(UInt32, RhGetLoadedOSModules, (Array * pResultArray))
{
// Note that we depend on the fact that this is a COOP helper to make writing into an unpinned array safe.
@@ -99,11 +108,69 @@ COOP_PINVOKE_HELPER(UInt32, RhGetLoadedModules, (Array * pResultArray))
}
END_FOREACH_MODULE
ReaderWriterLock::ReadHolder read(&GetRuntimeInstance()->GetTypeManagerLock());
RuntimeInstance::OsModuleList osModules = GetRuntimeInstance()->GetOsModuleList();
for (RuntimeInstance::OsModuleList::Iterator iter = osModules.Begin(); iter != osModules.End(); iter++)
{
if (pResultArray && (cModules < cResultArrayElements))
pResultElements[cModules] = iter->m_osModule;
cModules++;
}
return cModules;
}
COOP_PINVOKE_HELPER(HANDLE, RhGetModuleFromPointer, (PTR_VOID pPointerVal))
// Get the list of currently loaded Redhawk modules (as OS HMODULE handles or TypeManager pointers as appropriate).
// The caller provides a reference
// to an array of pointer-sized elements and we return the total number of modules currently loaded (whether
// that is less than, equal to or greater than the number of elements in the array). If there are more modules
// loaded than the array will hold then the array is filled to capacity and the caller can tell further
// modules are available based on the return count. It is also possible to call this method without an array,
// in which case just the module count is returned (note that it's still possible for the module count to
// increase between calls to this method).
COOP_PINVOKE_HELPER(UInt32, RhGetLoadedModules, (Array * pResultArray))
{
// Note that we depend on the fact that this is a COOP helper to make writing into an unpinned array safe.
// If a result array is passed then it should be an array type with pointer-sized components that are not
// GC-references.
ASSERT(!pResultArray || pResultArray->get_EEType()->IsArray());
ASSERT(!pResultArray || !pResultArray->get_EEType()->HasReferenceFields());
ASSERT(!pResultArray || pResultArray->get_EEType()->get_ComponentSize() == sizeof(void*));
UInt32 cResultArrayElements = pResultArray ? pResultArray->GetArrayLength() : 0;
TypeManagerHandle * pResultElements = pResultArray ? (TypeManagerHandle*)(pResultArray + 1) : NULL;
UInt32 cModules = 0;
FOREACH_MODULE(pModule)
{
if (pResultArray && (cModules < cResultArrayElements))
pResultElements[cModules] = TypeManagerHandle::Create(pModule->GetOsModuleHandle());
cModules++;
}
END_FOREACH_MODULE
ReaderWriterLock::ReadHolder read(&GetRuntimeInstance()->GetTypeManagerLock());
RuntimeInstance::TypeManagerList typeManagers = GetRuntimeInstance()->GetTypeManagerList();
for (RuntimeInstance::TypeManagerList::Iterator iter = typeManagers.Begin(); iter != typeManagers.End(); iter++)
{
if (pResultArray && (cModules < cResultArrayElements))
pResultElements[cModules] = TypeManagerHandle::Create(iter->m_pTypeManager);
cModules++;
}
return cModules;
}
COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleFromPointer, (PTR_VOID pPointerVal))
{
// TODO, this will always return nullptr in TypeManager based systems.
Module * pModule = GetRuntimeInstance()->FindModuleByAddress(pPointerVal);
if (pModule != NULL)
@@ -112,11 +179,16 @@ COOP_PINVOKE_HELPER(HANDLE, RhGetModuleFromPointer, (PTR_VOID pPointerVal))
return NULL;
}
COOP_PINVOKE_HELPER(HANDLE, RhGetModuleFromEEType, (EEType * pEEType))
COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleFromEEType, (EEType * pEEType))
{
#if CORERT
return (HANDLE)(pEEType->GetTypeManager());
return pEEType->GetTypeManagerPtr()->AsTypeManager()->GetOsModuleHandle();
#else
#if EETYPE_TYPE_MANAGER
if (pEEType->HasTypeManager())
return pEEType->GetTypeManagerPtr()->AsTypeManager()->GetOsModuleHandle();
#endif
// For dynamically created types, return the module handle that contains the template type
if (pEEType->IsDynamicType())
pEEType = pEEType->get_DynamicTemplateType();
@@ -137,65 +209,107 @@ COOP_PINVOKE_HELPER(HANDLE, RhGetModuleFromEEType, (EEType * pEEType))
#endif // !CORERT
}
COOP_PINVOKE_HELPER(Boolean, RhFindBlob, (HANDLE hOsModule, UInt32 blobId, UInt8 ** ppbBlob, UInt32 * pcbBlob))
COOP_PINVOKE_HELPER(TypeManagerHandle, RhGetModuleFromEEType, (EEType * pEEType))
{
#if CORERT
ReadyToRunSectionType section =
(ReadyToRunSectionType)((UInt32)ReadyToRunSectionType::ReadonlyBlobRegionStart + blobId);
ASSERT(section <= ReadyToRunSectionType::ReadonlyBlobRegionEnd);
TypeManager* pModule = (TypeManager*)hOsModule;
int length;
void* pBlob;
pBlob = pModule->GetModuleSection(section, &length);
*ppbBlob = (UInt8*)pBlob;
*pcbBlob = (UInt32)length;
return pBlob != NULL;
return *pEEType->GetTypeManagerPtr();
#else
// Search for the Redhawk module contained by the OS module.
#if EETYPE_TYPE_MANAGER
if (pEEType->HasTypeManager())
return *pEEType->GetTypeManagerPtr();
#endif
// For dynamically created types, return the module handle that contains the template type
if (pEEType->IsDynamicType())
pEEType = pEEType->get_DynamicTemplateType();
if (pEEType->get_DynamicModule() != nullptr)
{
// We should never get here (an EEType not located in any module) so fail fast to indicate the bug.
RhFailFast();
return TypeManagerHandle::Null();
}
FOREACH_MODULE(pModule)
{
if (pModule->GetOsModuleHandle() == hOsModule)
{
// Found a module match. Look through the blobs for one with a matching ID.
UInt32 cbBlobs;
BlobHeader * pBlob = pModule->GetReadOnlyBlobs(&cbBlobs);
while (cbBlobs)
{
UInt32 cbTotalBlob = sizeof(BlobHeader) + pBlob->m_size;
ASSERT(cbBlobs >= cbTotalBlob);
if (pBlob->m_id == blobId)
{
// Found the matching blob, return it.
*ppbBlob = (UInt8*)(pBlob + 1);
*pcbBlob = pBlob->m_size;
return TRUE;
}
cbBlobs -= cbTotalBlob;
pBlob = (BlobHeader*)((UInt8*)pBlob + cbTotalBlob);
}
// If we get here then we found a module match but didn't find a blob with a matching ID. That's a
// non-catastrophic error.
*ppbBlob = NULL;
*pcbBlob = 0;
return FALSE;
}
if (pModule->ContainsReadOnlyDataAddress(pEEType) || pModule->ContainsDataAddress(pEEType))
return TypeManagerHandle::Create(pModule->GetOsModuleHandle());
}
END_FOREACH_MODULE
// We should never get here (an EEType not located in any module) so fail fast to indicate the bug.
RhFailFast();
return TypeManagerHandle::Null();
#endif // !CORERT
}
COOP_PINVOKE_HELPER(Boolean, RhFindBlob, (TypeManagerHandle *pTypeManagerHandle, UInt32 blobId, UInt8 ** ppbBlob, UInt32 * pcbBlob))
{
TypeManagerHandle typeManagerHandle = *pTypeManagerHandle;
if (typeManagerHandle.IsTypeManager())
{
ReadyToRunSectionType section =
(ReadyToRunSectionType)((UInt32)ReadyToRunSectionType::ReadonlyBlobRegionStart + blobId);
ASSERT(section <= ReadyToRunSectionType::ReadonlyBlobRegionEnd);
TypeManager* pModule = typeManagerHandle.AsTypeManager();
int length;
void* pBlob;
pBlob = pModule->GetModuleSection(section, &length);
*ppbBlob = (UInt8*)pBlob;
*pcbBlob = (UInt32)length;
return pBlob != NULL;
}
#if !CORERT
else
{
HANDLE hOsModule = typeManagerHandle.AsOsModule();
// Search for the Redhawk module contained by the OS module.
FOREACH_MODULE(pModule)
{
if (pModule->GetOsModuleHandle() == hOsModule)
{
// Found a module match. Look through the blobs for one with a matching ID.
UInt32 cbBlobs;
BlobHeader * pBlob = pModule->GetReadOnlyBlobs(&cbBlobs);
while (cbBlobs)
{
UInt32 cbTotalBlob = sizeof(BlobHeader) + pBlob->m_size;
ASSERT(cbBlobs >= cbTotalBlob);
if (pBlob->m_id == blobId)
{
// Found the matching blob, return it.
*ppbBlob = (UInt8*)(pBlob + 1);
*pcbBlob = pBlob->m_size;
return TRUE;
}
cbBlobs -= cbTotalBlob;
pBlob = (BlobHeader*)((UInt8*)pBlob + cbTotalBlob);
}
// If we get here then we found a module match but didn't find a blob with a matching ID. That's a
// non-catastrophic error.
*ppbBlob = NULL;
*pcbBlob = 0;
return FALSE;
}
}
END_FOREACH_MODULE
}
#endif // !CORERT
// If we get here we were passed a bad module handle and should fail fast since this indicates a nasty bug
// (which could lead to the wrong blob being returned in some cases).
RhFailFast();
return FALSE;
#endif // !CORERT
}
// This helper is not called directly but is used by the implementation of RhpCheckCctor to locate the
@@ -203,17 +317,13 @@ COOP_PINVOKE_HELPER(Boolean, RhFindBlob, (HANDLE hOsModule, UInt32 blobId, UInt8
// to code in the caller's module and can be used in the lookup.
COOP_PINVOKE_HELPER(void *, GetClasslibCCtorCheck, (void * pReturnAddress))
{
// Locate the calling module from the context structure address (which is in writeable memory in the
// Locate the calling module from the context structure address (which is in writable memory in the
// module image).
Module * pModule = GetRuntimeInstance()->FindModuleByCodeAddress(pReturnAddress);
ASSERT(pModule);
// Locate the classlib module from the calling module.
Module * pClasslibModule = pModule->GetClasslibModule();
ASSERT(pClasslibModule);
ICodeManager * pCodeManager = GetRuntimeInstance()->FindCodeManagerByAddress(pReturnAddress);
ASSERT(pCodeManager);
// Lookup the callback registered by the classlib.
void * pCallback = pClasslibModule->GetClasslibCheckStaticClassConstruction();
void * pCallback = pCodeManager->GetClasslibFunction(ClasslibFunctionId::CheckStaticClassConstruction);
// We have no fallback path if we got here but the classlib doesn't implement the callback.
if (pCallback == NULL)
@@ -639,19 +749,24 @@ COOP_PINVOKE_HELPER(Boolean, RhpRegisterFrozenSegment, (void* pSegmentStart, UIn
return RedhawkGCInterface::RegisterFrozenSection(pSegmentStart, length) != NULL;
}
#ifdef CORERT
COOP_PINVOKE_HELPER(void*, RhpGetModuleSection, (TypeManager* pModule, Int32 headerId, Int32* length))
COOP_PINVOKE_HELPER(void*, RhpGetModuleSection, (TypeManagerHandle *pModule, Int32 headerId, Int32* length))
{
return pModule->GetModuleSection((ReadyToRunSectionType)headerId, length);
return pModule->AsTypeManager()->GetModuleSection((ReadyToRunSectionType)headerId, length);
}
COOP_PINVOKE_HELPER(void*, RhpCreateTypeManager, (void* pModuleHeader))
{
return TypeManager::Create(pModuleHeader);
}
#endif
COOP_PINVOKE_HELPER(void, RhGetCurrentThreadStackBounds, (PTR_VOID * ppStackLow, PTR_VOID * ppStackHigh))
{
ThreadStore::GetCurrentThread()->GetStackBounds(ppStackLow, ppStackHigh);
}
#ifdef PLATFORM_UNIX
// Function to call when a thread is detached from the runtime
ThreadExitCallback g_threadExitCallback;
COOP_PINVOKE_HELPER(void, RhSetThreadExitCallback, (void * pCallback))
{
g_threadExitCallback = (ThreadExitCallback)pCallback;
}
#endif // PLATFORM_UNIX

View File

@@ -498,9 +498,10 @@ typedef enum _EXCEPTION_DISPOSITION {
ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
#define STATUS_ACCESS_VIOLATION ((UInt32 )0xC0000005L)
#define STATUS_STACK_OVERFLOW ((UInt32 )0xC00000FDL)
#define STATUS_REDHAWK_NULL_REFERENCE ((UInt32 )0x00000000L)
#define STATUS_ACCESS_VIOLATION ((UInt32 )0xC0000005L)
#define STATUS_STACK_OVERFLOW ((UInt32 )0xC00000FDL)
#define STATUS_REDHAWK_NULL_REFERENCE ((UInt32 )0x00000000L)
#define STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE ((UInt32 )0x00000042L)
#ifdef PLATFORM_UNIX
#define NULL_AREA_SIZE (4*1024)
@@ -838,6 +839,8 @@ REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalDetachThread(void* thread);
REDHAWK_PALIMPORT UInt64 PalGetCurrentThreadIdForLogging();
REDHAWK_PALIMPORT void PalPrintFatalError(const char* message);
#ifdef PLATFORM_UNIX
REDHAWK_PALIMPORT Int32 __cdecl _stricmp(const char *string1, const char *string2);
#endif // PLATFORM_UNIX

View File

@@ -61,13 +61,15 @@ struct PAL_LIMITED_CONTEXT
UIntNative GetIp() const { return IP; }
UIntNative GetSp() const { return SP; }
UIntNative GetFp() const { return R7; }
UIntNative GetLr() const { return LR; }
void SetIp(UIntNative ip) { IP = ip; }
#elif defined(_TARGET_ARM64_)
// @TODO: Add ARM64 registers
UIntNative IP;
UIntNative GetIp() const { PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); }
UIntNative GetSp() const { PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); }
UIntNative GetFp() const { PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); }
UIntNative GetLr() const { PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); }
#elif defined(UNIX_AMD64_ABI)
// Param regs: rdi, rsi, rdx, rcx, r8, r9, scratch: rax, rdx (both return val), preserved: rbp, rbx, r12-r15
UIntNative IP;
@@ -121,6 +123,10 @@ struct PAL_LIMITED_CONTEXT
void RuntimeThreadShutdown(void* thread);
#ifdef PLATFORM_UNIX
typedef void (__fastcall * ThreadExitCallback)();
extern ThreadExitCallback g_threadExitCallback;
typedef Int32 (*PHARDWARE_EXCEPTION_HANDLER)(UIntNative faultCode, UIntNative faultAddress, PAL_LIMITED_CONTEXT* palContext, UIntNative* arg0Reg, UIntNative* arg1Reg);
#endif

View File

@@ -248,6 +248,11 @@ void RuntimeInstance::EnumAllStaticGCRefs(void * pfnCallback, void * pvCallbackD
}
END_FOREACH_MODULE
for (TypeManagerList::Iterator iter = m_TypeManagerList.Begin(); iter != m_TypeManagerList.End(); iter++)
{
iter->m_pTypeManager->EnumStaticGCRefs(pfnCallback, pvCallbackData);
}
EnumStaticGCRefDescs(pfnCallback, pvCallbackData);
EnumThreadStaticGCRefDescs(pfnCallback, pvCallbackData);
}
@@ -407,6 +412,68 @@ extern "C" void __stdcall UnregisterCodeManager(ICodeManager * pCodeManager)
}
#endif
bool RuntimeInstance::RegisterTypeManager(TypeManager * pTypeManager)
{
TypeManagerEntry * pEntry = new (nothrow) TypeManagerEntry();
if (NULL == pEntry)
return false;
pEntry->m_pTypeManager = pTypeManager;
{
ReaderWriterLock::WriteHolder write(&m_ModuleListLock);
m_TypeManagerList.PushHead(pEntry);
}
return true;
}
COOP_PINVOKE_HELPER(TypeManagerHandle, RhpCreateTypeManager, (HANDLE osModule, void* pModuleHeader))
{
TypeManager * typeManager = TypeManager::Create(osModule, pModuleHeader);
GetRuntimeInstance()->RegisterTypeManager(typeManager);
return TypeManagerHandle::Create(typeManager);
}
COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleForMrt, ())
{
return GetRuntimeInstance()->GetPalInstance();
}
COOP_PINVOKE_HELPER(void*, RhpRegisterOsModule, (HANDLE hOsModule))
{
RuntimeInstance::OsModuleEntry * pEntry = new (nothrow) RuntimeInstance::OsModuleEntry();
if (NULL == pEntry)
return nullptr; // Return null on failure.
pEntry->m_osModule = hOsModule;
{
RuntimeInstance *pRuntimeInstance = GetRuntimeInstance();
ReaderWriterLock::WriteHolder write(&pRuntimeInstance->GetTypeManagerLock());
pRuntimeInstance->GetOsModuleList().PushHead(pEntry);
}
return hOsModule; // Return non-null on success
}
RuntimeInstance::TypeManagerList& RuntimeInstance::GetTypeManagerList()
{
return m_TypeManagerList;
}
RuntimeInstance::OsModuleList& RuntimeInstance::GetOsModuleList()
{
return m_OsModuleList;
}
ReaderWriterLock& RuntimeInstance::GetTypeManagerLock()
{
return m_ModuleListLock;
}
// static
RuntimeInstance * RuntimeInstance::Create(HANDLE hPalInstance)
{

Some files were not shown because too many files have changed in this diff Show More