1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

mjit.c: RubyVM::MJIT.pause / RubyVM::MJIT.resume

[Feature #14830]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63710 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
k0kubun 2018-06-21 14:04:05 +00:00
parent 48efa44719
commit 0af19735d7
2 changed files with 73 additions and 18 deletions

86
mjit.c
View file

@ -941,7 +941,9 @@ static int worker_stopped;
static void
worker(void)
{
make_pch();
if (pch_status == PCH_NOT_READY) {
make_pch();
}
if (pch_status == PCH_FAILED) {
mjit_init_p = FALSE;
CRITICAL_SECTION_START(3, "in worker to update worker_stopped");
@ -1376,6 +1378,26 @@ system_tmpdir(void)
extern const char ruby_description_with_jit[];
/* Start MJIT worker. Return TRUE if worker is sucessfully started. */
static int
start_worker(void)
{
stop_worker_p = FALSE;
worker_stopped = FALSE;
if (!rb_thread_create_mjit_thread(child_after_fork, worker)) {
mjit_init_p = FALSE;
rb_native_mutex_destroy(&mjit_engine_mutex);
rb_native_cond_destroy(&mjit_pch_wakeup);
rb_native_cond_destroy(&mjit_client_wakeup);
rb_native_cond_destroy(&mjit_worker_wakeup);
rb_native_cond_destroy(&mjit_gc_wakeup);
verbose(1, "Failure in MJIT thread initialization\n");
return FALSE;
}
return TRUE;
}
/* Initialize MJIT. Start a thread creating the precompiled header and
processing ISeqs. The function should be called first for using MJIT.
If everything is successfull, MJIT_INIT_P will be TRUE. */
@ -1438,19 +1460,53 @@ mjit_init(struct mjit_options *opts)
rb_define_global_const("RUBY_DESCRIPTION", rb_obj_freeze(rb_description));
/* Initialize worker thread */
stop_worker_p = FALSE;
worker_stopped = FALSE;
if (!rb_thread_create_mjit_thread(child_after_fork, worker)) {
mjit_init_p = FALSE;
rb_native_mutex_destroy(&mjit_engine_mutex);
rb_native_cond_destroy(&mjit_pch_wakeup);
rb_native_cond_destroy(&mjit_client_wakeup);
rb_native_cond_destroy(&mjit_worker_wakeup);
rb_native_cond_destroy(&mjit_gc_wakeup);
verbose(1, "Failure in MJIT thread initialization\n");
start_worker();
}
static void
stop_worker(void)
{
stop_worker_p = TRUE;
while (!worker_stopped) {
verbose(3, "Sending cancel signal to worker");
CRITICAL_SECTION_START(3, "in stop_worker");
rb_native_cond_broadcast(&mjit_worker_wakeup);
CRITICAL_SECTION_FINISH(3, "in stop_worker");
}
}
/* Stop JIT-compiling methods but compiled code is kept available. */
VALUE
mjit_pause(void)
{
if (!mjit_init_p) {
rb_raise(rb_eRuntimeError, "MJIT is not enabled");
}
if (worker_stopped) {
return Qfalse;
}
stop_worker();
return Qtrue;
}
/* Restart JIT-compiling methods after mjit_pause. */
VALUE
mjit_resume(void)
{
if (!mjit_init_p) {
rb_raise(rb_eRuntimeError, "MJIT is not enabled");
}
if (!worker_stopped) {
return Qfalse;
}
if (!start_worker()) {
rb_raise(rb_eRuntimeError, "Failed to resume MJIT worker");
}
return Qtrue;
}
/* Finish the threads processing units and creating PCH, finalize
and free MJIT data. It should be called last during MJIT
life. */
@ -1475,13 +1531,7 @@ mjit_finish(void)
CRITICAL_SECTION_FINISH(3, "in mjit_finish to wakeup from pch");
/* Stop worker */
stop_worker_p = TRUE;
while (!worker_stopped) {
verbose(3, "Sending cancel signal to workers");
CRITICAL_SECTION_START(3, "in mjit_finish");
rb_native_cond_broadcast(&mjit_worker_wakeup);
CRITICAL_SECTION_FINISH(3, "in mjit_finish");
}
stop_worker();
rb_native_mutex_destroy(&mjit_engine_mutex);
rb_native_cond_destroy(&mjit_pch_wakeup);

5
vm.c
View file

@ -2780,6 +2780,9 @@ mjit_enabled_p(void)
return mjit_init_p ? Qtrue : Qfalse;
}
extern VALUE mjit_pause(void);
extern VALUE mjit_resume(void);
extern VALUE *rb_gc_stack_start;
extern size_t rb_gc_stack_maxsize;
#ifdef __ia64
@ -2868,6 +2871,8 @@ Init_VM(void)
/* RubyVM::MJIT */
mjit = rb_define_module_under(rb_cRubyVM, "MJIT");
rb_define_singleton_method(mjit, "enabled?", mjit_enabled_p, 0);
rb_define_singleton_method(mjit, "pause", mjit_pause, 0);
rb_define_singleton_method(mjit, "resume", mjit_resume, 0);
/*
* Document-class: Thread