Feature #3436 » bug_3436-spawn_the_timer_thread_lazily.patch
ChangeLog (working copy) | ||
---|---|---|
Mon Oct 4 18:14:47 2010 Mark Somerville <mark@scottishclimbs.com>
|
||
* process.c, signal.c, test/ruby/test_signal.rb,
|
||
test/thread/test_timer_thread.rb: use the timer thread only when
|
||
needed to schedule Ruby threads [bug #3436].
|
||
Mon Oct 4 12:43:47 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||
* parse.y (regexp): dregexp has literal string only at the head
|
thread.c (working copy) | ||
---|---|---|
static VALUE rb_threadptr_raise(rb_thread_t *, int, VALUE *);
|
||
void rb_thread_recycle_stack_release(VALUE *);
|
||
static int
|
||
vm_living_thread_num(rb_vm_t *vm)
|
||
{
|
||
return vm->living_threads->num_entries;
|
||
}
|
||
void
|
||
rb_thread_start_timer_thread(void)
|
||
{
|
||
system_working = 1;
|
||
if (vm_living_thread_num(GET_VM()) > 1) {
|
||
rb_thread_create_timer_thread();
|
||
}
|
||
}
|
||
void
|
||
ruby_thread_init_stack(rb_thread_t *th)
|
||
{
|
||
native_thread_init_stack(th);
|
||
... | ... | |
th->status = THREAD_KILLED;
|
||
rb_raise(rb_eThreadError, "can't create Thread (%d)", err);
|
||
}
|
||
rb_thread_start_timer_thread();
|
||
return thval;
|
||
}
|
||
... | ... | |
rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
|
||
rb_class2name(klass));
|
||
}
|
||
rb_thread_start_timer_thread();
|
||
return thread;
|
||
}
|
||
... | ... | |
return thread_create_core(rb_thread_alloc(rb_cThread), (VALUE)arg, fn);
|
||
}
|
||
/* +infty, for this purpose */
|
||
#define DELAY_INFTY 1E30
|
||
... | ... | |
thread_debug("thread_join: success (thid: %p)\n",
|
||
(void *)target_th->thread_id);
|
||
rb_disable_interrupt();
|
||
if (vm_living_thread_num(th->vm) == 1 && rb_signal_buff_size() == 0) {
|
||
rb_thread_stop_timer_thread();
|
||
}
|
||
rb_enable_interrupt();
|
||
if (target_th->errinfo != Qnil) {
|
||
VALUE err = target_th->errinfo;
|
||
... | ... | |
return ST_CONTINUE;
|
||
}
|
||
static int
|
||
vm_living_thread_num(rb_vm_t *vm)
|
||
{
|
||
return vm->living_threads->num_entries;
|
||
}
|
||
int
|
||
rb_thread_alone(void)
|
||
{
|
||
... | ... | |
native_reset_timer_thread();
|
||
}
|
||
void
|
||
rb_thread_start_timer_thread(void)
|
||
{
|
||
system_working = 1;
|
||
rb_thread_create_timer_thread();
|
||
}
|
||
static int
|
||
clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
|
||
{
|
||
... | ... | |
}
|
||
}
|
||
rb_thread_create_timer_thread();
|
||
rb_thread_start_timer_thread();
|
||
(void)native_mutex_trylock;
|
||
}
|
process.c (working copy) | ||
---|---|---|
#define before_exec() \
|
||
(rb_enable_interrupt(), (void)(forked_child ? 0 : (rb_thread_stop_timer_thread(), 1)))
|
||
#define after_exec() \
|
||
(rb_thread_reset_timer_thread(), rb_thread_start_timer_thread(), forked_child = 0, rb_disable_interrupt())
|
||
(rb_thread_reset_timer_thread(), rb_thread_start_timer_thread(), forked_child = 0)
|
||
#define before_fork() before_exec()
|
||
#define after_fork() (GET_THREAD()->thrown_errinfo = 0, after_exec())
|
||
test/ruby/test_signal.rb (working copy) | ||
---|---|---|
w.close
|
||
assert_equal(r.read, "foo")
|
||
end
|
||
def test_signals_before_and_after_timer_thread
|
||
count = 0
|
||
Signal.trap(:USR1) { count += 1 }
|
||
Process.kill :USR1, Process.pid
|
||
assert_equal 1, count
|
||
th = Thread.new { sleep 0.5 }
|
||
Process.kill :USR1, Process.pid
|
||
assert_equal 2, count
|
||
th.join
|
||
Process.kill :USR1, Process.pid
|
||
assert_equal 3, count
|
||
end
|
||
end
|
test/thread/test_timer_thread.rb (revision 0) | ||
---|---|---|
require 'test/unit'
|
||
require 'thread'
|
||
class TestTimerThread < Test::Unit::TestCase
|
||
def number_of_lwps
|
||
`ps -o nlwp #{Process.pid} | tail -n1`.strip.to_i
|
||
end
|
||
def test_timer_is_created_and_destroyed
|
||
# TODO: enable this test on other platforms
|
||
return if /linux/ !~ RUBY_PLATFORM
|
||
assert_equal 1, number_of_lwps
|
||
th = Thread.new { sleep 0.1 }
|
||
assert_equal 3, number_of_lwps
|
||
th.join
|
||
assert_equal 1, number_of_lwps
|
||
end
|
||
end
|
signal.c (working copy) | ||
---|---|---|
#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
|
||
ruby_signal(sig, sighandler);
|
||
#endif
|
||
rb_vm_t *vm = GET_VM();
|
||
if (vm->running_thread == vm->main_thread) {
|
||
rb_threadptr_check_signal(vm->main_thread);
|
||
}
|
||
}
|
||
int
|