X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmonitor.c;h=9933f1dd48730ba5f4d5ae377a67752543063a85;hb=157cb97206f627685c15410953d2767146f6e426;hp=f86ff5c0cd637264609614e96fdfdcd09a256dfd;hpb=28e91840ef6c829350b74c0fc4430e4a456a5123;p=mono.git diff --git a/mono/metadata/monitor.c b/mono/metadata/monitor.c index f86ff5c0cd6..9933f1dd487 100644 --- a/mono/metadata/monitor.c +++ b/mono/metadata/monitor.c @@ -26,6 +26,7 @@ #include #include #include +#include /* * Pull the list of opcodes @@ -242,7 +243,9 @@ mon_finalize (MonoThreadsSync *mon) mon->data = monitor_freelist; monitor_freelist = mon; +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->gc_sync_blocks--; +#endif } /* LOCKING: this is called with monitor_mutex held */ @@ -268,7 +271,7 @@ mon_new (gsize id) new->wait_list = g_slist_remove (new->wait_list, new->wait_list->data); } } - mono_gc_weak_link_remove (&new->data); + mono_gc_weak_link_remove (&new->data, FALSE); new->data = monitor_freelist; monitor_freelist = new; } @@ -309,8 +312,11 @@ mon_new (gsize id) new->owner = id; new->nest = 1; + new->data = NULL; +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->gc_sync_blocks++; +#endif return new; } @@ -536,7 +542,9 @@ retry: } /* The object must be locked by someone else... */ +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->thread_contentions++; +#endif /* If ms is 0 we don't block, but just fail straight away */ if (ms == 0) { @@ -612,8 +620,10 @@ retry_contended: InterlockedIncrement (&mon->entry_count); +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->thread_queue_len++; mono_perfcounters->thread_queue_max++; +#endif thread = mono_thread_internal_current (); mono_thread_set_state (thread, ThreadState_WaitSleepJoin); @@ -627,7 +637,9 @@ retry_contended: mono_thread_clr_state (thread, ThreadState_WaitSleepJoin); InterlockedDecrement (&mon->entry_count); +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->thread_queue_len--; +#endif if (ms != INFINITE) { now = mono_msec_ticks (); @@ -773,8 +785,10 @@ mono_monitor_get_object_monitor_weak_link (MonoObject *object) return NULL; } +#ifndef DISABLE_JIT + static void -emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch, int *syncp_true_false_branch, +emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch, int *true_locktaken_branch, int *syncp_true_false_branch, int *thin_hash_branch, gboolean branch_on_true) { /* @@ -785,6 +799,17 @@ emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch mono_mb_emit_byte (mb, CEE_LDARG_0); *obj_null_branch = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); + /* + ldarg.1 + ldind.i1 + brtrue.s true_locktaken + */ + if (true_locktaken_branch) { + mono_mb_emit_byte (mb, CEE_LDARG_1); + mono_mb_emit_byte (mb, CEE_LDIND_I1); + *true_locktaken_branch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); + } + /* ldarg 0 obj conv.i objp @@ -826,23 +851,58 @@ emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch *syncp_true_false_branch = mono_mb_emit_short_branch (mb, branch_on_true ? CEE_BRTRUE_S : CEE_BRFALSE_S); } +#endif + +static MonoMethod* monitor_il_fastpaths[3]; + +gboolean +mono_monitor_is_il_fastpath_wrapper (MonoMethod *method) +{ + int i; + for (i = 0; i < 3; ++i) { + if (monitor_il_fastpaths [i] == method) + return TRUE; + } + return FALSE; +} + +enum { + FASTPATH_ENTER, + FASTPATH_ENTERV4, + FASTPATH_EXIT +}; + + static MonoMethod* -mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method) +register_fastpath (MonoMethod *method, int idx) { - static MonoMethod *fast_monitor_enter; - static MonoMethod *compare_exchange_method; + mono_memory_barrier (); + monitor_il_fastpaths [idx] = method; + return method; +} +static MonoMethod* +mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method) +{ MonoMethodBuilder *mb; - int obj_null_branch, syncp_null_branch, has_owner_branch, other_owner_branch, tid_branch, thin_hash_branch; + MonoMethod *res; + static MonoMethod *compare_exchange_method; + int obj_null_branch, true_locktaken_branch = 0, syncp_null_branch, has_owner_branch, other_owner_branch, tid_branch, thin_hash_branch; int tid_loc, syncp_loc, owner_loc; int thread_tls_offset; + gboolean is_v4 = mono_method_signature (monitor_enter_method)->param_count == 2; + int fast_path_idx = is_v4 ? FASTPATH_ENTERV4 : FASTPATH_ENTER; + WrapperInfo *info; + + /* The !is_v4 version is not used/tested */ + g_assert (is_v4); thread_tls_offset = mono_thread_get_tls_offset (); if (thread_tls_offset == -1) return NULL; - if (fast_monitor_enter) - return fast_monitor_enter; + if (monitor_il_fastpaths [fast_path_idx]) + return monitor_il_fastpaths [fast_path_idx]; if (!compare_exchange_method) { MonoMethodDesc *desc; @@ -857,17 +917,18 @@ mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method) return NULL; } - mb = mono_mb_new (mono_defaults.monitor_class, "FastMonitorEnter", MONO_WRAPPER_UNKNOWN); + mb = mono_mb_new (mono_defaults.monitor_class, is_v4 ? "FastMonitorEnterV4" : "FastMonitorEnter", MONO_WRAPPER_UNKNOWN); mb->method->slot = -1; mb->method->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_STATIC | METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL; +#ifndef DISABLE_JIT tid_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); syncp_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); owner_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); - emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, &syncp_null_branch, &thin_hash_branch, FALSE); + emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, is_v4 ? &true_locktaken_branch : NULL, &syncp_null_branch, &thin_hash_branch, FALSE); /* mono. tls thread_tls_offset threadp @@ -917,6 +978,12 @@ mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method) mono_mb_emit_byte (mb, CEE_LDC_I4_0); mono_mb_emit_managed_call (mb, compare_exchange_method, NULL); has_owner_branch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); + + if (is_v4) { + mono_mb_emit_byte (mb, CEE_LDARG_1); + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_byte (mb, CEE_STIND_I1); + } mono_mb_emit_byte (mb, CEE_RET); /* @@ -947,6 +1014,13 @@ mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method) mono_mb_emit_byte (mb, CEE_LDC_I4_1); mono_mb_emit_byte (mb, CEE_ADD); mono_mb_emit_byte (mb, CEE_STIND_I4); + + if (is_v4) { + mono_mb_emit_byte (mb, CEE_LDARG_1); + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_byte (mb, CEE_STIND_I1); + } + mono_mb_emit_byte (mb, CEE_RET); /* @@ -962,32 +1036,41 @@ mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method) mono_mb_patch_short_branch (mb, syncp_null_branch); mono_mb_patch_short_branch (mb, has_owner_branch); mono_mb_patch_short_branch (mb, other_owner_branch); + if (true_locktaken_branch) + mono_mb_patch_short_branch (mb, true_locktaken_branch); mono_mb_emit_byte (mb, CEE_LDARG_0); + if (is_v4) + mono_mb_emit_byte (mb, CEE_LDARG_1); mono_mb_emit_managed_call (mb, monitor_enter_method, NULL); mono_mb_emit_byte (mb, CEE_RET); +#endif - fast_monitor_enter = mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_enter_method), 5); - mono_mb_free (mb); + res = register_fastpath (mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_enter_method), 5), fast_path_idx); - return fast_monitor_enter; + info = mono_image_alloc0 (mono_defaults.corlib, sizeof (WrapperInfo)); + info->subtype = is_v4 ? WRAPPER_SUBTYPE_FAST_MONITOR_ENTER_V4 : WRAPPER_SUBTYPE_FAST_MONITOR_ENTER; + mono_marshal_set_wrapper_info (res, info); + + mono_mb_free (mb); + return res; } static MonoMethod* mono_monitor_get_fast_exit_method (MonoMethod *monitor_exit_method) { - static MonoMethod *fast_monitor_exit; - MonoMethodBuilder *mb; + MonoMethod *res; int obj_null_branch, has_waiting_branch, has_syncp_branch, owned_branch, nested_branch, thin_hash_branch; int thread_tls_offset; int syncp_loc; + WrapperInfo *info; thread_tls_offset = mono_thread_get_tls_offset (); if (thread_tls_offset == -1) return NULL; - if (fast_monitor_exit) - return fast_monitor_exit; + if (monitor_il_fastpaths [FASTPATH_EXIT]) + return monitor_il_fastpaths [FASTPATH_EXIT]; mb = mono_mb_new (mono_defaults.monitor_class, "FastMonitorExit", MONO_WRAPPER_UNKNOWN); @@ -995,9 +1078,10 @@ mono_monitor_get_fast_exit_method (MonoMethod *monitor_exit_method) mb->method->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_STATIC | METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL; +#ifndef DISABLE_JIT syncp_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); - emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, &has_syncp_branch, &thin_hash_branch, TRUE); + emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, NULL, &has_syncp_branch, &thin_hash_branch, TRUE); /* ret @@ -1121,11 +1205,16 @@ mono_monitor_get_fast_exit_method (MonoMethod *monitor_exit_method) mono_mb_emit_byte (mb, CEE_LDARG_0); mono_mb_emit_managed_call (mb, monitor_exit_method, NULL); mono_mb_emit_byte (mb, CEE_RET); +#endif - fast_monitor_exit = mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_exit_method), 5); + res = register_fastpath (mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_exit_method), 5), FASTPATH_EXIT); mono_mb_free (mb); - return fast_monitor_exit; + info = mono_image_alloc0 (mono_defaults.corlib, sizeof (WrapperInfo)); + info->subtype = WRAPPER_SUBTYPE_FAST_MONITOR_EXIT; + mono_marshal_set_wrapper_info (res, info); + + return res; } MonoMethod*