diff --git a/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs
index f8246642b9e61b..dd7cd4c6309443 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs
@@ -155,12 +155,16 @@ public static void RemoveMemoryPressure(long bytesAllocated)
_RemoveMemoryPressure((ulong)bytesAllocated);
}
-
// Returns the generation that obj is currently in.
//
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern int GetGeneration(object obj);
+ public static int GetGeneration(object obj)
+ {
+ ArgumentNullException.ThrowIfNull(obj);
+ return GetGenerationInternal(obj);
+ }
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern int GetGenerationInternal(object obj);
// Forces a collection of all generations from 0 through Generation.
//
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
index 77311a0242172b..1b1f550ae53e1a 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
@@ -301,13 +301,18 @@ public static int OffsetToStringData
// This method ensures that there is sufficient stack to execute the average Framework function.
// If there is not enough stack, then it throws System.InsufficientExecutionStackException.
- // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack.
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern void EnsureSufficientExecutionStack();
+ // Note: this method is not to be confused with ProbeForSufficientStack.
+ public static void EnsureSufficientExecutionStack()
+ {
+ if (!TryEnsureSufficientExecutionStack())
+ {
+ throw new InsufficientExecutionStackException();
+ }
+ }
// This method ensures that there is sufficient stack to execute the average Framework function.
// If there is not enough stack, then it return false.
- // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack.
+ // Note: this method is not to be confused with ProbeForSufficientStack.
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern bool TryEnsureSufficientExecutionStack();
@@ -469,7 +474,17 @@ public static IntPtr AllocateTypeAssociatedMemory(Type type, int size)
private static partial IntPtr AllocateTypeAssociatedMemory(QCallTypeHandle type, uint size);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern IntPtr AllocTailCallArgBuffer(int size, IntPtr gcDesc);
+ private static extern IntPtr AllocTailCallArgBufferWorker(int size, IntPtr gcDesc);
+
+ private static IntPtr AllocTailCallArgBuffer(int size, IntPtr gcDesc)
+ {
+ IntPtr buffer = AllocTailCallArgBufferWorker(size, gcDesc);
+ if (buffer == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ return buffer;
+ }
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern unsafe TailCallTls* GetTailCallInfo(IntPtr retAddrSlot, IntPtr* retAddr);
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs
index 08b3ae8944d630..4f1c6d9ac10896 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs
@@ -60,6 +60,7 @@ public sealed partial class Thread
// Set in unmanaged and read in managed code.
private bool _isDead;
+ private bool _isThreadPool;
private Thread() { }
@@ -89,13 +90,13 @@ private unsafe void StartCore()
{
fixed (char* pThreadName = _name)
{
- StartInternal(GetNativeHandle(), _startHelper?._maxStackSize ?? 0, _priority, pThreadName);
+ StartInternal(GetNativeHandle(), _startHelper?._maxStackSize ?? 0, _priority, _isThreadPool ? Interop.BOOL.TRUE : Interop.BOOL.FALSE, pThreadName);
}
}
}
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_Start")]
- private static unsafe partial void StartInternal(ThreadHandle t, int stackSize, int priority, char* pThreadName);
+ private static unsafe partial void StartInternal(ThreadHandle t, int stackSize, int priority, Interop.BOOL isThreadPool, char* pThreadName);
// Called from the runtime
private void StartCallback()
@@ -194,9 +195,24 @@ partial void ThreadNameChanged(string? value)
///
public bool IsBackground
{
- get => GetIsBackground();
+ get
+ {
+ if (_isDead)
+ {
+ throw new ThreadStateException(SR.ThreadState_Dead_State);
+ }
+
+ Interop.BOOL res = GetIsBackground(GetNativeHandle());
+ GC.KeepAlive(this);
+ return res != Interop.BOOL.FALSE;
+ }
set
{
+ if (_isDead)
+ {
+ throw new ThreadStateException(SR.ThreadState_Dead_State);
+ }
+
SetIsBackground(GetNativeHandle(), value ? Interop.BOOL.TRUE : Interop.BOOL.FALSE);
GC.KeepAlive(this);
if (!value)
@@ -206,19 +222,36 @@ public bool IsBackground
}
}
- [MethodImpl(MethodImplOptions.InternalCall)]
- private extern bool GetIsBackground();
+ [SuppressGCTransition]
+ [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_GetIsBackground")]
+ private static partial Interop.BOOL GetIsBackground(ThreadHandle t);
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_SetIsBackground")]
private static partial void SetIsBackground(ThreadHandle t, Interop.BOOL value);
/// Returns true if the thread is a threadpool thread.
- public extern bool IsThreadPoolThread
+ public bool IsThreadPoolThread
{
- [MethodImpl(MethodImplOptions.InternalCall)]
- get;
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal set;
+ get
+ {
+ if (_isDead)
+ {
+ throw new ThreadStateException(SR.ThreadState_Dead_State);
+ }
+
+ return _isThreadPool;
+ }
+ internal set
+ {
+ Debug.Assert(value);
+ Debug.Assert(!_isDead);
+ Debug.Assert(((ThreadState & ThreadState.Unstarted) != 0)
+#if TARGET_WINDOWS
+ || ThreadPool.UseWindowsThreadPool
+#endif
+ );
+ _isThreadPool = value;
+ }
}
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_SetPriority")]
diff --git a/src/coreclr/vm/comsynchronizable.cpp b/src/coreclr/vm/comsynchronizable.cpp
index 7f1751aaa15f58..e4a8c87023515e 100644
--- a/src/coreclr/vm/comsynchronizable.cpp
+++ b/src/coreclr/vm/comsynchronizable.cpp
@@ -127,20 +127,17 @@ INT32 MapFromNTPriority(INT32 NTPriority)
return ours;
}
-
-void ThreadNative::KickOffThread_Worker(LPVOID ptr)
+static void KickOffThread_Worker(LPVOID ptr)
{
CONTRACTL
{
GC_TRIGGERS;
THROWS;
MODE_COOPERATIVE;
+ PRECONDITION(ptr == NULL);
}
CONTRACTL_END;
- KickOffThread_Args *pKickOffArgs = (KickOffThread_Args *) ptr;
- pKickOffArgs->retVal = 0;
-
PREPARE_NONVIRTUAL_CALLSITE(METHOD__THREAD__START_CALLBACK);
DECLARE_ARGHOLDER_ARRAY(args, 1);
args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(GetThread()->GetExposedObjectRaw());
@@ -175,7 +172,7 @@ static void PulseAllHelper(Thread* pThread)
}
// When an exposed thread is started by Win32, this is where it starts.
-ULONG WINAPI ThreadNative::KickOffThread(void* pass)
+static ULONG WINAPI KickOffThread(void* pass)
{
CONTRACTL
@@ -212,11 +209,7 @@ ULONG WINAPI ThreadNative::KickOffThread(void* pass)
_ASSERTE(GetThread() == pThread); // Now that it's started
- KickOffThread_Args args;
- args.share = NULL;
- args.pThread = pThread;
-
- ManagedThreadBase::KickOff(KickOffThread_Worker, &args);
+ ManagedThreadBase::KickOff(KickOffThread_Worker, NULL);
PulseAllHelper(pThread);
@@ -230,21 +223,13 @@ ULONG WINAPI ThreadNative::KickOffThread(void* pass)
return 0;
}
-extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, PCWSTR pThreadName)
+extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, BOOL isThreadPool, PCWSTR pThreadName)
{
QCALL_CONTRACT;
BEGIN_QCALL;
- ThreadNative::Start(thread, threadStackSize, priority, pThreadName);
-
- END_QCALL;
-}
-
-void ThreadNative::Start(Thread* pNewThread, int threadStackSize, int priority, PCWSTR pThreadName)
-{
- STANDARD_VM_CONTRACT;
-
+ Thread* pNewThread = thread;
_ASSERTE(pNewThread != NULL);
// Is the thread already started? You can't restart a thread.
@@ -291,6 +276,8 @@ void ThreadNative::Start(Thread* pNewThread, int threadStackSize, int priority,
pNewThread->ChooseThreadCPUGroupAffinity();
pNewThread->SetThreadState(Thread::TS_LegalToJoin);
+ if (isThreadPool)
+ pNewThread->SetIsThreadPoolThread();
DWORD ret = pNewThread->StartThread();
@@ -319,6 +306,8 @@ void ThreadNative::Start(Thread* pNewThread, int threadStackSize, int priority,
PulseAllHelper(pNewThread);
pNewThread->HandleThreadStartupFailure();
}
+
+ END_QCALL;
}
extern "C" void QCALLTYPE ThreadNative_SetPriority(QCall::ObjectHandleOnStack thread, INT32 iPriority)
@@ -427,24 +416,6 @@ extern "C" void QCALLTYPE ThreadNative_Initialize(QCall::ObjectHandleOnStack t)
END_QCALL;
}
-// Return whether or not this is a background thread.
-FCIMPL1(FC_BOOL_RET, ThreadNative::GetIsBackground, ThreadBaseObject* pThisUNSAFE)
-{
- FCALL_CONTRACT;
-
- if (pThisUNSAFE==NULL)
- FCThrowRes(kNullReferenceException, W("NullReference_This"));
-
- // validate the thread
- Thread *thread = pThisUNSAFE->GetInternal();
-
- if (ThreadIsDead(thread))
- FCThrowRes(kThreadStateException, W("ThreadState_Dead_State"));
-
- FC_RETURN_BOOL(thread->IsBackground());
-}
-FCIMPLEND
-
// Deliver the state of the thread as a consistent set of bits.
// Duplicate logic in DacDbiInterfaceImpl::GetPartialUserState()
extern "C" INT32 QCALLTYPE ThreadNative_GetThreadState(QCall::ThreadHandle thread)
@@ -729,6 +700,27 @@ FCIMPL1(void, ThreadNative::Finalize, ThreadBaseObject* pThisUNSAFE)
}
FCIMPLEND
+// Get whether or not this is a background thread.
+extern "C" BOOL QCALLTYPE ThreadNative_GetIsBackground(QCall::ThreadHandle thread)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK_NO_GC_TRANSITION;
+ PRECONDITION(thread != NULL);
+ }
+ CONTRACTL_END;
+
+ BOOL res = FALSE;
+
+ BEGIN_QCALL;
+
+ res = thread->IsBackground();
+
+ END_QCALL;
+
+ return res;
+}
+
// Set whether or not this is a background thread.
extern "C" void QCALLTYPE ThreadNative_SetIsBackground(QCall::ThreadHandle thread, BOOL value)
{
@@ -741,9 +733,6 @@ extern "C" void QCALLTYPE ThreadNative_SetIsBackground(QCall::ThreadHandle threa
BEGIN_QCALL;
- if (ThreadIsDead(thread))
- COMPlusThrow(kThreadStateException, W("ThreadState_Dead_State"));
-
thread->SetBackground(value);
END_QCALL;
@@ -755,16 +744,10 @@ extern "C" void QCALLTYPE ThreadNative_InformThreadNameChange(QCall::ThreadHandl
BEGIN_QCALL;
- ThreadNative::InformThreadNameChange(thread, name, len);
-
- END_QCALL;
-}
+ Thread* pThread = thread;
-void ThreadNative::InformThreadNameChange(Thread* pThread, LPCWSTR name, INT32 len)
-{
- // Set on Windows 10 Creators Update and later machines the unmanaged thread name as well. That will show up in ETW traces and debuggers which is very helpful
- // if more and more threads get a meaningful name
- // Will also show up in Linux in gdb and such.
+ // The name will show up in ETW traces and debuggers which is very helpful if more and more threads
+ // get a meaningful name. Will also show up in Linux in gdb and such.
if (len > 0 && name != NULL && pThread->GetThreadHandle() != INVALID_HANDLE_VALUE)
{
SetThreadName(pThread->GetThreadHandle(), name);
@@ -785,7 +768,6 @@ void ThreadNative::InformThreadNameChange(Thread* pThread, LPCWSTR name, INT32 l
}
#endif // PROFILING_SUPPORTED
-
#ifdef DEBUGGING_SUPPORTED
if (CORDebuggerAttached())
{
@@ -793,43 +775,9 @@ void ThreadNative::InformThreadNameChange(Thread* pThread, LPCWSTR name, INT32 l
g_pDebugInterface->NameChangeEvent(NULL, pThread);
}
#endif // DEBUGGING_SUPPORTED
-}
-
-FCIMPL1(FC_BOOL_RET, ThreadNative::IsThreadpoolThread, ThreadBaseObject* thread)
-{
- FCALL_CONTRACT;
-
- if (thread==NULL)
- FCThrowRes(kNullReferenceException, W("NullReference_This"));
- Thread *pThread = thread->GetInternal();
-
- if (pThread == NULL)
- FCThrowRes(kThreadStateException, W("ThreadState_Dead_State"));
-
- BOOL ret = pThread->IsThreadPoolThread();
-
- FC_GC_POLL_RET();
-
- FC_RETURN_BOOL(ret);
-}
-FCIMPLEND
-
-FCIMPL1(void, ThreadNative::SetIsThreadpoolThread, ThreadBaseObject* thread)
-{
- FCALL_CONTRACT;
-
- if (thread == NULL)
- FCThrowResVoid(kNullReferenceException, W("NullReference_This"));
-
- Thread *pThread = thread->GetInternal();
-
- if (pThread == NULL)
- FCThrowResVoid(kThreadStateException, W("ThreadState_Dead_State"));
-
- pThread->SetIsThreadPoolThread();
+ END_QCALL;
}
-FCIMPLEND
FCIMPL0(INT32, ThreadNative::GetOptimalMaxSpinWaitsPerSpinIteration)
{
diff --git a/src/coreclr/vm/comsynchronizable.h b/src/coreclr/vm/comsynchronizable.h
index b7c64c529084f8..c06af82d0f2967 100644
--- a/src/coreclr/vm/comsynchronizable.h
+++ b/src/coreclr/vm/comsynchronizable.h
@@ -15,22 +15,9 @@
#ifndef _COMSYNCHRONIZABLE_H
#define _COMSYNCHRONIZABLE_H
-#include "field.h" // For FieldDesc definition.
-
-//
-// Each function that we call through native only gets one argument,
-// which is actually a pointer to its stack of arguments. Our structs
-// for accessing these are defined below.
-//
-
-struct SharedState;
-
class ThreadNative
{
-friend class ThreadBaseObject;
-
public:
-
enum
{
PRIORITY_LOWEST = 0,
@@ -52,30 +39,14 @@ friend class ThreadBaseObject;
ThreadAbortRequested = 128,
};
- static FCDECL1(FC_BOOL_RET, GetIsBackground, ThreadBaseObject* pThisUNSAFE);
-
static FCDECL0(INT32, GetOptimalMaxSpinWaitsPerSpinIteration);
static FCDECL1(void, Finalize, ThreadBaseObject* pThis);
- static FCDECL1(FC_BOOL_RET,IsThreadpoolThread, ThreadBaseObject* thread);
- static FCDECL1(void, SetIsThreadpoolThread, ThreadBaseObject* thread);
-
- static void Start(Thread* pNewThread, int threadStackSize, int priority, PCWSTR pThreadName);
- static void InformThreadNameChange(Thread* pThread, LPCWSTR name, INT32 len);
-private:
-
- struct KickOffThread_Args {
- Thread *pThread;
- SharedState *share;
- ULONG retVal;
- };
-
- static void KickOffThread_Worker(LPVOID /* KickOffThread_Args* */);
- static ULONG WINAPI KickOffThread(void *pass);
};
-extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, PCWSTR pThreadName);
+extern "C" void QCALLTYPE ThreadNative_Start(QCall::ThreadHandle thread, int threadStackSize, int priority, BOOL isThreadPool, PCWSTR pThreadName);
extern "C" void QCALLTYPE ThreadNative_SetPriority(QCall::ObjectHandleOnStack thread, INT32 iPriority);
extern "C" void QCALLTYPE ThreadNative_GetCurrentThread(QCall::ObjectHandleOnStack thread);
+extern "C" BOOL QCALLTYPE ThreadNative_GetIsBackground(QCall::ThreadHandle thread);
extern "C" void QCALLTYPE ThreadNative_SetIsBackground(QCall::ThreadHandle thread, BOOL value);
extern "C" void QCALLTYPE ThreadNative_InformThreadNameChange(QCall::ThreadHandle thread, LPCWSTR name, INT32 len);
extern "C" BOOL QCALLTYPE ThreadNative_YieldThread();
diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp
index f15b1085ebab4e..3788b19f0da975 100644
--- a/src/coreclr/vm/comutilnative.cpp
+++ b/src/coreclr/vm/comutilnative.cpp
@@ -688,19 +688,15 @@ extern "C" int QCALLTYPE GCInterface_WaitForFullGCComplete(int millisecondsTimeo
return result;
}
-/*================================GetGeneration=================================
+/*================================GetGenerationInternal=================================
**Action: Returns the generation in which args->obj is found.
**Returns: The generation in which args->obj is found.
**Arguments: args->obj -- The object to locate.
-**Exceptions: ArgumentException if args->obj is null.
==============================================================================*/
-FCIMPL1(int, GCInterface::GetGeneration, Object* objUNSAFE)
+FCIMPL1(int, GCInterface::GetGenerationInternal, Object* objUNSAFE)
{
FCALL_CONTRACT;
-
- if (objUNSAFE == NULL)
- FCThrowArgumentNull(W("obj"));
-
+ _ASSERTE(objUNSAFE != NULL);
int result = (INT32)GCHeapUtilities::GetGCHeap()->WhichGeneration(objUNSAFE);
FC_GC_POLL_RET();
return result;
diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h
index ef41239a6bb0f3..473300b87677f9 100644
--- a/src/coreclr/vm/comutilnative.h
+++ b/src/coreclr/vm/comutilnative.h
@@ -170,7 +170,7 @@ class GCInterface {
static FCDECL1(void, SetLOHCompactionMode, int newLOHCompactionyMode);
static FCDECL2(FC_BOOL_RET, RegisterForFullGCNotification, UINT32 gen2Percentage, UINT32 lohPercentage);
static FCDECL0(FC_BOOL_RET, CancelFullGCNotification);
- static FCDECL1(int, GetGeneration, Object* objUNSAFE);
+ static FCDECL1(int, GetGenerationInternal, Object* objUNSAFE);
static FCDECL0(UINT64, GetSegmentSize);
static FCDECL0(int, GetLastGCPercentTimeInGC);
static FCDECL1(UINT64, GetGenerationSize, int gen);
diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h
index 138e3d51399e60..17ee79fb968581 100644
--- a/src/coreclr/vm/corelib.h
+++ b/src/coreclr/vm/corelib.h
@@ -836,6 +836,7 @@ DEFINE_FIELD_U(_startHelper, ThreadBaseObject, m_StartHelper)
DEFINE_FIELD_U(_DONT_USE_InternalThread, ThreadBaseObject, m_InternalThread)
DEFINE_FIELD_U(_priority, ThreadBaseObject, m_Priority)
DEFINE_FIELD_U(_isDead, ThreadBaseObject, m_IsDead)
+DEFINE_FIELD_U(_isThreadPool, ThreadBaseObject, m_IsThreadPool)
DEFINE_CLASS(THREAD, Threading, Thread)
DEFINE_METHOD(THREAD, START_CALLBACK, StartCallback, IM_RetVoid)
#ifdef FEATURE_OBJCMARSHAL
diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h
index b1f475b3b16406..8996b3a16d8115 100644
--- a/src/coreclr/vm/ecalllist.h
+++ b/src/coreclr/vm/ecalllist.h
@@ -299,9 +299,6 @@ FCFuncEnd()
FCFuncStart(gThreadFuncs)
FCFuncElement("InternalFinalize", ThreadNative::Finalize)
- FCFuncElement("GetIsBackground", ThreadNative::GetIsBackground)
- FCFuncElement("get_IsThreadPoolThread", ThreadNative::IsThreadpoolThread)
- FCFuncElement("set_IsThreadPoolThread", ThreadNative::SetIsThreadpoolThread)
FCFuncElement("get_OptimalMaxSpinWaitsPerSpinIteration", ThreadNative::GetOptimalMaxSpinWaitsPerSpinIteration)
FCFuncEnd()
@@ -340,7 +337,7 @@ FCFuncStart(gGCInterfaceFuncs)
FCFuncElement("GetSegmentSize", GCInterface::GetSegmentSize)
FCFuncElement("GetLastGCPercentTimeInGC", GCInterface::GetLastGCPercentTimeInGC)
FCFuncElement("GetGenerationSize", GCInterface::GetGenerationSize)
- FCFuncElement("GetGeneration", GCInterface::GetGeneration)
+ FCFuncElement("GetGenerationInternal", GCInterface::GetGenerationInternal)
FCFuncElement("GetMaxGeneration", GCInterface::GetMaxGeneration)
FCFuncElement("_SuppressFinalize", GCInterface::SuppressFinalize)
@@ -396,9 +393,8 @@ FCFuncStart(gRuntimeHelpers)
FCFuncElement("PrepareDelegate", ReflectionInvocation::PrepareDelegate)
FCFuncElement("TryGetHashCode", ObjectNative::TryGetHashCode)
FCFuncElement("ContentEquals", ObjectNative::ContentEquals)
- FCFuncElement("EnsureSufficientExecutionStack", ReflectionInvocation::EnsureSufficientExecutionStack)
FCFuncElement("TryEnsureSufficientExecutionStack", ReflectionInvocation::TryEnsureSufficientExecutionStack)
- FCFuncElement("AllocTailCallArgBuffer", TailCallHelp::AllocTailCallArgBuffer)
+ FCFuncElement("AllocTailCallArgBufferWorker", TailCallHelp::AllocTailCallArgBufferWorker)
FCFuncElement("GetTailCallInfo", TailCallHelp::GetTailCallInfo)
FCFuncElement("Box", JIT_Box)
FCFuncElement("Unbox_Nullable", JIT_Unbox_Nullable)
diff --git a/src/coreclr/vm/fcall.h b/src/coreclr/vm/fcall.h
index a8b11854e795e2..5982611e882952 100644
--- a/src/coreclr/vm/fcall.h
+++ b/src/coreclr/vm/fcall.h
@@ -1242,29 +1242,9 @@ struct FCSigCheck {
return 0; \
}
-//==============================================================================================
-// Like FCThrow but can be used for a VOID-returning FCall. The only
-// difference is in the "return" statement.
-//==============================================================================================
-#define FCThrowVoid(reKind) FCThrowExVoid(reKind, 0, 0, 0, 0)
-
-//==============================================================================================
-// This version lets you attach a message with inserts (similar to
-// COMPlusThrow()).
-//==============================================================================================
-#define FCThrowExVoid(reKind, resID, arg1, arg2, arg3) \
- { \
- while (NULL == \
- __FCThrow(__me, reKind, resID, arg1, arg2, arg3)) {}; \
- return; \
- }
-
// Use FCThrowRes to throw an exception with a localized error message from the
// ResourceManager in managed code.
#define FCThrowRes(reKind, resourceName) FCThrowArgumentEx(reKind, NULL, resourceName)
-#define FCThrowArgumentNull(argName) FCThrowArgumentEx(kArgumentNullException, argName, NULL)
-#define FCThrowArgumentOutOfRange(argName, message) FCThrowArgumentEx(kArgumentOutOfRangeException, argName, message)
-#define FCThrowArgument(argName, message) FCThrowArgumentEx(kArgumentException, argName, message)
#define FCThrowArgumentEx(reKind, argName, resourceName) \
{ \
@@ -1276,9 +1256,6 @@ struct FCSigCheck {
// Use FCThrowRes to throw an exception with a localized error message from the
// ResourceManager in managed code.
#define FCThrowResVoid(reKind, resourceName) FCThrowArgumentVoidEx(reKind, NULL, resourceName)
-#define FCThrowArgumentNullVoid(argName) FCThrowArgumentVoidEx(kArgumentNullException, argName, NULL)
-#define FCThrowArgumentOutOfRangeVoid(argName, message) FCThrowArgumentVoidEx(kArgumentOutOfRangeException, argName, message)
-#define FCThrowArgumentVoid(argName, message) FCThrowArgumentVoidEx(kArgumentException, argName, message)
#define FCThrowArgumentVoidEx(reKind, argName, resourceName) \
{ \
diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h
index c9abe58b8e7316..e637a64da2fd16 100644
--- a/src/coreclr/vm/object.h
+++ b/src/coreclr/vm/object.h
@@ -1327,6 +1327,8 @@ class ThreadBaseObject : public Object
// Set in unmanaged code and read in managed code.
bool m_IsDead;
+ bool m_IsThreadPool;
+
protected:
// the ctor and dtor can do no useful work.
ThreadBaseObject() {LIMITED_METHOD_CONTRACT;};
diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp
index bd4f396de49590..18e080bbe12d21 100644
--- a/src/coreclr/vm/qcallentrypoints.cpp
+++ b/src/coreclr/vm/qcallentrypoints.cpp
@@ -240,6 +240,7 @@ static const Entry s_QCall[] =
DllImportEntry(ThreadNative_Start)
DllImportEntry(ThreadNative_SetPriority)
DllImportEntry(ThreadNative_GetCurrentThread)
+ DllImportEntry(ThreadNative_GetIsBackground)
DllImportEntry(ThreadNative_SetIsBackground)
DllImportEntry(ThreadNative_InformThreadNameChange)
DllImportEntry(ThreadNative_YieldThread)
diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp
index d332fc12a468c8..1cd79ba6326c8b 100644
--- a/src/coreclr/vm/reflectioninvocation.cpp
+++ b/src/coreclr/vm/reflectioninvocation.cpp
@@ -1438,37 +1438,17 @@ FCIMPL1(void, ReflectionInvocation::PrepareDelegate, Object* delegateUNSAFE)
}
FCIMPLEND
-// This method checks to see if there is sufficient stack to execute the average Framework method.
-// If there is not, then it throws System.InsufficientExecutionStackException. The limit for each
-// thread is precomputed when the thread is created.
-FCIMPL0(void, ReflectionInvocation::EnsureSufficientExecutionStack)
-{
- FCALL_CONTRACT;
-
- Thread *pThread = GetThread();
-
- // We use the address of a local variable as our "current stack pointer", which is
- // plenty close enough for the purposes of this method.
- UINT_PTR current = reinterpret_cast(&pThread);
- UINT_PTR limit = pThread->GetCachedStackSufficientExecutionLimit();
-
- if (current < limit)
- {
- FCThrowVoid(kInsufficientExecutionStackException);
- }
-}
-FCIMPLEND
-
-// As with EnsureSufficientExecutionStack, this method checks and returns whether there is
-// sufficient stack to execute the average Framework method, but rather than throwing,
-// it simply returns a Boolean: true for sufficient stack space, otherwise false.
+// This method checks and returns whether there is sufficient stack to execute the
+// average Framework method, but rather than throwing, it simply returns a
+// Boolean: true for sufficient stack space, otherwise false.
FCIMPL0(FC_BOOL_RET, ReflectionInvocation::TryEnsureSufficientExecutionStack)
{
FCALL_CONTRACT;
Thread *pThread = GetThread();
- // Same logic as EnsureSufficientExecutionStack
+ // We use the address of a local variable as our "current stack pointer", which is
+ // plenty close enough for the purposes of this method.
UINT_PTR current = reinterpret_cast(&pThread);
UINT_PTR limit = pThread->GetCachedStackSufficientExecutionLimit();
diff --git a/src/coreclr/vm/reflectioninvocation.h b/src/coreclr/vm/reflectioninvocation.h
index ff20d72d870f9c..f2879590f2d96e 100644
--- a/src/coreclr/vm/reflectioninvocation.h
+++ b/src/coreclr/vm/reflectioninvocation.h
@@ -47,7 +47,6 @@ class ReflectionInvocation {
public:
static FCDECL1(void, PrepareDelegate, Object* delegateUNSAFE);
- static FCDECL0(void, EnsureSufficientExecutionStack);
static FCDECL0(FC_BOOL_RET, TryEnsureSufficientExecutionStack);
// TypedReference functions, should go somewhere else
diff --git a/src/coreclr/vm/tailcallhelp.cpp b/src/coreclr/vm/tailcallhelp.cpp
index 4d9c60838b54f5..d59a2861a80c42 100644
--- a/src/coreclr/vm/tailcallhelp.cpp
+++ b/src/coreclr/vm/tailcallhelp.cpp
@@ -11,23 +11,11 @@
#include "threads.h"
-FCIMPL2(void*, TailCallHelp::AllocTailCallArgBuffer, INT32 size, void* gcDesc)
+FCIMPL2(void*, TailCallHelp::AllocTailCallArgBufferWorker, INT32 size, void* gcDesc)
{
- CONTRACTL
- {
- FCALL_CHECK;
- INJECT_FAULT(FCThrow(kOutOfMemoryException););
- }
- CONTRACTL_END
-
+ FCALL_CONTRACT;
_ASSERTE(size >= 0);
-
- void* result = GetThread()->GetTailCallTls()->AllocArgBuffer(size, gcDesc);
-
- if (result == NULL)
- FCThrow(kOutOfMemoryException);
-
- return result;
+ return GetThread()->GetTailCallTls()->AllocArgBuffer(size, gcDesc);
}
FCIMPLEND
diff --git a/src/coreclr/vm/tailcallhelp.h b/src/coreclr/vm/tailcallhelp.h
index 32883076a69201..10b14bd9f6161d 100644
--- a/src/coreclr/vm/tailcallhelp.h
+++ b/src/coreclr/vm/tailcallhelp.h
@@ -13,7 +13,7 @@ struct ArgBufferLayout;
class TailCallHelp
{
public:
- static FCDECL2(void*, AllocTailCallArgBuffer, INT32, void*);
+ static FCDECL2(void*, AllocTailCallArgBufferWorker, INT32, void*);
static FCDECL2(void*, GetTailCallInfo, void**, void**);
static void CreateTailCallHelperStubs(
diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp
index 99a366e9a2f131..1db3062c466e77 100644
--- a/src/coreclr/vm/threads.cpp
+++ b/src/coreclr/vm/threads.cpp
@@ -6232,9 +6232,9 @@ BOOL Thread::SetStackLimits(SetStackLimitScope scope)
return FALSE;
}
- // Compute the limit used by EnsureSufficientExecutionStack and cache it on the thread. This minimum stack size should
+ // Compute the limit used by TryEnsureSufficientExecutionStack and cache it on the thread. This minimum stack size should
// be sufficient to allow a typical non-recursive call chain to execute, including potential exception handling and
- // garbage collection. Used for probing for available stack space through RuntimeImports.EnsureSufficientExecutionStack,
+ // garbage collection. Used for probing for available stack space through RuntimeImports.TryEnsureSufficientExecutionStack,
// among other things.
#ifdef HOST_64BIT
const UINT_PTR MinExecutionStackSize = 128 * 1024;
diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h
index 5c0f0bc8e1c315..e096162eb97724 100644
--- a/src/coreclr/vm/threads.h
+++ b/src/coreclr/vm/threads.h
@@ -2420,7 +2420,7 @@ class Thread
// These access the stack base and limit values for this thread. (They are cached during InitThread.) The
// "stack base" is the "upper bound", i.e., where the stack starts growing from. (Main's call frame is at the
// upper bound.) The "stack limit" is the "lower bound", i.e., how far the stack can grow down to.
- // The "stack sufficient execution limit" is used by EnsureSufficientExecutionStack() to limit how much stack
+ // The "stack sufficient execution limit" is used by TryEnsureSufficientExecutionStack() to limit how much stack
// should remain to execute the average Framework method.
PTR_VOID GetCachedStackBase() {LIMITED_METHOD_DAC_CONTRACT; return m_CacheStackBase; }
PTR_VOID GetCachedStackLimit() {LIMITED_METHOD_DAC_CONTRACT; return m_CacheStackLimit;}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/RegisteredWaitHandle.Portable.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/RegisteredWaitHandle.Portable.cs
index 74dbefe5869067..574dbf5ee2ed28 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/RegisteredWaitHandle.Portable.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/RegisteredWaitHandle.Portable.cs
@@ -58,7 +58,7 @@ internal RegisteredWaitHandle(WaitHandle waitHandle, _ThreadPoolWaitOrTimerCallb
#if TARGET_WASI
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
#endif
-#if WINDOWS
+#if TARGET_WINDOWS
Debug.Assert(!ThreadPool.UseWindowsThreadPool);
#endif
GC.SuppressFinalize(this);