Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mono/metadata/threads-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,7 @@ mono_thread_internal_describe (MonoInternalThread *internal, GString *str);
gboolean
mono_thread_internal_is_current (MonoInternalThread *internal);

gboolean
mono_threads_is_current_thread_in_protected_block (void);

#endif /* _MONO_METADATA_THREADS_TYPES_H_ */
8 changes: 8 additions & 0 deletions mono/metadata/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,14 @@ mono_thread_get_abort_prot_block_count (MonoInternalThread *thread)
return (state & ABORT_PROT_BLOCK_MASK) >> ABORT_PROT_BLOCK_SHIFT;
}

gboolean
mono_threads_is_current_thread_in_protected_block (void)
{
MonoInternalThread *thread = mono_thread_internal_current ();

return mono_thread_get_abort_prot_block_count (thread) > 0;
}

void
mono_threads_begin_abort_protected_block (void)
{
Expand Down
32 changes: 27 additions & 5 deletions mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1900,8 +1900,15 @@ typedef struct {
MonoCoopMutex lock;
} JitCompilationData;

/*
Timeout, in millisecounds, that we wait other threads to finish JITing.
This value can't be too small or we won't see enough methods being reused and it can't be too big to cause massive stalls due to unforseable circunstances.
*/
#define MAX_JIT_TIMEOUT_MS 1000


static JitCompilationData compilation_data;
static int jit_methods_waited, jit_methods_multiple, jit_methods_overload, jit_spurious_wakeups;
static int jit_methods_waited, jit_methods_multiple, jit_methods_overload, jit_spurious_wakeups_or_timeouts;

static void
mini_jit_init_job_control (void)
Expand Down Expand Up @@ -1966,7 +1973,7 @@ wait_or_register_method_to_compile (MonoMethod *method, MonoDomain *domain)
mono_counters_register ("JIT compile waited others", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_waited);
mono_counters_register ("JIT compile 1+ jobs", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_multiple);
mono_counters_register ("JIT compile overload wait", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_overload);
mono_counters_register ("JIT compile spurious wakeups", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_spurious_wakeups);
mono_counters_register ("JIT compile spurious wakeups or timeouts", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_spurious_wakeups_or_timeouts);
inited = TRUE;
}

Expand All @@ -1983,9 +1990,14 @@ wait_or_register_method_to_compile (MonoMethod *method, MonoDomain *domain)

unlock_compilation_data ();
return FALSE;
} else if (jit_tls->active_jit_methods > 0) {
} else if (jit_tls->active_jit_methods > 0 || mono_threads_is_current_thread_in_protected_block ()) {
//We can't suspend the current thread if it's already JITing a method.
//Dependency management is too compilated and we want to get rid of this anyways.

//We can't suspend the current thread if it's running a protected block (such as a cctor)
//We can't rely only on JIT nesting as cctor's can be run from outside the JIT.

//Finally, he hit a timeout or spurious wakeup. We're better off just giving up and keep recompiling
++entry->compilation_count;
++jit_methods_multiple;
++jit_tls->active_jit_methods;
Expand All @@ -2005,15 +2017,25 @@ wait_or_register_method_to_compile (MonoMethod *method, MonoDomain *domain)
++entry->threads_waiting;

g_assert (entry->has_cond);
mono_coop_cond_wait (&entry->cond, &compilation_data.lock);
mono_coop_cond_timedwait (&entry->cond, &compilation_data.lock, MAX_JIT_TIMEOUT_MS);
--entry->threads_waiting;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this going to mask bugs ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will.
OTH, it ensures progress can be made even if slow enough. Do you think it's not worth it?


if (entry->done) {
unref_jit_entry (entry);
unlock_compilation_data ();
return TRUE;
} else {
++jit_spurious_wakeups;
//We hit the timeout or a spurious wakeup, fallback to JITing
g_assert (entry->ref_count > 1);
unref_jit_entry (entry);
++jit_spurious_wakeups_or_timeouts;

++entry->compilation_count;
++jit_methods_multiple;
++jit_tls->active_jit_methods;

unlock_compilation_data ();
return FALSE;
}
}
}
Expand Down