Skip to content

Commit

Permalink
[mono] Reduce usage of the domain lock (#50313)
Browse files Browse the repository at this point in the history
* [mono] Add a separate lock for the method_to_dyn_method hashtable.

* Use the jit memory manager lock instead of the domain lock in the arm64 patch code.

* Remove usage of the domain lock from the interpreter code.

* Use a separate lock to protect the jit info table.

* Fix the build.
  • Loading branch information
vargaz authored Mar 27, 2021
1 parent 3fc609c commit 7795971
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 44 deletions.
37 changes: 23 additions & 14 deletions src/mono/mono/metadata/jit-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static MonoJitInfoTable * volatile jit_info_table;
static MonoJitInfoTable * volatile aot_modules;
static GSList *jit_info_free_queue;
static int num_jit_info_table_duplicates;
static mono_mutex_t jit_info_mutex;

#define JIT_INFO_TABLE_FILL_RATIO_NOM 3
#define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
Expand All @@ -64,6 +65,18 @@ static int num_jit_info_table_duplicates;
#define JIT_INFO_TABLE_HAZARD_INDEX 0
#define JIT_INFO_HAZARD_INDEX 1

static inline void
jit_info_lock (void)
{
mono_os_mutex_lock (&jit_info_mutex);
}

static inline void
jit_info_unlock (void)
{
mono_os_mutex_unlock (&jit_info_mutex);
}

static int
jit_info_table_num_elements (MonoJitInfoTable *table)
{
Expand All @@ -83,6 +96,7 @@ void
mono_jit_info_tables_init (void)
{
jit_info_table = mono_jit_info_table_new ();
mono_os_mutex_init_recursive (&jit_info_mutex);
}

MonoJitInfoTable *
Expand All @@ -104,9 +118,8 @@ jit_info_table_free (MonoJitInfoTable *table, gboolean duplicate)

int i;
int num_chunks = table->num_chunks;
MonoDomain *domain = mono_get_root_domain ();

mono_domain_lock (domain);
jit_info_lock ();

if (duplicate) {
num_jit_info_table_duplicates--;
Expand Down Expand Up @@ -141,7 +154,7 @@ jit_info_table_free (MonoJitInfoTable *table, gboolean duplicate)
g_free (chunk);
}

mono_domain_unlock (domain);
jit_info_unlock ();

g_free (table);
}
Expand Down Expand Up @@ -700,17 +713,15 @@ jit_info_table_add (MonoJitInfoTable *volatile *table_ptr, MonoJitInfo *ji)
void
mono_jit_info_table_add (MonoJitInfo *ji)
{
MonoDomain *domain = mono_get_root_domain ();

g_assert (ji->d.method != NULL);

mono_domain_lock (domain);
jit_info_lock ();

UnlockedIncrement (&mono_stats.jit_info_table_insert_count);

jit_info_table_add (&jit_info_table, ji);

mono_domain_unlock (domain);
jit_info_unlock ();
}

static MonoJitInfo*
Expand Down Expand Up @@ -792,10 +803,10 @@ jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji)
void
mono_jit_info_table_remove (MonoJitInfo *ji)
{
MonoDomain *domain = mono_get_root_domain ();
MonoJitInfoTable *table;

mono_domain_lock (domain);
jit_info_lock ();

table = jit_info_table;

UnlockedIncrement (&mono_stats.jit_info_table_remove_count);
Expand All @@ -804,7 +815,7 @@ mono_jit_info_table_remove (MonoJitInfo *ji)

mono_jit_info_free_or_queue (ji);

mono_domain_unlock (domain);
jit_info_unlock ();
}

/*
Expand All @@ -815,11 +826,9 @@ mono_jit_info_table_remove (MonoJitInfo *ji)
void
mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
{
MonoDomain *domain = mono_get_root_domain ();
MonoJitInfo *ji;

g_assert (domain);
mono_domain_lock (domain);
jit_info_lock ();

/*
* We reuse MonoJitInfoTable to store AOT module info,
Expand All @@ -834,7 +843,7 @@ mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
ji->code_size = (guint8*)end - (guint8*)start;
jit_info_table_add (&aot_modules, ji);

mono_domain_unlock (domain);
jit_info_unlock ();
}

void
Expand Down
32 changes: 21 additions & 11 deletions src/mono/mono/metadata/sre.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,20 @@
#include "icall-decl.h"

/* Maps MonoMethod* to weak links to DynamicMethod objects */
/* Protected by the domain lock */
static GHashTable *method_to_dyn_method;
static mono_mutex_t method_to_dyn_method_lock;

