diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index 4a58182aa9eae6..4f9a1b1d896c58 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -496,6 +496,19 @@ else() message(FATAL_ERROR "TARGET_ARCH='${TARGET_ARCH}' not supported.") endif() +# Default stack size: 2MB for 64-bit, 1MB for 32-bit. +# Use large (8MB) stack size for s390x/ppc64le due to limited tail call optimization support. +# On Windows, use 0 to defer to the OS/PE header default. +if(TARGET_WIN32) + set(MONO_DEFAULT_STACKSIZE 0) +elseif(TARGET_S390X OR TARGET_POWERPC64) + set(MONO_DEFAULT_STACKSIZE 8388608) +elseif(TARGET_SIZEOF_VOID_P EQUAL 4) + set(MONO_DEFAULT_STACKSIZE 1048576) +else() + set(MONO_DEFAULT_STACKSIZE 2097152) +endif() + # arm64 MacCatalyst runtime host or AOT target is more like Apple mobile targets than x64 if ((HOST_MACCAT AND HOST_ARM64) OR (TARGET_MACCAT AND TARGET_ARM64)) set(TARGET_APPLE_MOBILE 1) diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in index 4fe413349369af..c887a617527d68 100644 --- a/src/mono/cmake/config.h.in +++ b/src/mono/cmake/config.h.in @@ -598,6 +598,9 @@ /* byte order of target */ #define TARGET_BYTE_ORDER @TARGET_BYTE_ORDER@ +/* default stack size for managed threads */ +#define MONO_DEFAULT_STACKSIZE @MONO_DEFAULT_STACKSIZE@ + /* wordsize of target */ #define TARGET_SIZEOF_VOID_P @TARGET_SIZEOF_VOID_P@ diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c index b0794d1a9f69f7..8641175cfee2b7 100644 --- a/src/mono/mono/metadata/threads.c +++ b/src/mono/mono/metadata/threads.c @@ -204,7 +204,7 @@ static MonoThreadAttachCB mono_thread_attach_cb = NULL; static MonoThreadCleanupFunc mono_thread_cleanup_fn = NULL; /* The default stack size for each thread */ -static guint32 default_stacksize = 0; +static guint32 default_stacksize = ~0; static void mono_free_static_data (gpointer* static_data); static void mono_init_static_data_info (StaticDataInfo *static_data); @@ -1371,7 +1371,7 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, MonoThreadStart mono_coop_sem_init (&start_info->registered, 0); if (flags != MONO_THREAD_CREATE_FLAGS_SMALL_STACK) - stack_set_size = stack_size ? stack_size : default_stacksize; + stack_set_size = stack_size ? stack_size : mono_threads_get_default_stacksize(); else stack_set_size = 0; @@ -1445,6 +1445,21 @@ mono_threads_set_default_stacksize (guint32 stacksize) guint32 mono_threads_get_default_stacksize (void) { + if (default_stacksize == ~0) + { + unsigned long stacksize = 0; + + const char *value = g_getenv ("DOTNET_Thread_DefaultStackSize"); + if (value) { + errno = 0; + stacksize = strtoul (value, NULL, 16); + if (errno != 0 || stacksize >= UINT_MAX) + stacksize = 0; + } + + default_stacksize = (guint32)stacksize; + } + return default_stacksize; } diff --git a/src/mono/mono/utils/mono-threads-posix.c b/src/mono/mono/utils/mono-threads-posix.c index fa18993907a032..711c2dd3b64553 100644 --- a/src/mono/mono/utils/mono-threads-posix.c +++ b/src/mono/mono/utils/mono-threads-posix.c @@ -72,10 +72,10 @@ mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_d if (RUNNING_ON_VALGRIND) set_stack_size = 1 << 20; else - set_stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; -#else - set_stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; #endif + { + set_stack_size = MONO_DEFAULT_STACKSIZE; + } } #ifdef PTHREAD_STACK_MIN diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index f43e46c4ffa20a..88ae9557381000 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -225,8 +225,6 @@ mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_d g_error ("%s: pthread_attr_init failed, error: \"%s\" (%d)", __func__, g_strerror (res), res); #if 0 - gsize set_stack_size; - if (stack_size) set_stack_size = *stack_size; else @@ -238,10 +236,10 @@ mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_d if (RUNNING_ON_VALGRIND) set_stack_size = 1 << 20; else - set_stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; -#else - set_stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; #endif + { + set_stack_size = MONO_DEFAULT_STACKSIZE; + } } #ifdef PTHREAD_STACK_MIN diff --git a/src/mono/mono/utils/mono-threads-windows.c b/src/mono/mono/utils/mono-threads-windows.c index 21997a97b624c1..8aeb089b08340b 100644 --- a/src/mono/mono/utils/mono-threads-windows.c +++ b/src/mono/mono/utils/mono-threads-windows.c @@ -395,15 +395,12 @@ mono_threads_suspend_get_abort_signal (void) #if defined (HOST_WIN32) -// Use default stack size on netcore. -#define MONO_WIN32_DEFAULT_NATIVE_STACK_SIZE 0 - gboolean mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid) { HANDLE result; DWORD thread_id; - gsize set_stack_size = MONO_WIN32_DEFAULT_NATIVE_STACK_SIZE; + gsize set_stack_size = MONO_DEFAULT_STACKSIZE; if (stack_size && *stack_size) set_stack_size = *stack_size; @@ -450,7 +447,7 @@ mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2) gboolean mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg) { - return CreateThread (NULL, MONO_WIN32_DEFAULT_NATIVE_STACK_SIZE, (LPTHREAD_START_ROUTINE)func, arg, 0, tid) != NULL; + return CreateThread (NULL, MONO_DEFAULT_STACKSIZE, (LPTHREAD_START_ROUTINE)func, arg, 0, tid) != NULL; } gboolean