summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-08-22 16:19:18 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-08-22 16:19:18 +0000
commit832fd6825ce0878688cb60946fccd8a5289224b2 (patch)
tree25ec9e0d72189f7b6d62c4c4ba41f93b26d224b6
parent00b8444c930c3b9ce8c422c97496dd15bbf050e5 (diff)
* thread.c (rb_thread_schedule): don't recur infinitely.
(rb_threadptr_execute_interrupts): ditto. [ruby-dev:38060] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24628 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--thread.c30
2 files changed, 29 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 2643f816a0..9e23dc6074 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sun Aug 23 00:56:13 2009 Tanaka Akira <akr@fsij.org>
+
+ * thread.c (rb_thread_schedule): don't recur infinitely.
+ (rb_threadptr_execute_interrupts): ditto.
+ [ruby-dev:38060]
+
Sat Aug 22 15:07:23 2009 Tanaka Akira <akr@fsij.org>
* ext/syck/rubyext.c (id_hash_new): new function to create a hash
diff --git a/thread.c b/thread.c
index fe00a3f907..05d129de2a 100644
--- a/thread.c
+++ b/thread.c
@@ -931,8 +931,10 @@ rb_thread_sleep(int sec)
rb_thread_wait_for(rb_time_timeval(INT2FIX(sec)));
}
-void
-rb_thread_schedule(void)
+static void rb_threadptr_execute_interrupts_rec(rb_thread_t *, int);
+
+static void
+rb_thread_schedule_rec(int sched_depth)
{
thread_debug("rb_thread_schedule\n");
if (!rb_thread_alone()) {
@@ -950,10 +952,18 @@ rb_thread_schedule(void)
rb_thread_set_current(th);
thread_debug("rb_thread_schedule/switch done\n");
- RUBY_VM_CHECK_INTS();
+ if (!sched_depth && UNLIKELY(GET_THREAD()->interrupt_flag)) {
+ rb_threadptr_execute_interrupts_rec(GET_THREAD(), sched_depth+1);
+ }
}
}
+void
+rb_thread_schedule(void)
+{
+ rb_thread_schedule_rec(0);
+}
+
/* blocking region */
static inline void
blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
@@ -1183,8 +1193,8 @@ thread_s_pass(VALUE klass)
*
*/
-void
-rb_threadptr_execute_interrupts(rb_thread_t *th)
+static void
+rb_threadptr_execute_interrupts_rec(rb_thread_t *th, int sched_depth)
{
if (GET_VM()->main_thread == th) {
while (rb_signal_buff_size() && !th->exec_signal) native_thread_yield();
@@ -1227,7 +1237,8 @@ rb_threadptr_execute_interrupts(rb_thread_t *th)
rb_gc_finalize_deferred();
}
- if (timer_interrupt) {
+ if (!sched_depth && timer_interrupt) {
+ sched_depth++;
EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0);
if (th->slice > 0) {
@@ -1235,7 +1246,7 @@ rb_threadptr_execute_interrupts(rb_thread_t *th)
}
else {
reschedule:
- rb_thread_schedule();
+ rb_thread_schedule_rec(sched_depth+1);
if (th->slice < 0) {
th->slice++;
goto reschedule;
@@ -1248,6 +1259,11 @@ rb_threadptr_execute_interrupts(rb_thread_t *th)
}
}
+void
+rb_threadptr_execute_interrupts(rb_thread_t *th)
+{
+ rb_threadptr_execute_interrupts_rec(th, 0);
+}
void
rb_gc_mark_threads(void)