static inline void
dyn_methods_lock (void)
{
mono_os_mutex_lock (&method_to_dyn_method_lock);
}

static inline void
dyn_methods_unlock (void)
{
mono_os_mutex_unlock (&method_to_dyn_method_lock);
}

static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, "System.Runtime.InteropServices", "MarshalAsAttribute");
#ifndef DISABLE_REFLECTION_EMIT
Expand Down Expand Up @@ -100,6 +112,8 @@ void
mono_reflection_emit_init (void)
{
mono_dynamic_images_init ();

mono_os_mutex_init_recursive (&method_to_dyn_method_lock);
}

char*
Expand Down Expand Up @@ -3980,14 +3994,13 @@ static void
free_dynamic_method (void *dynamic_method)
{
DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
MonoDomain *domain = mono_get_root_domain ();
MonoMethod *method = data->handle;
MonoGCHandle dis_link;

mono_domain_lock (domain);
dyn_methods_lock ();
dis_link = g_hash_table_lookup (method_to_dyn_method, method);
g_hash_table_remove (method_to_dyn_method, method);
mono_domain_unlock (domain);
dyn_methods_unlock ();
g_assert (dis_link);
mono_gchandle_free_internal (dis_link);

Expand All @@ -4006,7 +4019,6 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
ReflectionMethodBuilder rmb;
MonoMethodSignature *sig;
MonoClass *klass;
MonoDomain *domain;
GSList *l;
int i;
gboolean ret = TRUE;
Expand Down Expand Up @@ -4119,12 +4131,11 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
}
g_slist_free (mb->referenced_by);

domain = mono_get_root_domain ();
mono_domain_lock (domain);
dyn_methods_lock ();
if (!method_to_dyn_method)
method_to_dyn_method = g_hash_table_new (NULL, NULL);
g_hash_table_insert (method_to_dyn_method, handle, mono_gchandle_new_weakref_internal ((MonoObject *)mb, TRUE));
mono_domain_unlock (domain);
dyn_methods_unlock ();

goto exit;
exit_false:
Expand Down Expand Up @@ -4590,10 +4601,9 @@ mono_method_to_dyn_method (MonoMethod *method)
if (!method_to_dyn_method)
return (MonoGCHandle)NULL;

MonoDomain *domain = mono_get_root_domain ();
mono_domain_lock (domain);
dyn_methods_lock ();
handle = (MonoGCHandle*)g_hash_table_lookup (method_to_dyn_method, method);
mono_domain_unlock (domain);
dyn_methods_unlock ();

return handle;
}
4 changes: 2 additions & 2 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,11 +693,11 @@ get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset)

if (!table) {
/* Lazily allocate method table */
mono_domain_lock (vtable->domain);
mono_mem_manager_lock (memory_manager);
table = get_method_table (vtable, offset);
if (!table)
table = alloc_method_table (vtable, offset);
mono_domain_unlock (vtable->domain);
mono_mem_manager_unlock (memory_manager);
}

if (!table [offset]) {
Expand Down
3 changes: 0 additions & 3 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -9048,7 +9048,6 @@ mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context, Mon
MonoMethodSignature *signature = mono_method_signature_internal (method);
MonoVTable *method_class_vt;
MonoGenericContext *generic_context = NULL;
MonoDomain *domain = mono_get_root_domain ();
InterpMethod tmp_imethod;
InterpMethod *real_imethod;

Expand Down Expand Up @@ -9167,12 +9166,10 @@ mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context, Mon
}
mono_os_mutex_unlock (&calc_section);

mono_domain_lock (domain);
if (mono_stats_method_desc && mono_method_desc_full_match (mono_stats_method_desc, imethod->method)) {
g_printf ("Printing runtime stats at method: %s\n", mono_method_get_full_name (imethod->method));
mono_runtime_print_stats ();
}
mono_domain_unlock (domain);

MonoJitMemoryManager *jit_mm = jit_mm_for_method (imethod->method);
jit_mm_lock (jit_mm);
Expand Down
28 changes: 14 additions & 14 deletions src/mono/mono/mini/mini-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,17 +858,15 @@ emit_thunk (guint8 *code, gconstpointer target)
}

