1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-09 09:34:49 +09:00

Move last P/Invoke error from native Thread and delete C/C++ SafeHandle implementation (#100267)

* Delete native safehandle

* Delete PInvoke last error on thread

* Delete IsRealThreadPoolResetNeeded

* Delete TS_TaskReset

* Delete GetThreadContext

* Fix build break

* Delete unused resource strings

* Introduce FEATURE_IJW and use it in number of places
This commit is contained in:
Jan Kotas 2024-03-27 06:14:44 -07:00 committed by GitHub
parent f390af4631
commit 3f7ffddeda
Signed by: github
GPG key ID: B5690EEEBB952194
24 changed files with 61 additions and 478 deletions

View file

@ -25,6 +25,7 @@ terminology.
| EE | [Execution Engine](https://docs.microsoft.com/dotnet/standard/managed-execution-process#running_code). |
| GC | [Garbage Collector](https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/garbage-collection.md). |
| IBC | Instrumented Block Counts - used as extension (`*.ibc`) for old PGO files. |
| IJW | "It Just Works" - Codename for [C++/CLI](https://learn.microsoft.com/cpp/dotnet/dotnet-programming-with-cpp-cli-visual-cpp) managed/native interop |
| IPC | Inter-Process Communication. |
| IL | Intermediate Language. Equivalent to CIL, also equivalent to [MSIL](https://docs.microsoft.com/dotnet/standard/managed-execution-process#compiling-to-msil). |
| JIT | [Just-in-Time](https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/jit/ryujit-overview.md) compiler. RyuJIT is the code name for the next generation Just-in-Time(aka "JIT") for the .NET runtime. |

View file

@ -92,6 +92,7 @@ if(CLR_CMAKE_TARGET_WIN32)
add_definitions(-DFEATURE_COMINTEROP)
add_definitions(-DFEATURE_COMINTEROP_APARTMENT_SUPPORT)
add_definitions(-DFEATURE_COMINTEROP_UNMANAGED_ACTIVATION)
add_definitions(-DFEATURE_IJW) # C++/CLI managed/native interop support
endif(CLR_CMAKE_TARGET_WIN32)
add_definitions(-DFEATURE_BASICFREEZE)

View file

@ -491,9 +491,6 @@ BEGIN
IDS_EE_CLASS_TO_VARIANT_TLB_NOT_REG "Type '%1' cannot be marshalled to a Variant. Type library is not registered."
IDS_EE_CANNOT_MAP_TO_MANAGED_VC "The specified record cannot be mapped to a managed value class."
IDS_EE_SAFEHANDLECLOSED "Safe handle has been closed"
IDS_EE_SAFEHANDLECANNOTSETHANDLE "Safe handle's handle field can only be set if the safe handle is not closed and has a ref count of 1."
IDS_EE_SH_IN_VARIANT_NOT_SUPPORTED "SafeHandle derived types cannot be stored in Variants."
IDS_EE_CH_IN_VARIANT_NOT_SUPPORTED "CriticalHandle derived types cannot be stored in Variants."

View file

@ -243,9 +243,6 @@
#define IDS_EE_METHOD_NOT_FOUND_ON_EV_PROV 0x1a24
#define IDS_EE_BAD_COMEVENTITF_CLASS 0x1a25
#define IDS_EE_COREXEMAIN2_FAILED_TITLE 0x1a2b
#define IDS_EE_COREXEMAIN2_FAILED_TEXT 0x1a2c
#define IDS_EE_ICUSTOMMARSHALERNOTIMPL 0x1a2e
#define IDS_EE_GETINSTANCENOTIMPL 0x1a2f
@ -265,9 +262,6 @@
#define IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE 0x1a3c
#define IDS_EE_BADMARSHAL_SAFEHANDLE 0x1a3d
#define IDS_EE_SAFEHANDLECLOSED 0x1a3f
#define IDS_EE_SAFEHANDLECANNOTSETHANDLE 0x1a40
#define IDS_EE_BADMARSHAL_ABSTRACTRETSAFEHANDLE 0x1a44
#define IDS_EE_SH_IN_VARIANT_NOT_SUPPORTED 0x1a47

View file

@ -358,7 +358,6 @@ set(VM_SOURCES_WKS
reflectclasswriter.cpp
reflectioninvocation.cpp
runtimehandles.cpp
safehandle.cpp
simplerwlock.cpp
stackingallocator.cpp
stringliteralmap.cpp

View file

@ -1414,9 +1414,6 @@ void SystemDomain::LoadBaseSystemClasses()
g_profControlBlock.fBaseSystemClassesLoaded = TRUE;
#endif // PROFILING_SUPPORTED
// Perform any once-only SafeHandle initialization.
SafeHandle::Init();
#if defined(_DEBUG)
g_CoreLib.Check();
g_CoreLib.CheckExtended();

View file

@ -545,9 +545,7 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *
if (transitionToPreemptive)
{
GCPreemp transitionIfILStub(transitionToPreemptive);
DWORD* pLastError = &GetThread()->m_dwLastErrorInterp;
CallDescrWorkerInternal(&callDescrData);
*pLastError = GetLastError();
}
else
#endif // FEATURE_INTERPRETER

View file

@ -59,7 +59,7 @@ public:
static FCDECL1(void, Initialize, ThreadBaseObject* pThisUNSAFE);
static FCDECL1(FC_BOOL_RET, GetIsBackground, ThreadBaseObject* pThisUNSAFE);
static FCDECL1(INT32, GetThreadState, ThreadBaseObject* pThisUNSAFE);
static FCDECL1(INT32, GetThreadContext, ThreadBaseObject* pThisUNSAFE);
#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
static FCDECL1(INT32, GetApartmentState, ThreadBaseObject* pThis);
static FCDECL2(INT32, SetApartmentState, ThreadBaseObject* pThisUNSAFE, INT32 iState);

View file

@ -188,9 +188,6 @@ DEFINE_METHOD(LICENSE_INTEROP_PROXY, SAVEKEYINCURRENTCONTEXT, SaveKeyInCurrentCo
#endif // FEATURE_COMINTEROP
END_ILLINK_FEATURE_SWITCH()
DEFINE_CLASS_U(Interop, CriticalHandle, CriticalHandle)
DEFINE_FIELD_U(handle, CriticalHandle, m_handle)
DEFINE_FIELD_U(_isClosed, CriticalHandle, m_isClosed)
DEFINE_CLASS(CRITICAL_HANDLE, Interop, CriticalHandle)
DEFINE_FIELD(CRITICAL_HANDLE, HANDLE, handle)
DEFINE_METHOD(CRITICAL_HANDLE, RELEASE_HANDLE, ReleaseHandle, IM_RetBool)
@ -731,12 +728,6 @@ DEFINE_CLASS(CALLCONV_SUPPRESSGCTRANSITION, CompilerServices, CallConvSup
DEFINE_CLASS(CALLCONV_MEMBERFUNCTION, CompilerServices, CallConvMemberFunction)
DEFINE_CLASS(CALLCONV_SWIFT, CompilerServices, CallConvSwift)
DEFINE_CLASS_U(Interop, SafeHandle, SafeHandle)
DEFINE_FIELD_U(_ctorStackTrace, SafeHandle, m_ctorStackTrace)
DEFINE_FIELD_U(handle, SafeHandle, m_handle)
DEFINE_FIELD_U(_state, SafeHandle, m_state)
DEFINE_FIELD_U(_ownsHandle, SafeHandle, m_ownsHandle)
DEFINE_FIELD_U(_fullyInitialized, SafeHandle, m_fullyInitialized)
DEFINE_CLASS(SAFE_HANDLE, Interop, SafeHandle)
DEFINE_FIELD(SAFE_HANDLE, HANDLE, handle)
DEFINE_METHOD(SAFE_HANDLE, GET_IS_INVALID, get_IsInvalid, IM_RetBool)
@ -895,9 +886,6 @@ DEFINE_FIELD_U(_taggedHandle, WeakReferenceObject, m_taggedHandle)
DEFINE_CLASS(WEAKREFERENCE, System, WeakReference)
DEFINE_CLASS(WEAKREFERENCEGENERIC, System, WeakReference`1)
DEFINE_CLASS_U(Threading, WaitHandle, WaitHandleBase)
DEFINE_FIELD_U(_waitHandle, WaitHandleBase, m_safeHandle)
DEFINE_CLASS(DEBUGGER, Diagnostics, Debugger)
DEFINE_METHOD(DEBUGGER, BREAK, Break, SM_RetVoid)

View file

@ -1631,9 +1631,9 @@ NDirectStubLinker::NDirectStubLinker(
}
#endif // FEATURE_COMINTEROP
#if defined(TARGET_X86) && defined(TARGET_WINDOWS)
#if defined(TARGET_X86) && defined(FEATURE_IJW)
m_dwCopyCtorChainLocalNum = (DWORD)-1;
#endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
#endif // defined(TARGET_X86) && defined(FEATURE_IJW)
}
void NDirectStubLinker::SetCallingConvention(CorInfoCallConvExtension unmngCallConv, BOOL fIsVarArg)
@ -1846,7 +1846,7 @@ DWORD NDirectStubLinker::GetReturnValueLocalNum()
return m_dwRetValLocalNum;
}
#if defined(TARGET_X86) && defined(TARGET_WINDOWS)
#if defined(TARGET_X86) && defined(FEATURE_IJW)
DWORD NDirectStubLinker::GetCopyCtorChainLocalNum()
{
STANDARD_VM_CONTRACT;
@ -1861,7 +1861,7 @@ DWORD NDirectStubLinker::GetCopyCtorChainLocalNum()
return m_dwCopyCtorChainLocalNum;
}
#endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
#endif // defined(TARGET_X86) && defined(FEATURE_IJW)
BOOL NDirectStubLinker::IsCleanupNeeded()
{
@ -2179,7 +2179,7 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
}
}
#if defined(TARGET_X86) && defined(TARGET_WINDOWS)
#if defined(TARGET_X86) && defined(FEATURE_IJW)
if (m_dwCopyCtorChainLocalNum != (DWORD)-1)
{
// If we have a copy constructor chain local, we need to call the copy constructor stub
@ -2192,7 +2192,7 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
pcsEmit->EmitCALL(METHOD__COPY_CONSTRUCTOR_CHAIN__INSTALL, 2, 0);
pcsEmit->EmitLDC((DWORD_PTR)&CopyConstructorCallStub);
}
#endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
#endif // defined(TARGET_X86) && defined(FEATURE_IJW)
// For managed-to-native calls, the rest of the work is done by the JIT. It will
// erect InlinedCallFrame, flip GC mode, and use the specified calling convention
@ -2867,6 +2867,7 @@ static LPBYTE FollowIndirect(LPBYTE pTarget)
}
#endif // !TARGET_UNIX
#ifdef FEATURE_IJW
BOOL HeuristicDoesThisLookLikeAGetLastErrorCall(LPBYTE pTarget)
{
CONTRACTL
@ -2877,7 +2878,6 @@ BOOL HeuristicDoesThisLookLikeAGetLastErrorCall(LPBYTE pTarget)
}
CONTRACTL_END;
#if !defined(TARGET_UNIX)
static LPBYTE pGetLastError = NULL;
if (!pGetLastError)
{
@ -2912,18 +2912,10 @@ BOOL HeuristicDoesThisLookLikeAGetLastErrorCall(LPBYTE pTarget)
// jmp [xxxx] - could be an import thunk
return pTarget2 == pGetLastError;
}
#endif // !TARGET_UNIX
return FALSE;
}
DWORD STDMETHODCALLTYPE FalseGetLastError()
{
WRAPPER_NO_CONTRACT;
return GetThread()->m_dwLastError;
}
#endif // FEATURE_IJW
CorInfoCallConvExtension GetDefaultCallConv(BOOL bIsVarArg)
{
@ -6141,7 +6133,7 @@ PCODE GetILStubForCalli(VASigCookie *pVASigCookie, MethodDesc *pMD)
RETURN pVASigCookie->pNDirectILStub;
}
#if defined(TARGET_X86) && defined(TARGET_WINDOWS)
#if defined(TARGET_X86) && defined(FEATURE_IJW)
// Copy constructor support for C++/CLI
EXTERN_C void* STDCALL CallCopyConstructorsWorker(void* esp)
{
@ -6156,6 +6148,6 @@ EXTERN_C void* STDCALL CallCopyConstructorsWorker(void* esp)
return pExecute(esp);
}
#endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
#endif // defined(TARGET_X86) && defined(FEATURE_IJW)
#endif // #ifndef DACCESS_COMPILE

View file

@ -496,9 +496,9 @@ public:
DWORD GetCleanupWorkListLocalNum();
DWORD GetThreadLocalNum();
DWORD GetReturnValueLocalNum();
#if defined(TARGET_X86) && defined(TARGET_WINDOWS)
#if defined(TARGET_X86) && defined(FEATURE_IJW)
DWORD GetCopyCtorChainLocalNum();
#endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
#endif // defined(TARGET_X86) && defined(FEATURE_IJW)
void SetCleanupNeeded();
void SetExceptionCleanupNeeded();
BOOL IsCleanupWorkListSetup();
@ -568,9 +568,9 @@ protected:
DWORD m_dwTargetEntryPointLocalNum;
#endif // FEATURE_COMINTEROP
#if defined(TARGET_X86) && defined(TARGET_WINDOWS)
#if defined(TARGET_X86) && defined(FEATURE_IJW)
DWORD m_dwCopyCtorChainLocalNum;
#endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
#endif // defined(TARGET_X86) && defined(FEATURE_IJW)
BOOL m_fHasCleanupCode;
BOOL m_fHasExceptionCleanupCode;

View file

@ -3394,7 +3394,7 @@ ILCriticalHandleMarshaler::ReturnOverride(
return OVERRIDDEN;
} // ILCriticalHandleMarshaler::ReturnOverride
#if defined(TARGET_WINDOWS)
#if defined(FEATURE_IJW)
MarshalerOverrideStatus ILBlittableValueClassWithCopyCtorMarshaler::ArgumentOverride(NDirectStubLinker* psl,
BOOL byref,
BOOL fin,
@ -3520,7 +3520,7 @@ MarshalerOverrideStatus ILBlittableValueClassWithCopyCtorMarshaler::ArgumentOver
return OVERRIDDEN;
}
}
#endif // defined(TARGET_WINDOWS)
#endif // defined(FEATURE_IJW)
LocalDesc ILArgIteratorMarshaler::GetNativeType()
{

View file

@ -2923,7 +2923,7 @@ protected:
void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
};
#if defined(TARGET_WINDOWS)
#if defined(FEATURE_IJW)
class ILBlittableValueClassWithCopyCtorMarshaler : public ILMarshaler
{
public:

View file

@ -9271,19 +9271,6 @@ void Interpreter::DoCallWork(bool virtualCall, void* thisArg, CORINFO_RESOLVED_T
break;
}
// Plus some other calls that we're going to treat "like" intrinsics...
if (methToCall == CoreLibBinder::GetMethod(METHOD__STUBHELPERS__SET_LAST_ERROR))
{
// If we're interpreting a method that calls "SetLastError", it's very likely that the call(i) whose
// error we're trying to capture was performed with MethodDescCallSite machinery that itself trashes
// the last error. We solve this by saving the last error in a special interpreter-specific field of
// "Thread" in that case, and essentially implement SetLastError here, taking that field as the
// source for the last error.
Thread* thrd = GetThread();
thrd->m_dwLastError = thrd->m_dwLastErrorInterp;
didIntrinsic = true;
}
// TODO: The following check for hardware intrinsics is not a production-level
// solution and may produce incorrect results.
static ConfigDWORD s_InterpreterHWIntrinsicsIsSupportedFalse;

View file

@ -34,6 +34,7 @@
#include "comdelegate.h"
#include "typestring.h"
#include "appdomain.inl"
#include "stubhelpers.h"
#ifdef FEATURE_COMINTEROP
#include "comcallablewrapper.h"
@ -283,27 +284,47 @@ extern "C" IsInCooperativeGCMode_fn QCALLTYPE MarshalNative_GetIsInCooperativeGC
#endif
/************************************************************************
* Marshal.GetLastPInvokeError
* Support for the last PInvoke error
*/
static thread_local int t_lastPInvokeError;
FCIMPL0(int, MarshalNative::GetLastPInvokeError)
{
FCALL_CONTRACT;
return (UINT32)(GetThread()->m_dwLastError);
return t_lastPInvokeError;
}
FCIMPLEND
/************************************************************************
* Marshal.SetLastPInvokeError
*/
FCIMPL1(void, MarshalNative::SetLastPInvokeError, int error)
{
FCALL_CONTRACT;
GetThread()->m_dwLastError = (DWORD)error;
t_lastPInvokeError = error;
}
FCIMPLEND
FCIMPL0(void, StubHelpers::SetLastError)
{
// Make sure this is the first thing we do after returning from the target, as almost everything can cause the last error to get trashed
DWORD lastError = ::GetLastError();
FCALL_CONTRACT;
t_lastPInvokeError = lastError;
}
FCIMPLEND
#ifdef FEATURE_IJW
// GetLastError override for C++/CLI
DWORD STDMETHODCALLTYPE FalseGetLastError()
{
WRAPPER_NO_CONTRACT;
return t_lastPInvokeError;
}
#endif // FEATURE_IJW
/************************************************************************
* Support for the GCHandle class.
*/

View file

@ -3563,8 +3563,10 @@ void NDirectMethodDesc::InitEarlyBoundNDirectTarget()
const void *target = GetModule()->GetInternalPInvokeTarget(GetRVA());
_ASSERTE(target != 0);
#ifdef FEATURE_IJW
if (HeuristicDoesThisLookLikeAGetLastErrorCall((LPBYTE)target))
target = (BYTE*)FalseGetLastError;
#endif
// As long as we've set the NDirect target field we don't need to backpatch the import thunk glue.
// All NDirect calls all through the NDirect target, so if it's updated, then we won't go into

View file

@ -2383,7 +2383,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
{
if (fNeedsCopyCtor && !IsFieldScenario()) // We don't support automatically discovering copy constructors for fields.
{
#if defined(TARGET_WINDOWS)
#if defined(FEATURE_IJW)
MethodDesc *pCopyCtor;
MethodDesc *pDtor;
FindCopyCtor(pModule, m_pMT, &pCopyCtor);
@ -2393,10 +2393,10 @@ MarshalInfo::MarshalInfo(Module* pModule,
m_args.mm.m_pCopyCtor = pCopyCtor;
m_args.mm.m_pDtor = pDtor;
m_type = MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR;
#else // !defined(TARGET_WINDOWS)
#else // !defined(FEATURE_IJW)
m_resID = IDS_EE_BADMARSHAL_BADMANAGED;
IfFailGoto(E_FAIL, lFail);
#endif // defined(TARGET_WINDOWS)
#endif // defined(FEATURE_IJW)
}
else
{
@ -3126,9 +3126,9 @@ bool MarshalInfo::IsValueClass(MarshalType mtype)
{
case MARSHAL_TYPE_BLITTABLEVALUECLASS:
case MARSHAL_TYPE_VALUECLASS:
#if defined(TARGET_WINDOWS)
#if defined(FEATURE_IJW)
case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
#endif // defined(TARGET_WINDOWS)
#endif // defined(FEATURE_IJW)
return true;
default:
@ -3612,9 +3612,9 @@ DispParamMarshaler *MarshalInfo::GenerateDispParamMarshaler()
case MARSHAL_TYPE_BLITTABLEVALUECLASS:
case MARSHAL_TYPE_BLITTABLEPTR:
case MARSHAL_TYPE_LAYOUTCLASSPTR:
#if defined(TARGET_WINDOWS)
#if defined(FEATURE_IJW)
case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
#endif // defined(TARGET_WINDOWS)
#endif // defined(FEATURE_IJW)
pDispParamMarshaler = new DispParamRecordMarshaler(m_pMT);
break;

View file

@ -80,9 +80,9 @@ DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_VALUECLASS, ValueClassMa
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_REFERENCECUSTOMMARSHALER, ReferenceCustomMarshaler)
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_ARGITERATOR, ArgIteratorMarshaler)
#if defined(TARGET_WINDOWS)
#if defined(FEATURE_IJW)
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR, BlittableValueClassWithCopyCtorMarshaler)
#endif // defined(TARGET_WINDOWS)
#endif // defined(FEATURE_IJW)
#ifdef FEATURE_COMINTEROP
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_OBJECT, ObjectMarshaler)

View file

@ -1194,15 +1194,7 @@ class ReflectModuleBaseObject : public Object
NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive);
#define FC_RETURN_MODULE_OBJECT(pModule, refKeepAlive) FC_INNER_RETURN(ReflectModuleBaseObject*, GetRuntimeModuleHelper(__me, pModule, refKeepAlive))
class SafeHandle;
#ifdef USE_CHECKED_OBJECTREFS
typedef REF<SafeHandle> SAFEHANDLE;
typedef REF<SafeHandle> SAFEHANDLEREF;
#else // USE_CHECKED_OBJECTREFS
typedef SafeHandle * SAFEHANDLE;
typedef SafeHandle * SAFEHANDLEREF;
#endif // USE_CHECKED_OBJECTREFS
@ -1242,19 +1234,6 @@ typedef CultureInfoBaseObject* CULTUREINFOBASEREF;
typedef PTR_ArrayBase ARRAYBASEREF;
#endif
// Note that the name must always be "" or "en-US". Other cases and nulls
// aren't allowed (we already checked.)
__inline bool IsCultureEnglishOrInvariant(LPCWSTR localeName)
{
LIMITED_METHOD_CONTRACT;
if (localeName != NULL &&
(localeName[0] == W('\0') ||
u16_strcmp(localeName, W("en-US")) == 0))
{
return true;
}
return false;
}
class CultureInfoBaseObject : public Object
{
@ -1866,110 +1845,6 @@ typedef BStrWrapper* BSTRWRAPPEROBJECTREF;
#endif // FEATURE_COMINTEROP
class SafeHandle : public Object
{
friend class CoreLibBinder;
private:
// READ ME:
// Modifying the order or fields of this object may require
// other changes to the classlib class definition of this
// object or special handling when loading this system class.
#if DEBUG
STRINGREF m_ctorStackTrace; // Debug-only stack trace captured when the SafeHandle was constructed
#endif
Volatile<LPVOID> m_handle;
Volatile<INT32> m_state; // Combined ref count and closed/disposed state (for atomicity)
Volatile<CLR_BOOL> m_ownsHandle;
Volatile<CLR_BOOL> m_fullyInitialized; // Did constructor finish?
// Describe the bits in the m_state field above.
enum StateBits
{
SH_State_Closed = 0x00000001,
SH_State_Disposed = 0x00000002,
SH_State_RefCount = 0xfffffffc,
SH_RefCountOne = 4, // Amount to increment state field to yield a ref count increment of 1
};
static WORD s_IsInvalidHandleMethodSlot;
static WORD s_ReleaseHandleMethodSlot;
static void RunReleaseMethod(SafeHandle* psh);
BOOL IsFullyInitialized() const { LIMITED_METHOD_CONTRACT; return m_fullyInitialized; }
public:
static void Init();
// To use the SafeHandle from native, look at the SafeHandleHolder, which
// will do the AddRef & Release for you.
LPVOID GetHandle() const {
LIMITED_METHOD_CONTRACT;
_ASSERTE(((unsigned int) m_state) >= SH_RefCountOne);
return m_handle;
}
void AddRef();
void Release(bool fDispose = false);
void SetHandle(LPVOID handle);
};
void AcquireSafeHandle(SAFEHANDLEREF* s);
void ReleaseSafeHandle(SAFEHANDLEREF* s);
typedef Holder<SAFEHANDLEREF*, AcquireSafeHandle, ReleaseSafeHandle> SafeHandleHolder;
class CriticalHandle : public Object
{
friend class CoreLibBinder;
private:
// READ ME:
// Modifying the order or fields of this object may require
// other changes to the classlib class definition of this
// object or special handling when loading this system class.
Volatile<LPVOID> m_handle;
Volatile<CLR_BOOL> m_isClosed;
public:
LPVOID GetHandle() const { LIMITED_METHOD_CONTRACT; return m_handle; }
static size_t GetHandleOffset() { LIMITED_METHOD_CONTRACT; return offsetof(CriticalHandle, m_handle); }
void SetHandle(LPVOID handle) { LIMITED_METHOD_CONTRACT; m_handle = handle; }
};
#ifdef USE_CHECKED_OBJECTREFS
typedef REF<CriticalHandle> CRITICALHANDLE;
typedef REF<CriticalHandle> CRITICALHANDLEREF;
#else // USE_CHECKED_OBJECTREFS
typedef CriticalHandle * CRITICALHANDLE;
typedef CriticalHandle * CRITICALHANDLEREF;
#endif // USE_CHECKED_OBJECTREFS
// WaitHandleBase
// Base class for WaitHandle
class WaitHandleBase :public MarshalByRefObjectBaseObject
{
friend class CoreLibBinder;
public:
__inline LPVOID GetWaitHandle() {
LIMITED_METHOD_CONTRACT;
SAFEHANDLEREF safeHandle = (SAFEHANDLEREF)m_safeHandle.LoadWithoutBarrier();
return safeHandle != NULL ? safeHandle->GetHandle() : INVALID_HANDLE_VALUE;
}
__inline SAFEHANDLEREF GetSafeHandle() {LIMITED_METHOD_CONTRACT; return (SAFEHANDLEREF)m_safeHandle.LoadWithoutBarrier();}
private:
Volatile<SafeHandle*> m_safeHandle;
};
#ifdef USE_CHECKED_OBJECTREFS
typedef REF<WaitHandleBase> WAITHANDLEREF;
#else // USE_CHECKED_OBJECTREFS
typedef WaitHandleBase* WAITHANDLEREF;
#endif // USE_CHECKED_OBJECTREFS
// This class corresponds to System.MulticastDelegate on the managed side.
class DelegateObject : public Object

View file

@ -1,220 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//
/*============================================================
**
** Class: SafeHandle
**
**
** Purpose: The unmanaged implementation of the SafeHandle
** class
**
===========================================================*/
#include "common.h"
#include "vars.hpp"
#include "object.h"
#include "excep.h"
#include "frames.h"
#include "eecontract.h"
#include "typestring.h"
WORD SafeHandle::s_IsInvalidHandleMethodSlot = MethodTable::NO_SLOT;
WORD SafeHandle::s_ReleaseHandleMethodSlot = MethodTable::NO_SLOT;
void SafeHandle::Init()
{
CONTRACTL {
THROWS;
GC_TRIGGERS;
MODE_ANY;
} CONTRACTL_END;
// For reliability purposes, we need to eliminate all possible failure
// points before making a call to a CER method. IsInvalidHandle, and
// ReleaseHandle methods are critical calls that are already prepared (code:
// PrepareCriticalFinalizerObject). As a performance optimization, we are
// calling these methods through a fast macro that assumes the method slot
// has been already cached. Since figuring out the method slot for these 2
// methods involves calling .GetMethod which can fail, we are doing this
// eagerly here, Otherwise we will have to do it at the time of the call,
// and this could be at risk if .GetMethod failed.
MethodDesc* pMD = CoreLibBinder::GetMethod(METHOD__SAFE_HANDLE__GET_IS_INVALID);
s_IsInvalidHandleMethodSlot = pMD->GetSlot();
pMD = CoreLibBinder::GetMethod(METHOD__SAFE_HANDLE__RELEASE_HANDLE);
s_ReleaseHandleMethodSlot = pMD->GetSlot();
}
// These AddRef and Release methods (and supporting functions) also exist with equivalent
// code in SafeHandle.cs. Those implementations are the primary ones used by most code
// and exposed publicly; the implementations here are only for use by the runtime, without
// having to call out to the managed implementations.
void SafeHandle::AddRef()
{
CONTRACTL {
THROWS;
GC_TRIGGERS;
MODE_COOPERATIVE;
INSTANCE_CHECK;
} CONTRACTL_END;
// Cannot use "this" after Release, which toggles the GC mode.
SAFEHANDLEREF sh(this);
_ASSERTE(sh->IsFullyInitialized());
// See comments in SafeHandle.cs
INT32 oldState, newState;
do {
oldState = sh->m_state;
if (oldState & SH_State_Closed)
COMPlusThrow(kObjectDisposedException, IDS_EE_SAFEHANDLECLOSED);
newState = oldState + SH_RefCountOne;
} while (InterlockedCompareExchange((LONG*)&sh->m_state, newState, oldState) != oldState);
}
void SafeHandle::Release(bool fDispose)
{
CONTRACTL {
THROWS;
GC_TRIGGERS;
MODE_COOPERATIVE;
INSTANCE_CHECK;
} CONTRACTL_END;
// Cannot use "this" after RunReleaseMethod, which toggles the GC mode.
SAFEHANDLEREF sh(this);
_ASSERTE(sh->IsFullyInitialized());
// See comments in SafeHandle.cs
bool fPerformRelease = false;
INT32 oldState, newState;
do {
oldState = sh->m_state;
if (fDispose && (oldState & SH_State_Disposed))
return;
if ((oldState & SH_State_RefCount) == 0)
COMPlusThrow(kObjectDisposedException, IDS_EE_SAFEHANDLECLOSED);
fPerformRelease = ((oldState & (SH_State_RefCount | SH_State_Closed)) == SH_RefCountOne) && m_ownsHandle;
if (fPerformRelease)
{
GCPROTECT_BEGIN(sh);
CLR_BOOL fIsInvalid = FALSE;
DECLARE_ARGHOLDER_ARRAY(args, 1);
args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(sh);
PREPARE_SIMPLE_VIRTUAL_CALLSITE_USING_SLOT(s_IsInvalidHandleMethodSlot, sh);
CRITICAL_CALLSITE;
CALL_MANAGED_METHOD(fIsInvalid, CLR_BOOL, args);
if (fIsInvalid)
{
fPerformRelease = false;
}
GCPROTECT_END();
}
newState = (oldState - SH_RefCountOne) |
((oldState & SH_State_RefCount) == SH_RefCountOne ? SH_State_Closed : 0) |
(fDispose ? SH_State_Disposed : 0);
} while (InterlockedCompareExchange((LONG*)&sh->m_state, newState, oldState) != oldState);
if (fPerformRelease)
RunReleaseMethod((SafeHandle*) OBJECTREFToObject(sh));
}
void SafeHandle::SetHandle(LPVOID handle)
{
CONTRACTL {
THROWS;
MODE_COOPERATIVE;
INSTANCE_CHECK;
} CONTRACTL_END;
_ASSERTE(IsFullyInitialized());
// The SafeHandle's handle field can only be set it if the SafeHandle isn't
// closed or disposed and its ref count is 1.
if (m_state != (LONG)SH_RefCountOne)
COMPlusThrow(kObjectDisposedException, IDS_EE_SAFEHANDLECANNOTSETHANDLE);
m_handle = handle;
}
void AcquireSafeHandle(SAFEHANDLEREF* s)
{
WRAPPER_NO_CONTRACT;
GCX_COOP();
_ASSERTE(s != NULL && *s != NULL);
(*s)->AddRef();
}
void ReleaseSafeHandle(SAFEHANDLEREF* s)
{
WRAPPER_NO_CONTRACT;
GCX_COOP();
_ASSERTE(s != NULL && *s != NULL);
(*s)->Release(false);
}
// This could theoretically be an instance method, but we'd need to
// somehow GC protect the this pointer or never dereference any
// field within the object. It's a lot simpler if we simply make
// this method static.
void SafeHandle::RunReleaseMethod(SafeHandle* psh)
{
CONTRACTL {
THROWS;
GC_TRIGGERS;
MODE_COOPERATIVE;
} CONTRACTL_END;
SAFEHANDLEREF sh(psh);
_ASSERTE(sh != NULL);
_ASSERTE(sh->m_ownsHandle);
_ASSERTE(sh->IsFullyInitialized());
GCPROTECT_BEGIN(sh);
// Save last error from P/Invoke in case the implementation of ReleaseHandle
// trashes it (important because this ReleaseHandle could occur implicitly
// as part of unmarshaling another P/Invoke).
Thread *pThread = GetThread();
DWORD dwSavedError = pThread->m_dwLastError;
CLR_BOOL fReleaseHandle = FALSE;
DECLARE_ARGHOLDER_ARRAY(args, 1);
args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(sh);
PREPARE_SIMPLE_VIRTUAL_CALLSITE_USING_SLOT(s_ReleaseHandleMethodSlot, sh);
CRITICAL_CALLSITE;
CALL_MANAGED_METHOD(fReleaseHandle, CLR_BOOL, args);
pThread->m_dwLastError = dwSavedError;
GCPROTECT_END();
}

View file

@ -422,17 +422,6 @@ extern "C" void QCALLTYPE InterfaceMarshaler_ConvertToManaged(IUnknown** ppUnk,
#endif // FEATURE_COMINTEROP
FCIMPL0(void, StubHelpers::SetLastError)
{
// Make sure this is the first thing we do after returning from the target, as almost everything can cause the last error to get trashed
DWORD lastError = ::GetLastError();
FCALL_CONTRACT;
GetThread()->m_dwLastError = lastError;
}
FCIMPLEND
FCIMPL0(void, StubHelpers::ClearLastError)
{
FCALL_CONTRACT;

View file

@ -7889,32 +7889,6 @@ INT32 Thread::ResetManagedThreadObjectInCoopMode(INT32 nPriority)
return nPriority;
}
BOOL Thread::IsRealThreadPoolResetNeeded()
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
MODE_COOPERATIVE;
}
CONTRACTL_END;
if(!IsBackground())
return TRUE;
THREADBASEREF pObject = (THREADBASEREF)ObjectFromHandle(m_ExposedObject);
if(pObject != NULL)
{
INT32 nPriority = pObject->GetPriority();
if(nPriority != ThreadNative::PRIORITY_NORMAL)
return TRUE;
}
return FALSE;
}
void Thread::InternalReset(BOOL fNotFinalizerThread, BOOL fThreadObjectResetNeeded, BOOL fResetAbort)
{
CONTRACTL {

View file

@ -638,7 +638,7 @@ public:
TS_ReportDead = 0x00010000, // in WaitForOtherThreads()
TS_FullyInitialized = 0x00020000, // Thread is fully initialized and we are ready to broadcast its existence to external clients
TS_TaskReset = 0x00040000, // The task is reset
// unused = 0x00040000,
TS_SyncSuspended = 0x00080000, // Suspended via WaitSuspendEvent
TS_DebugWillSync = 0x00100000, // Debugger will wait for this thread to sync
@ -753,7 +753,7 @@ public:
void InternalReset (BOOL fNotFinalizerThread=FALSE, BOOL fThreadObjectResetNeeded=TRUE, BOOL fResetAbort=TRUE);
INT32 ResetManagedThreadObject(INT32 nPriority);
INT32 ResetManagedThreadObjectInCoopMode(INT32 nPriority);
BOOL IsRealThreadPoolResetNeeded();
public:
HRESULT DetachThread(BOOL fDLLThreadDetach);
@ -2454,18 +2454,6 @@ public:
// making m_Link public.
SLink m_Link;
// For N/Direct calls with the "setLastError" bit, this field stores
// the errorcode from that call.
DWORD m_dwLastError;
#ifdef FEATURE_INTERPRETER
// When we're interpreting IL stubs for N/Direct calls with the "setLastError" bit,
// the interpretation will trash the last error before we get to the call to "SetLastError".
// Therefore, we record it here immediately after the calli, and treat "SetLastError" as an
// intrinsic that transfers the value stored here into the field above.
DWORD m_dwLastErrorInterp;
#endif
// Debugger per-thread flag for enabling notification on "manual"
// method calls, for stepping logic
void IncrementTraceCallCount();

View file

@ -1382,7 +1382,7 @@ Thread::UserAbort(EEPolicy::ThreadAbortTypes abortType, DWORD timeout)
// If a thread is Dead or Detached, abort is a NOP.
//
if (m_State & (TS_Dead | TS_Detached | TS_TaskReset))
if (m_State & (TS_Dead | TS_Detached))
{
UnmarkThreadForAbort();