}
gboolean
+mono_monitor_enter_fast (MonoObject *obj)
+{
+ return mono_monitor_try_enter_internal (obj, 0, FALSE) == 1;
+}
+
+gboolean
mono_monitor_try_enter (MonoObject *obj, guint32 ms)
{
return mono_monitor_try_enter_internal (obj, ms, FALSE) == 1;
void
mono_monitor_enter_v4 (MonoObject *obj, char *lock_taken)
{
-
if (*lock_taken == 1) {
mono_set_pending_exception (mono_get_exception_argument ("lockTaken", "lockTaken is already true"));
return;
ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (obj, INFINITE, lock_taken);
}
+/*
+ * mono_monitor_enter_v4_fast:
+ *
+ * Same as mono_monitor_enter_v4, but return immediately if the
+ * monitor cannot be acquired.
+ * Returns TRUE if the lock was acquired, FALSE otherwise.
+ */
+gboolean
+mono_monitor_enter_v4_fast (MonoObject *obj, char *lock_taken)
+{
+ if (*lock_taken == 1)
+ return FALSE;
+ gint32 res = mono_monitor_try_enter_internal (obj, 0, TRUE);
+ *lock_taken = res == 1;
+ return res == 1;
+}
+
gboolean
ves_icall_System_Threading_Monitor_Monitor_test_owner (MonoObject *obj)
{
void mono_monitor_init (void);
void mono_monitor_cleanup (void);
+gboolean mono_monitor_enter_fast (MonoObject *obj);
+gboolean mono_monitor_enter_v4_fast (MonoObject *obj, char *lock_taken);
+
guint32 mono_monitor_get_object_monitor_gchandle (MonoObject *object);
void mono_monitor_threads_sync_members_offset (int *status_offset, int *nest_offset);
#include <mono/metadata/security-core-clr.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/profiler.h>
+#include <mono/metadata/monitor.h>
#include <mono/metadata/debug-mono-symfile.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-memory-model.h>
} else
return NULL;
} else if (cmethod->klass == mono_defaults.object_class) {
-
if (strcmp (cmethod->name, "GetType") == 0 && fsig->param_count + fsig->hasthis == 1) {
int dreg = alloc_ireg_ref (cfg);
int vt_reg = alloc_preg (cfg);
} else
return NULL;
} else if (cmethod->klass == runtime_helpers_class) {
-
if (strcmp (cmethod->name, "get_OffsetToStringData") == 0 && fsig->param_count == 0) {
EMIT_NEW_ICONST (cfg, ins, MONO_STRUCT_OFFSET (MonoString, chars));
return ins;
} else
return NULL;
+ } else if (cmethod->klass == mono_defaults.monitor_class) {
+ gboolean is_enter = FALSE;
+ gboolean is_v4 = FALSE;
+
+ if (!strcmp (cmethod->name, "enter_with_atomic_var") && mono_method_signature (cmethod)->param_count == 2) {
+ is_enter = TRUE;
+ is_v4 = TRUE;
+ }
+ if (!strcmp (cmethod->name, "Enter") && mono_method_signature (cmethod)->param_count == 1)
+ is_enter = TRUE;
+
+ if (is_enter) {
+ /*
+ * To make async stack traces work, icalls which can block should have a wrapper.
+ * For Monitor.Enter, emit two calls: a fastpath which doesn't have a wrapper, and a slowpath, which does.
+ */
+ MonoBasicBlock *end_bb, *slowpath_bb;
+
+ NEW_BBLOCK (cfg, end_bb);
+ NEW_BBLOCK (cfg, slowpath_bb);
+
+ ins = mono_emit_jit_icall (cfg, is_v4 ? mono_monitor_enter_v4_fast : mono_monitor_enter_fast, args);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, ins->dreg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, slowpath_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+ MONO_START_BB (cfg, slowpath_bb);
+ ins = mono_emit_jit_icall (cfg, is_v4 ? mono_monitor_enter_v4 : mono_monitor_enter, args);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+ MONO_START_BB (cfg, end_bb);
+ return ins;
+ }
} else if (cmethod->klass == mono_defaults.thread_class) {
if (strcmp (cmethod->name, "SpinWait_nop") == 0 && fsig->param_count == 0) {
MONO_INST_NEW (cfg, ins, OP_RELAXED_NOP);
#include <mono/metadata/attach.h>
#include <mono/metadata/runtime.h>
#include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/monitor.h>
#include <mono/utils/mono-math.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-counters.h>
mono_register_jit_icall_full (func, name, sig, TRUE, FALSE, name);
}
+static void
+register_icall_with_wrapper (gpointer func, const char *name, const char *sigstr)
+{
+ MonoMethodSignature *sig;
+
+ if (sigstr)
+ sig = mono_create_icall_signature (sigstr);
+ else
+ sig = NULL;
+
+ mono_register_jit_icall_full (func, name, sig, FALSE, FALSE, NULL);
+}
+
static void
register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
{
register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
+ register_icall_with_wrapper (mono_monitor_enter, "mono_monitor_enter", "void obj");
+ register_icall_with_wrapper (mono_monitor_enter_v4, "mono_monitor_enter_v4", "void obj ptr");
+ register_icall_no_wrapper (mono_monitor_enter_fast, "mono_monitor_enter_fast", "int obj");
+ register_icall_no_wrapper (mono_monitor_enter_v4_fast, "mono_monitor_enter_v4_fast", "int obj ptr");
+
#ifdef TARGET_IOS
register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
#endif