static gpointer
create_thunk (MonoCompile *cfg, MonoDomain *domain, guchar *code, const guchar *target)
create_thunk (MonoCompile *cfg, guchar *code, const guchar *target)
{
MonoJitInfo *ji;
MonoThunkJitInfo *info;
guint8 *thunks, *p;
int thunks_size;
guint8 *orig_target;
guint8 *target_thunk;

if (!domain)
domain = mono_domain_get ();
MonoJitMemoryManager* jit_mm;

if (cfg) {
/*
Expand Down Expand Up @@ -905,7 +903,10 @@ create_thunk (MonoCompile *cfg, MonoDomain *domain, guchar *code, const guchar *

orig_target = mono_arch_get_call_target (code + 4);

mono_domain_lock (domain);
/* Arbitrary lock */
jit_mm = get_default_jit_mm ();

jit_mm_lock (jit_mm);

target_thunk = NULL;
if (orig_target >= thunks && orig_target < thunks + thunks_size) {
Expand All @@ -928,21 +929,21 @@ create_thunk (MonoCompile *cfg, MonoDomain *domain, guchar *code, const guchar *
//printf ("THUNK: %p %p %p\n", code, target, target_thunk);

if (!target_thunk) {
mono_domain_unlock (domain);
jit_mm_unlock (jit_mm);
g_print ("thunk failed %p->%p, thunk space=%d method %s", code, target, thunks_size, cfg ? mono_method_full_name (cfg->method, TRUE) : mono_method_full_name (jinfo_get_method (ji), TRUE));
g_assert_not_reached ();
}

emit_thunk (target_thunk, target);

mono_domain_unlock (domain);
jit_mm_unlock (jit_mm);

return target_thunk;
}
}

static void
arm_patch_full (MonoCompile *cfg, MonoDomain *domain, guint8 *code, guint8 *target, int relocation)
arm_patch_full (MonoCompile *cfg, guint8 *code, guint8 *target, int relocation)
{
switch (relocation) {
case MONO_R_ARM64_B:
Expand All @@ -952,7 +953,7 @@ arm_patch_full (MonoCompile *cfg, MonoDomain *domain, guint8 *code, guint8 *targ
} else {
gpointer thunk;

thunk = create_thunk (cfg, domain, code, target);
thunk = create_thunk (cfg, code, target);
g_assert (arm_is_bl_disp (code, thunk));
arm_b (code, thunk);
}
Expand Down Expand Up @@ -986,7 +987,7 @@ arm_patch_full (MonoCompile *cfg, MonoDomain *domain, guint8 *code, guint8 *targ
} else {
gpointer thunk;

thunk = create_thunk (cfg, domain, code, target);
thunk = create_thunk (cfg, code, target);
g_assert (arm_is_bl_disp (code, thunk));
arm_bl (code, thunk);
}
Expand All @@ -999,7 +1000,7 @@ arm_patch_full (MonoCompile *cfg, MonoDomain *domain, guint8 *code, guint8 *targ
static void
arm_patch_rel (guint8 *code, guint8 *target, int relocation)
{
arm_patch_full (NULL, NULL, code, target, relocation);
arm_patch_full (NULL, code, target, relocation);
}

void
Expand All @@ -1012,18 +1013,17 @@ void
mono_arch_patch_code_new (MonoCompile *cfg, guint8 *code, MonoJumpInfo *ji, gpointer target)
{
guint8 *ip;
MonoDomain *domain = mono_get_root_domain ();

ip = ji->ip.i + code;

switch (ji->type) {
case MONO_PATCH_INFO_METHOD_JUMP:
/* ji->relocation is not set by the caller */
arm_patch_full (cfg, domain, ip, (guint8*)target, MONO_R_ARM64_B);
arm_patch_full (cfg, ip, (guint8*)target, MONO_R_ARM64_B);
mono_arch_flush_icache (ip, 8);
break;
default:
arm_patch_full (cfg, domain, ip, (guint8*)target, ji->relocation);
arm_patch_full (cfg, ip, (guint8*)target, ji->relocation);
break;
case MONO_PATCH_INFO_NONE:
break;
Expand Down

0 comments on commit 7795971

Please sign in to comment.