Skip to content

Commit

Permalink
Implement icall used by RuntimeHelpers.EnsureSufficientExecutionStack…
Browse files Browse the repository at this point in the history
… on netcore Mono.

Current implementation always returned true for Windows/Linux/Android.
There are however use of this API in Task library to make sure recursive
tasks won't hit stackoverflow. There are several tests in System.Threading.Tasks
that currently hit this, at least on Windows, causing test failures.

Fix use stack limits already setup in register_thread and used by GC when
doing conservative stack scan. If the limits have not been setup or is not
supported on platform, we will use old defaults, always assume there is
enough stack space available. Heuristics around size of minimum execution
stack needed are picked from corresponding CoreCLR implementation.
  • Loading branch information
lateralusX committed Mar 23, 2020
1 parent 8db7154 commit edbb000
Showing 1 changed file with 32 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/mono/mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@

//#define MONO_DEBUG_ICALLARRAY

// Inline with CoreCLR heuristics, https://github.com/dotnet/runtime/blob/385b4d4296f9c5cb82363565aa210a1a37f92d90/src/coreclr/src/vm/threads.cpp#L6344.
// 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 RuntimeHelpers.EnsureSufficientExecutionStack.
#if TARGET_SIZEOF_VOID_P == 8
#define MONO_MIN_EXECUTION_STACK_SIZE (128 * 1024)
#else
#define MONO_MIN_EXECUTION_STACK_SIZE (64 * 1024)
#endif

#ifdef MONO_DEBUG_ICALLARRAY

static char debug_icallarray; // 0:uninitialized 1:true 2:false
Expand Down Expand Up @@ -1293,6 +1303,27 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (M
mono_runtime_class_init_full (vtable, error);
}

#ifdef ENABLE_NETCORE
MonoBoolean
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
{
MonoThreadInfo *thread = mono_thread_info_current ();
void *current = &thread;

// Stack upper/lower bound should have been calculated and set as part of register_thread.
// If not, we are optimistic and assume there is enough room.
if (!thread->stack_start_limit || !thread->stack_end)
return TRUE;

// Stack start limit is stack lower bound. Make sure there is enough room left.
void *limit = ((uint8_t *)thread->stack_start_limit) + MONO_MIN_EXECUTION_STACK_SIZE;

if (current < limit)
return FALSE;

return TRUE;
}
#else
MonoBoolean
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
{
Expand Down Expand Up @@ -1331,6 +1362,7 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStac
#endif
return TRUE;
}
#endif

#ifdef ENABLE_NETCORE
MonoObjectHandle
Expand Down

0 comments on commit edbb000

Please sign in to comment.