Skip to content

Commit

Permalink
[threads] Remove configuration dependency of Hybrid Suspend on Coop S…
Browse files Browse the repository at this point in the history
…uspend (#8261)

* [threads] Have Hybrid Suspend not depend on Coop Suspend

* [threads] Enable CI
  • Loading branch information
luhenry committed Apr 16, 2018
1 parent 8fec8ee commit 282ee4b
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 47 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -241,12 +241,12 @@ Disables the inclusion of a Boehm garbage collector.

* This defaults to `included`.

* `--with-cooperative-gc`
* `--enable-cooperative-suspend`

* If you pass this flag the Mono runtime is configured to only use
the cooperative mode of the garbage collector. If you do not pass
this flag, then you can control at runtime the use of the
cooperative GC mode by setting the `MONO_ENABLE_COOP` flag.
cooperative GC mode by setting the `MONO_ENABLE_COOP_SUSPEND` flag.

* `--with-tls=__thread,pthread`

Expand Down
40 changes: 24 additions & 16 deletions configure.ac
Expand Up @@ -1063,7 +1063,7 @@ with_unreal_default=no
with_wasm_default=no

with_bitcode_default=no
with_cooperative_gc_default=no
enable_cooperative_suspend_default=no

INVARIANT_AOT_OPTIONS=nimt-trampolines=2000,ntrampolines=10000,nrgctx-fetch-trampolines=256,ngsharedvt-trampolines=4000

Expand All @@ -1090,7 +1090,7 @@ elif test x$with_runtime_preset = xbitcode; then
DISABLE_MCS_DOCS_default=yes
with_testing_aot_full_default=yes
with_bitcode_default=yes
with_cooperative_gc_default=yes
enable_cooperative_suspend_default=yes
TEST_PROFILE=testing_aot_full
enable_llvm_default=yes

Expand Down Expand Up @@ -4513,26 +4513,34 @@ AC_ARG_WITH(lazy_gc_thread_creation, [ --with-lazy-gc-thread-creation=yes|no
fi
], [with_lazy_gc_thread_creation=no])

AC_ARG_WITH(cooperative_gc, [ --with-cooperative-gc=yes|no Enable cooperative stop-the-world garbage collection (sgen only) (defaults to no)], [], [with_cooperative_gc=default])
AC_ARG_WITH(cooperative_gc, [ --with-cooperative-gc=yes|no Enable cooperative stop-the-world garbage collection (sgen only) (defaults to no)], [AC_MSG_WARN([--with-cooperative-gc is deprecated, use --enable-cooperative-suspend instead])], [with_cooperative_gc=default])
AC_ARG_ENABLE(cooperative_suspend, [ --enable-cooperative-suspend Enable cooperative stop-the-world garbage collection (sgen only) (defaults to no)], [], [enable_cooperative_suspend=default])

if test x$with_cooperative_gc = xdefault; then
with_cooperative_gc=$with_cooperative_gc_default
if test x$enable_cooperative_suspend = xdefault -a test x$with_cooperative_gc != xdefault; then
enable_cooperative_suspend=$with_cooperative_gc
fi

if test x$with_cooperative_gc != xno; then
AC_DEFINE(USE_COOP_GC,1,[Enable cooperative stop-the-world garbage collection.])
if test x$enable_cooperative_suspend = xdefault; then
enable_cooperative_suspend=$enable_cooperative_suspend_default
fi

AM_CONDITIONAL([ENABLE_COOP], [test x$with_cooperative_gc != xno])
if test x$enable_cooperative_suspend != xno; then
AC_DEFINE(ENABLE_COOP_SUSPEND,1,[Enable cooperative stop-the-world garbage collection.])
fi

AC_ARG_WITH(hybrid_suspend, [ --with-hybrid-suspend=yes|no Enable hybrid cooperative stop-the-world garbage collection (sgen only) - cooperative suspend for threads running managed and native code, and preemptive suspend for threads running native and P/Invoke code (defaults to no)], [
if test x$with_hybrid_suspend != xno ; then
AC_DEFINE(USE_HYBRID_SUSPEND,1,[Enable hybrid cooperative suspend for GC stop-the-world])
fi
if test x$with_cooperative_gc != xyes ; then
AC_MSG_ERROR([Hybrid suspend requires --with-cooperative-gc=yes])
fi
], [with_hybrid_suspend=no])
AM_CONDITIONAL([ENABLE_COOP_SUSPEND], [test x$enable_cooperative_suspend != xno])

AC_ARG_ENABLE(hybrid_suspend, [ --enable-hybrid-suspend Enable hybrid stop-the-world garbage collection (sgen only) - cooperative suspend for threads running managed and runtime code, and preemptive suspend for threads running native and P/Invoke code (defaults to no)], [], [enable_hybrid_suspend=no])

if test x$enable_hybrid_suspend != xno -a x$enable_cooperative_suspend != xno ; then
AC_MSG_ERROR([Hybrid suspend and Cooperative suspend cannot be both enabled.])
fi

if test x$enable_hybrid_suspend != xno ; then
AC_DEFINE(ENABLE_HYBRID_SUSPEND,1,[Enable hybrid suspend for GC stop-the-world])
fi

AM_CONDITIONAL([ENABLE_HYBRID_SUSPEND], [test x$enable_hybrid_suspend != xno])

AC_ARG_ENABLE(checked_build, [ --enable-checked-build=LIST To enable checked build (expensive asserts), configure with a comma-separated LIST of checked build modules and then include that same list in the environment variable MONO_CHECK_MODE at runtime. Recognized checked build modules: all, gc, metadata, thread, private_types],[
Expand Down
4 changes: 2 additions & 2 deletions man/mono.1
Expand Up @@ -1170,7 +1170,7 @@ If set, tells mono to attempt using native asynchronous I/O services. If not
set, a default select/poll implementation is used. Currently epoll and kqueue
are supported.
.TP
\fBMONO_ENABLE_COOP\fR
\fBMONO_ENABLE_COOP_SUSPEND\fR
This makes the Mono runtime and the SGen garbage collector run in cooperative
mode as opposed to run on preemptive mode. Preemptive mode is the mode
that Mono has used historically, going back to the Boehm days, where the
Expand All @@ -1181,7 +1181,7 @@ safe point. This makes for an easier to debug garbage collector. As
of Mono 4.3.0 it is a work in progress, and while it works, it has not
been used extensively. This option enabled the feature and allows us to
find spots that need to be tuned for this mode of operation. Alternatively,
this mode can be enabled at compile time by using the --with-cooperative-gc
this mode can be enabled at compile time by using the --enable-cooperative-suspend
flag when calling configure.
.TP
\fBMONO_ENV_OPTIONS\fR
Expand Down
2 changes: 1 addition & 1 deletion mono/metadata/mono-hash.c
Expand Up @@ -227,7 +227,7 @@ rehash (MonoGHashTable *hash)
if (hash->gc_type & MONO_HASH_VALUE_GC)
mono_gc_register_root_wbarrier ((char*)data.values, sizeof (MonoObject*) * data.new_size, mono_gc_make_vector_descr (), hash->source, hash->key, hash->msg);

if (!mono_threads_are_safepoints_enabled () || mono_threads_is_hybrid_suspension_enabled ()) {
if (!mono_threads_are_safepoints_enabled ()) {
mono_gc_invoke_with_gc_lock (do_rehash, &data);
} else {
/* We cannot be preempted */
Expand Down
4 changes: 2 additions & 2 deletions mono/mini/mini-arm64.c
Expand Up @@ -4567,16 +4567,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
break;
}
case OP_GC_SAFE_POINT: {
#if defined (USE_COOP_GC)
guint8 *buf [1];

g_assert (mono_threads_are_safepoints_enabled ());

arm_ldrx (code, ARMREG_IP1, ins->sreg1, 0);
/* Call it if it is non-null */
buf [0] = code;
arm_cbzx (code, ARMREG_IP1, 0);
code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, "mono_threads_state_poll");
mono_arm_patch (buf [0], code, MONO_R_ARM64_CBZ);
#endif
break;
}
case OP_FILL_PROF_CALL_CTX:
Expand Down
4 changes: 3 additions & 1 deletion mono/profiler/Makefile.am
Expand Up @@ -33,9 +33,11 @@ suppression_DATA = mono-profiler-coverage.suppression
# sampling infrastructure depends on signals being available.
#
# See: https://bugzilla.xamarin.com/show_bug.cgi?id=57011
if !ENABLE_COOP
if !ENABLE_COOP_SUSPEND
if !ENABLE_HYBRID_SUSPEND
check_targets = testlog
endif
endif

endif
endif
Expand Down
14 changes: 7 additions & 7 deletions mono/utils/mono-threads-coop.c
Expand Up @@ -509,40 +509,40 @@ mono_threads_assert_gc_unsafe_region (void)
}

gboolean
mono_threads_are_safepoints_enabled (void)
mono_threads_is_cooperative_suspension_enabled (void)
{
#if defined(USE_COOP_GC)
#if defined(ENABLE_COOP_SUSPEND)
return TRUE;
#else
static int is_coop_enabled = -1;
if (G_UNLIKELY (is_coop_enabled == -1))
is_coop_enabled = g_hasenv ("MONO_ENABLE_COOP") ? 1 : 0;
is_coop_enabled = (g_hasenv ("MONO_ENABLE_COOP") || g_hasenv ("MONO_ENABLE_COOP_SUSPEND")) ? 1 : 0;
return is_coop_enabled == 1;
#endif
}

gboolean
mono_threads_is_blocking_transition_enabled (void)
{
#if defined(USE_COOP_GC)
#if defined(ENABLE_COOP_SUSPEND) || defined(ENABLE_HYBRID_SUSPEND)
return TRUE;
#else
static int is_blocking_transition_enabled = -1;
if (G_UNLIKELY (is_blocking_transition_enabled == -1))
is_blocking_transition_enabled = (g_hasenv ("MONO_ENABLE_COOP") || g_hasenv ("MONO_ENABLE_BLOCKING_TRANSITION")) ? 1 : 0;
is_blocking_transition_enabled = (g_hasenv ("MONO_ENABLE_COOP") || g_hasenv ("MONO_ENABLE_COOP_SUSPEND") || g_hasenv ("MONO_ENABLE_HYBRID_SUSPEND") || g_hasenv ("MONO_ENABLE_BLOCKING_TRANSITION")) ? 1 : 0;
return is_blocking_transition_enabled == 1;
#endif
}

gboolean
mono_threads_is_hybrid_suspension_enabled (void)
{
#if defined(USE_HYBRID_SUSPEND)
#if defined(ENABLE_HYBRID_SUSPEND)
return TRUE;
#else
static int is_hybrid_suspension_enabled = -1;
if (G_UNLIKELY (is_hybrid_suspension_enabled == -1))
is_hybrid_suspension_enabled = g_hasenv ("MONO_ENABLE_COOP") && g_hasenv ("MONO_ENABLE_HYBRID_SUSPEND");
is_hybrid_suspension_enabled = (g_hasenv ("MONO_ENABLE_HYBRID_SUSPEND")) ? 1 : 0;
return is_hybrid_suspension_enabled == 1;
#endif
}
Expand Down
18 changes: 11 additions & 7 deletions mono/utils/mono-threads-coop.h
Expand Up @@ -23,22 +23,26 @@ G_BEGIN_DECLS
/* JIT specific interface */
extern volatile size_t mono_polling_required;

/* Runtime consumable API */
/* Internal API */

gboolean
mono_threads_are_safepoints_enabled (void);
void
mono_threads_state_poll (void);

gboolean
mono_threads_is_blocking_transition_enabled (void);

/* Internal API */

void
mono_threads_state_poll (void);
gboolean
mono_threads_is_cooperative_suspension_enabled (void);

gboolean
mono_threads_is_hybrid_suspension_enabled (void);

static inline gboolean
mono_threads_are_safepoints_enabled (void)
{
return mono_threads_is_cooperative_suspension_enabled () || mono_threads_is_hybrid_suspension_enabled ();
}

static inline void
mono_threads_safepoint (void)
{
Expand Down
9 changes: 4 additions & 5 deletions mono/utils/mono-threads.c
Expand Up @@ -140,7 +140,7 @@ begin_preemptive_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
static BeginSuspendResult
begin_suspend_for_running_thread (MonoThreadInfo *info, gboolean interrupt_kernel)
{
if (mono_threads_are_safepoints_enabled ())
if (mono_threads_is_cooperative_suspension_enabled ())
return begin_cooperative_suspend (info);
else
return begin_preemptive_suspend (info, interrupt_kernel);
Expand Down Expand Up @@ -169,7 +169,7 @@ begin_suspend_for_blocking_thread (MonoThreadInfo *info, gboolean interrupt_kern
static gboolean
check_async_suspend (MonoThreadInfo *info, BeginSuspendResult result)
{
if (mono_threads_are_safepoints_enabled () && !mono_threads_is_hybrid_suspension_enabled ()) {
if (mono_threads_is_cooperative_suspension_enabled () && !mono_threads_is_hybrid_suspension_enabled ()) {
/* Async suspend can't async fail on coop */
g_assert (result == BeginSuspendOkCooperative);
return TRUE;
Expand All @@ -190,7 +190,7 @@ check_async_suspend (MonoThreadInfo *info, BeginSuspendResult result)
static void
resume_async_suspended (MonoThreadInfo *info)
{
if (mono_threads_are_safepoints_enabled () && !mono_threads_is_hybrid_suspension_enabled ())
if (mono_threads_is_cooperative_suspension_enabled () && !mono_threads_is_hybrid_suspension_enabled ())
g_assert_not_reached ();

g_assert (mono_threads_suspend_begin_async_resume (info));
Expand Down Expand Up @@ -1125,7 +1125,6 @@ mono_thread_info_safe_suspend_and_run (MonoNativeThreadId id, gboolean interrupt
case KeepSuspended:
THREADS_SUSPEND_DEBUG ("CALLBACK tid %p (%s): KeepSuspended\n", (void*)id, interrupt_kernel ? "int" : "");
g_assert (!mono_threads_are_safepoints_enabled ());
/* FIXME: what if mono_threads_is_hybrid_suspension_enabled () ? */
break;
default:
g_error ("Invalid suspend_and_run callback return value %d", result);
Expand Down Expand Up @@ -1224,7 +1223,7 @@ mono_thread_info_get_suspend_state (MonoThreadInfo *info)
// This state is only valid for full cooperative suspend. If
// we're preemptively suspending blocking threads, this is not
// a valid suspend state.
if (mono_threads_are_safepoints_enabled () && !mono_threads_is_hybrid_suspension_enabled ())
if (mono_threads_is_cooperative_suspension_enabled () && !mono_threads_is_hybrid_suspension_enabled ())
return &info->thread_saved_state [SELF_SUSPEND_STATE_INDEX];
break;
default:
Expand Down
4 changes: 3 additions & 1 deletion scripts/ci/run-jenkins.sh
Expand Up @@ -40,7 +40,9 @@ if [[ ${CI_TAGS} == *'osx-amd64'* ]]; then CFLAGS="$CFLAGS -m64 -arch x86_64"; L
if [[ ${CI_TAGS} == *'win-i386'* ]]; then PLATFORM=Win32; EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --host=i686-w64-mingw32"; export MONO_EXECUTABLE="${MONO_REPO_ROOT}/msvc/build/sgen/Win32/bin/Release/mono-sgen.exe"; fi
if [[ ${CI_TAGS} == *'win-amd64'* ]]; then PLATFORM=x64; EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --host=x86_64-w64-mingw32 --disable-boehm"; export MONO_EXECUTABLE="${MONO_REPO_ROOT}/msvc/build/sgen/x64/bin/Release/mono-sgen.exe"; fi

if [[ ${CI_TAGS} == *'coop-gc'* ]]; then EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --with-cooperative-gc=yes"; fi
if [[ ${CI_TAGS} == *'coop-suspend'* ]]; then EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --enable-cooperative-suspend";
elif [[ ${CI_TAGS} == *'hybrid-suspend'* ]]; then EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --enable-hybrid-suspend";
fi

if [[ ${CI_TAGS} == *'checked-coop'* ]]; then EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --enable-checked-build=gc,thread"; fi
if [[ ${CI_TAGS} == *'checked-all'* ]]; then EXTRA_CONF_FLAGS="${EXTRA_CONF_FLAGS} --enable-checked-build=all"; fi
Expand Down
6 changes: 3 additions & 3 deletions sdks/builds/ios.mk
Expand Up @@ -132,7 +132,7 @@ watchos_sysroot = -isysroot $(XCODE_DIR)/Platforms/WatchOS.platform/Developer/SD

# explicitly disable dtrace, since it requires inline assembly, which is disabled on AppleTV (and mono's configure.ac doesn't know that (yet at least))
ios-targettv_CONFIGURE_FLAGS = --enable-dtrace=no $(BITCODE_CONFIGURE_FLAGS)
ios-targetwatch_CONFIGURE_FLAGS = --with-cooperative-gc=yes $(BITCODE_CONFIGURE_FLAGS)
ios-targetwatch_CONFIGURE_FLAGS = --enable-cooperative-suspend $(BITCODE_CONFIGURE_FLAGS)

ios-target32_SYSROOT = $(ios_sysroot)
ios-target32s_SYSROOT = $(ios_sysroot)
Expand Down Expand Up @@ -265,7 +265,7 @@ ios-sim64_SYSROOT = $(ios_sim_sysroot)
ios-simtv_SYSROOT = $(tvos_sim_sysroot)
ios-simwatch_SYSROOT = $(watchos_sim_sysroot)

ios-simwatch_CONFIGURE_FLAGS = --with-cooperative-gc=yes
ios-simwatch_CONFIGURE_FLAGS = --enable-cooperative-suspend

ios-sim32_CPPFLAGS = -DHOST_IOS
ios-sim64_CPPFLAGS = -DHOST_IOS
Expand Down Expand Up @@ -399,7 +399,7 @@ $$(eval $$(call RuntimeTemplate,ios-$(1)))
endef

ios-cross32_CONFIGURE_FLAGS=--build=i386-apple-darwin10
ios-crosswatch_CONFIGURE_FLAGS=--build=i386-apple-darwin10 --with-cooperative-gc=yes
ios-crosswatch_CONFIGURE_FLAGS=--build=i386-apple-darwin10 --enable-cooperative-suspend
$(eval $(call iOSCrossTemplate,cross32,arm,llvm32,arm-darwin,arm-apple-darwin10))
$(eval $(call iOSCrossTemplate,cross64,aarch64,llvm64,aarch64-darwin,aarch64-apple-darwin10))
$(eval $(call iOSCrossTemplate,crosswatch,armv7k,llvm32,armv7k-unknown-darwin,armv7k-apple-darwin))

0 comments on commit 282ee4b

Please sign in to comment.