}
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