Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadSuspendInjection, W("INTERNAL_ThreadSusp
///
/// Thread (miscellaneous)
///
RETAIL_CONFIG_DWORD_INFO(INTERNAL_DefaultStackSize, W("DefaultStackSize"), 0, "Stack size to use for new VM threads when thread is created with default stack size (dwStackSize == 0).")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Thread_DefaultStackSize, W("Thread_DefaultStackSize"), 0, "Stack size to use for new VM threads when thread is created with default stack size (dwStackSize == 0).")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_Thread_DeadThreadCountThresholdForGCTrigger, W("Thread_DeadThreadCountThresholdForGCTrigger"), 75, "In the heuristics to clean up dead threads, this threshold must be reached before triggering a GC will be considered. Set to 0 to disable triggering a GC based on dead threads.")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_Thread_DeadThreadGCTriggerPeriodMilliseconds, W("Thread_DeadThreadGCTriggerPeriodMilliseconds"), 1000 * 60 * 30, "In the heuristics to clean up dead threads, this much time must have elapsed since the previous max-generation GC before triggering another GC will be considered")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Thread_UseAllCpuGroups, W("Thread_UseAllCpuGroups"), 0, "Specifies whether to query and use CPU group information for determining the processor count.")
Expand Down
19 changes: 19 additions & 0 deletions src/coreclr/nativeaot/Runtime/RhConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,23 @@ bool RhConfig::GetEmbeddedVariable(Config* config, _In_z_ const char* configName
return false;
}

size_t GetDefaultStackSizeSetting()
{
// Keep the same arbitrary minimum and maximum from the CoreCLR VM layer.
const size_t minStack = 0x10000; // 64K
const size_t maxStack = 0x80000000; // 2G

uint64_t uiStacksize;
if (g_pRhConfig->ReadConfigValue("Thread_DefaultStackSize", &uiStacksize)
|| g_pRhConfig->ReadKnobUInt64Value("System.Threading.DefaultStackSize", &uiStacksize))
{
if (uiStacksize < maxStack || uiStacksize >= minStack)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why || and not &&. I assume it is always true now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! #118077

{
return (size_t)uiStacksize;
}
}

return 0;
}

#endif
2 changes: 2 additions & 0 deletions src/coreclr/nativeaot/Runtime/RhConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class RhConfig

extern RhConfig * g_pRhConfig;

size_t GetDefaultStackSizeSetting();

#endif //!DACCESS_COMPILE

#endif // RHCONFIG_H
6 changes: 6 additions & 0 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,12 @@ FCIMPL0(uint64_t, RhCurrentOSThreadId)
}
FCIMPLEND

FCIMPL0(size_t, RhGetDefaultStackSize)
{
return GetDefaultStackSizeSetting();
}
FCIMPLEND

// Standard calling convention variant and actual implementation for RhpReversePInvokeAttachOrTrapThread
EXTERN_C NOINLINE void FASTCALL RhpReversePInvokeAttachOrTrapThread2(ReversePInvokeFrame* pFrame)
{
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,13 @@ bool PalStartBackgroundWork(_In_ BackgroundCallback callback, _In_opt_ void* pCa

int st = pthread_attr_init(&attrs);
ASSERT(st == 0);

size_t stacksize = GetDefaultStackSizeSetting();
if (stacksize != 0)
{
st = pthread_attr_setstacksize(&attrs, stacksize);
ASSERT(st == 0);
}

static const int NormalPriority = 0;
static const int HighestPriority = -20;
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/nativeaot/Runtime/windows/PalMinWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -846,9 +846,11 @@ static pfnSetThreadDescription g_pfnSetThreadDescription = SET_THREAD_DESCRIPTIO

bool PalStartBackgroundWork(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext, BOOL highPriority)
{
DWORD stacksize = (DWORD)GetDefaultStackSizeSetting();

HANDLE hThread = CreateThread(
NULL,
0,
(DWORD)stacksize,
(LPTHREAD_START_ROUTINE)callback,
pCallbackContext,
highPriority ? CREATE_SUSPENDED : 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,10 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe
[RuntimeImport(RuntimeLibrary, "RhCurrentOSThreadId")]
internal static extern unsafe ulong RhCurrentOSThreadId();

[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhGetDefaultStackSize")]
internal static extern unsafe IntPtr RhGetDefaultStackSize();

[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport("*", "RhGetCurrentThunkContext")]
internal static extern IntPtr GetCurrentInteropThunkContext();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,14 @@ private unsafe bool CreateThread(GCHandle<Thread> thisThreadHandle)
// This also avoids OOM after creating the thread.
_stopped = new ManualResetEvent(false);

if (!Interop.Sys.CreateThread((IntPtr)_startHelper!._maxStackSize, &ThreadEntryPoint, GCHandle<Thread>.ToIntPtr(thisThreadHandle)))
nint stackSize = _startHelper!._maxStackSize;

if (stackSize <= 0)
{
stackSize = RuntimeImports.RhGetDefaultStackSize();
}

if (!Interop.Sys.CreateThread(stackSize, &ThreadEntryPoint, GCHandle<Thread>.ToIntPtr(thisThreadHandle)))
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,13 @@ private bool JoinInternal(int millisecondsTimeout)
private unsafe bool CreateThread(GCHandle<Thread> thisThreadHandle)
{
const int AllocationGranularity = 0x10000; // 64 KiB

int stackSize = _startHelper._maxStackSize;

if (stackSize <= 0)
{
stackSize = (int)RuntimeImports.RhGetDefaultStackSize();
}

if ((0 < stackSize) && (stackSize < AllocationGranularity))
{
// If StackSizeParamIsAReservation flag is set and the reserve size specified by CreateThread's
Expand Down
7 changes: 5 additions & 2 deletions src/coreclr/vm/threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "comutilnative.h"
#include "finalizerthread.h"
#include "threadsuspend.h"
#include "configuration.h"

#include "wrappers.h"

Expand Down Expand Up @@ -2078,9 +2079,11 @@ void ParseDefaultStackSize(LPCWSTR valueStr)

SIZE_T GetDefaultStackSizeSetting()
{
static DWORD s_defaultStackSizeEnv = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DefaultStackSize);
static DWORD s_defaultStackSizeEnv = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Thread_DefaultStackSize);
static DWORD s_defaultStackSizeProp = Configuration::GetKnobDWORDValue(W("System.Threading.DefaultStackSize"), 0);

uint64_t value = s_defaultStackSizeEnv ? s_defaultStackSizeEnv : s_defaultStackSizeProperty;
uint64_t value = s_defaultStackSizeEnv ? s_defaultStackSizeEnv
: (s_defaultStackSizeProperty ? s_defaultStackSizeProperty : s_defaultStackSizeProp);

SIZE_T minStack = 0x10000; // 64K - Somewhat arbitrary minimum thread stack size
SIZE_T maxStack = 0x80000000; // 2G - Somewhat arbitrary maximum thread stack size
Expand Down
Loading