diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index a79411b5ee932..7734c0631cb73 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -7435,28 +7435,44 @@ interp_invalidate_transformed (void) } typedef struct { - InterpJitInfoFunc func; - gpointer user_data; -} InterpJitInfoFuncUserData; + MonoJitInfo **jit_info_array; + gint size; + gint next; +} InterpCopyJitInfoFuncUserData; static void -interp_call_jit_info_func (gpointer imethod, gpointer user_data) +interp_copy_jit_info_func (gpointer imethod, gpointer user_data) { - InterpJitInfoFuncUserData *data = (InterpJitInfoFuncUserData *)user_data; - data->func (((InterpMethod *)imethod)->jinfo, data->user_data); + InterpCopyJitInfoFuncUserData *data = (InterpCopyJitInfoFuncUserData*)user_data; + if (data->next < data->size) + data->jit_info_array [data->next++] = ((InterpMethod *)imethod)->jinfo; } static void interp_jit_info_foreach (InterpJitInfoFunc func, gpointer user_data) { - InterpJitInfoFuncUserData data = {func, user_data}; + InterpCopyJitInfoFuncUserData copy_jit_info_data; // FIXME: Enumerate all memory managers MonoJitMemoryManager *jit_mm = get_default_jit_mm (); - jit_mm_lock (jit_mm); - mono_internal_hash_table_apply (&jit_mm->interp_code_hash, interp_call_jit_info_func, &data); - jit_mm_unlock (jit_mm); + // Can't keep memory manager lock while iterating and calling callback since it might take other locks + // causing poential deadlock situations. Instead, create copy of interpreter imethod jinfo pointers into + // plain array and use pointers from array when when running callbacks. + copy_jit_info_data.size = mono_atomic_load_i32 (&(jit_mm->interp_code_hash.num_entries)); + copy_jit_info_data.next = 0; + copy_jit_info_data.jit_info_array = (MonoJitInfo**) g_new (MonoJitInfo*, copy_jit_info_data.size); + if (copy_jit_info_data.jit_info_array) { + jit_mm_lock (jit_mm); + mono_internal_hash_table_apply (&jit_mm->interp_code_hash, interp_copy_jit_info_func, ©_jit_info_data); + jit_mm_unlock (jit_mm); + } + + if (copy_jit_info_data.jit_info_array) { + for (size_t i = 0; i < copy_jit_info_data.next; ++i) + func (copy_jit_info_data.jit_info_array [i], user_data); + g_free (copy_jit_info_data.jit_info_array); + } } static void