revert_thread_scheduler_optimizations.diff [plain text]
Index: eval.c
===================================================================
--- eval.c (revision 27134)
+++ eval.c (working copy)
@@ -370,8 +370,7 @@
ent = cache; end = ent + CACHE_SIZE;
while (ent < end) {
if (ent->mid == id &&
- (ent->klass == klass ||
- RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl)) {
+ RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl) {
ent->mid = 0;
}
ent++;
@@ -1411,7 +1410,7 @@
rb_call_inits();
ruby_class = rb_cObject;
ruby_frame->self = ruby_top_self;
- ruby_top_cref = NEW_CREF(rb_cObject, 0);
+ ruby_top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
ruby_cref = ruby_top_cref;
rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self));
#ifdef __MACOS__
@@ -4663,7 +4662,6 @@
rb_exc_raise(mesg)
VALUE mesg;
{
- mesg = rb_make_exception(1, &mesg);
rb_longjmp(TAG_RAISE, mesg);
}
@@ -4671,7 +4669,6 @@
rb_exc_fatal(mesg)
VALUE mesg;
{
- mesg = rb_make_exception(1, &mesg);
rb_longjmp(TAG_FATAL, mesg);
}
@@ -5695,7 +5692,7 @@
exc = rb_eNameError;
}
else if (last_call_status & CSTAT_SUPER) {
- format = "super: no superclass method `%s' for %s";
+ format = "super: no superclass method `%s'";
}
if (!format) {
format = "undefined method `%s' for %s";
@@ -6141,14 +6138,13 @@
ent = cache + EXPR1(klass, mid);
if (ent->mid == mid && ent->klass == klass) {
if (!ent->method)
- goto nomethod;
+ return method_missing(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
klass = ent->origin;
id = ent->mid0;
noex = ent->noex;
body = ent->method;
}
else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
- nomethod:
if (scope == 3) {
return method_missing(recv, mid, argc, argv, CSTAT_SUPER);
}
@@ -8868,8 +8864,7 @@
_block = *data;
_block.block_obj = bvar;
if (self != Qundef) _block.frame.self = self;
- _block.frame.last_class = klass;
- if (!klass) _block.frame.last_func = 0;
+ if (klass) _block.frame.last_class = klass;
_block.frame.argc = RARRAY(tmp)->len;
_block.frame.flags = ruby_frame->flags;
if (_block.frame.argc && DMETHOD_P()) {
@@ -8877,7 +8872,7 @@
OBJSETUP(scope, tmp, T_SCOPE);
scope->local_tbl = _block.scope->local_tbl;
scope->local_vars = _block.scope->local_vars;
- scope->flags |= SCOPE_CLONE | (_block.scope->flags & SCOPE_MALLOC);
+ scope->flags |= SCOPE_CLONE;
_block.scope = scope;
}
/* modify current frame */
@@ -9271,8 +9266,8 @@
ID oid = id;
again:
- if ((body = rb_get_method_body(&klass, &oid, &noex)) == 0) {
- print_undef(rklass, id);
+ if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
+ print_undef(rklass, oid);
}
if (nd_type(body) == NODE_ZSUPER) {
@@ -9413,7 +9408,7 @@
struct METHOD *data;
Data_Get_Struct(obj, struct METHOD, data);
- return rb_str_new2(rb_id2name(data->id));
+ return rb_str_new2(rb_id2name(data->oid));
}
/*
@@ -9839,7 +9834,7 @@
}
}
rb_str_buf_cat2(str, sharp);
- rb_str_buf_cat2(str, rb_id2name(data->id));
+ rb_str_buf_cat2(str, rb_id2name(data->oid));
rb_str_buf_cat2(str, ">");
return str;
@@ -10219,7 +10214,6 @@
#define WAIT_TIME (1<<2)
#define WAIT_JOIN (1<<3)
#define WAIT_PID (1<<4)
-#define WAIT_DONE (1<<5)
/* +infty, for this purpose */
#define DELAY_INFTY 1E30
@@ -10662,8 +10656,9 @@
th->safe = ruby_safe_level;
th->node = ruby_current_node;
- if (ruby_sandbox_save != NULL) {
- ruby_sandbox_save(th);
+ if (ruby_sandbox_save != NULL)
+ {
+ ruby_sandbox_save(th);
}
}
@@ -10711,19 +10706,20 @@
(rb_thread_switch(ruby_setjmp(rb_thread_save_context(th), (th)->context)))
NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
-NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int)));
-NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int)));
+NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int,void*)));
+NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int, VALUE *)));
static void
-rb_thread_restore_context_0(rb_thread_t th, int exit)
+rb_thread_restore_context_0(rb_thread_t th, int exit, void *vp)
{
static rb_thread_t tmp;
static int ex;
static VALUE tval;
rb_trap_immediate = 0; /* inhibit interrupts from here */
- if (ruby_sandbox_restore != NULL) {
- ruby_sandbox_restore(th);
+ if (ruby_sandbox_restore != NULL)
+ {
+ ruby_sandbox_restore(th);
}
ruby_frame = th->frame;
ruby_scope = th->scope;
@@ -10771,9 +10767,9 @@
static volatile int C(k), C(l), C(m), C(n), C(o);
static volatile int C(p), C(q), C(r), C(s), C(t);
int rb_dummy_false = 0;
-NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, VALUE *)));
+NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, void *, VALUE *)));
static void
-register_stack_extend(rb_thread_t th, int exit, VALUE *curr_bsp)
+register_stack_extend(rb_thread_t th, int exit, void *vp, VALUE *curr_bsp)
{
if (rb_dummy_false) {
/* use registers as much as possible */
@@ -10787,63 +10783,52 @@
E(p) = E(q) = E(r) = E(s) = E(t) = 0;
}
if (curr_bsp < th->bstr_pos+th->bstr_len) {
- register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp());
+ register_stack_extend(th, exit, &exit, (VALUE*)rb_ia64_bsp());
}
- stack_extend(th, exit);
+ rb_thread_restore_context_0(th, exit, &exit);
}
#undef C
#undef E
#endif
+# if defined(_MSC_VER) && _MSC_VER >= 1300
+__declspec(noinline) static void stack_extend(rb_thread_t, int, VALUE*);
+# endif
static void
-stack_extend(rb_thread_t th, int exit)
+stack_extend(rb_thread_t th, int exit, VALUE *addr_in_prev_frame)
{
#define STACK_PAD_SIZE 1024
- volatile VALUE space[STACK_PAD_SIZE], *sp = space;
+ VALUE space[STACK_PAD_SIZE];
-#if !STACK_GROW_DIRECTION
- if (space < rb_gc_stack_start) {
+#if STACK_GROW_DIRECTION < 0
+ if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]);
+#elif STACK_GROW_DIRECTION > 0
+ if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]);
+#else
+ if (addr_in_prev_frame < rb_gc_stack_start) {
/* Stack grows downward */
-#endif
-#if STACK_GROW_DIRECTION <= 0
- if (space > th->stk_pos) {
-# ifdef HAVE_ALLOCA
- sp = ALLOCA_N(VALUE, &space[0] - th->stk_pos);
-# else
- stack_extend(th, exit);
-# endif
- }
-#endif
-#if !STACK_GROW_DIRECTION
+ if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]);
}
else {
/* Stack grows upward */
-#endif
-#if STACK_GROW_DIRECTION >= 0
- if (&space[STACK_PAD_SIZE] < th->stk_pos + th->stk_len) {
-# ifdef HAVE_ALLOCA
- sp = ALLOCA_N(VALUE, th->stk_pos + th->stk_len - &space[STACK_PAD_SIZE]);
-# else
- stack_extend(th, exit);
-# endif
- }
-#endif
-#if !STACK_GROW_DIRECTION
+ if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]);
}
#endif
- rb_thread_restore_context_0(th, exit);
-}
#ifdef __ia64
-#define stack_extend(th, exit) register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp())
+ register_stack_extend(th, exit, space, (VALUE*)rb_ia64_bsp());
+#else
+ rb_thread_restore_context_0(th, exit, space);
#endif
+}
static void
rb_thread_restore_context(th, exit)
rb_thread_t th;
int exit;
{
+ VALUE v;
if (!th->stk_ptr) rb_bug("unsaved context");
- stack_extend(th, exit);
+ stack_extend(th, exit, &v);
}
static void
@@ -10875,13 +10860,6 @@
rb_thread_die(th);
th->prev->next = th->next;
th->next->prev = th->prev;
-
-#if defined(_THREAD_SAFE) || defined(HAVE_SETITIMER)
- /* if this is the last ruby thread, stop timer signals */
- if (th->next == th->prev && th->next == main_thread) {
- rb_thread_stop_timer();
- }
-#endif
}
static int
@@ -11012,6 +10990,7 @@
rb_thread_t next; /* OK */
rb_thread_t th;
rb_thread_t curr;
+ rb_thread_t th_found = 0;
int found = 0;
fd_set readfds;
@@ -11050,7 +11029,6 @@
now = -1.0;
FOREACH_THREAD_FROM(curr, th) {
- th->wait_for &= ~WAIT_DONE;
if (!found && th->status <= THREAD_RUNNABLE) {
found = 1;
}
@@ -11083,12 +11061,7 @@
if (now < 0.0) now = timeofday();
th_delay = th->delay - now;
if (th_delay <= 0.0) {
- if (th->wait_for & WAIT_SELECT) {
- need_select = 1;
- }
- else {
- th->status = THREAD_RUNNABLE;
- }
+ th->status = THREAD_RUNNABLE;
found = 1;
}
else if (th_delay < delay) {
@@ -11207,22 +11180,22 @@
if (n > 0) {
now = -1.0;
/* Some descriptors are ready.
- * The corresponding threads are runnable as next.
- * Mark them with WAIT_DONE.
- * Don't change the status to runnable here because
- * threads which don't run next should not be changed.
+ * Choose a thread which may run next.
+ * Don't change the status of threads which don't run next.
*/
FOREACH_THREAD_FROM(curr, th) {
if ((th->wait_for&WAIT_FD) && FD_ISSET(th->fd, &readfds)) {
- th->wait_for |= WAIT_DONE;
+ th_found = th;
found = 1;
+ break;
}
if ((th->wait_for&WAIT_SELECT) &&
(match_fds(&readfds, &th->readfds, max) ||
match_fds(&writefds, &th->writefds, max) ||
match_fds(&exceptfds, &th->exceptfds, max))) {
- th->wait_for |= WAIT_DONE;
+ th_found = th;
found = 1;
+ break;
}
}
END_FOREACH_FROM(curr, th);
@@ -11238,28 +11211,27 @@
next = th;
break;
}
- if ((th->status == THREAD_RUNNABLE || (th->wait_for & WAIT_DONE)) && th->stk_ptr) {
+ if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) {
if (!next || next->priority < th->priority) {
+ if (th == th_found) {
+ th_found->status = THREAD_RUNNABLE;
+ th_found->wait_for = 0;
+ if (th->wait_for&WAIT_FD) {
+ th_found->fd = 0;
+ }
+ else { /* th->wait_for&WAIT_SELECT */
+ n = intersect_fds(&readfds, &th_found->readfds, max) +
+ intersect_fds(&writefds, &th_found->writefds, max) +
+ intersect_fds(&exceptfds, &th_found->exceptfds, max);
+ th_found->select_value = n;
+ }
+ }
next = th;
}
}
}
END_FOREACH_FROM(curr, th);
- if (next && (next->wait_for & WAIT_DONE)) {
- next->status = THREAD_RUNNABLE;
- if (next->wait_for&WAIT_FD) {
- next->fd = 0;
- }
- else { /* next->wait_for&WAIT_SELECT */
- n = intersect_fds(&readfds, &next->readfds, max) +
- intersect_fds(&writefds, &next->writefds, max) +
- intersect_fds(&exceptfds, &next->exceptfds, max);
- next->select_value = n;
- }
- next->wait_for = 0;
- }
-
if (!next) {
/* raise fatal error to main thread */
curr_thread->node = ruby_current_node;
@@ -11269,16 +11241,15 @@
TRAP_END;
}
FOREACH_THREAD_FROM(curr, th) {
- int wait_for = th->wait_for & ~WAIT_DONE;
warn_printf("deadlock 0x%lx: %s:",
th->thread, thread_status_name(th->status));
- if (wait_for & WAIT_FD) warn_printf("F(%d)", th->fd);
- if (wait_for & WAIT_SELECT) warn_printf("S");
- if (wait_for & WAIT_TIME) warn_printf("T(%f)", th->delay);
- if (wait_for & WAIT_JOIN)
+ if (th->wait_for & WAIT_FD) warn_printf("F(%d)", th->fd);
+ if (th->wait_for & WAIT_SELECT) warn_printf("S");
+ if (th->wait_for & WAIT_TIME) warn_printf("T(%f)", th->delay);
+ if (th->wait_for & WAIT_JOIN)
warn_printf("J(0x%lx)", th->join ? th->join->thread : 0);
- if (wait_for & WAIT_PID) warn_printf("P");
- if (!wait_for) warn_printf("-");
+ if (th->wait_for & WAIT_PID) warn_printf("P");
+ if (!th->wait_for) warn_printf("-");
warn_printf(" %s - %s:%d\n",
th==main_thread ? "(main)" : "",
th->node->nd_file, nd_line(th->node));
@@ -12222,9 +12193,9 @@
th->locals = 0;\
th->thread = 0;\
if (curr_thread == 0) {\
- th->sandbox = Qnil;\
+ th->sandbox = Qnil;\
} else {\
- th->sandbox = curr_thread->sandbox;\
+ th->sandbox = curr_thread->sandbox;\
}\
} while (0)
@@ -12247,12 +12218,6 @@
static int thread_init;
-#if defined(POSIX_SIGNAL)
-#define CATCH_VTALRM() posix_signal(SIGVTALRM, catch_timer)
-#else
-#define CATCH_VTALRM() signal(SIGVTALRM, catch_timer)
-#endif
-
#if defined(_THREAD_SAFE)
static void
catch_timer(sig)
@@ -12264,58 +12229,30 @@
/* cause EINTR */
}
-#define PER_NANO 1000000000
+static pthread_t time_thread;
-static struct timespec *
-get_ts(struct timespec *to, long ns)
-{
- struct timeval tv;
-
-#ifdef CLOCK_REALTIME
- if (clock_gettime(CLOCK_REALTIME, to) != 0)
-#endif
- {
- gettimeofday(&tv, NULL);
- to->tv_sec = tv.tv_sec;
- to->tv_nsec = tv.tv_usec * 1000;
- }
- if ((to->tv_nsec += ns) >= PER_NANO) {
- to->tv_sec += to->tv_nsec / PER_NANO;
- to->tv_nsec %= PER_NANO;
- }
- return to;
-}
-
-static struct timer_thread {
- pthread_cond_t cond;
- pthread_mutex_t lock;
- pthread_t thread;
-} time_thread = {PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER};
-
-#define safe_mutex_lock(lock) \
- pthread_mutex_lock(lock); \
- pthread_cleanup_push((void (*)_((void *)))pthread_mutex_unlock, lock)
-
static void*
thread_timer(dummy)
void *dummy;
{
- struct timer_thread *running = ((void **)dummy)[0];
- pthread_cond_t *start = ((void **)dummy)[1];
- struct timespec to;
- int err;
-
sigset_t all_signals;
sigfillset(&all_signals);
pthread_sigmask(SIG_BLOCK, &all_signals, 0);
- safe_mutex_lock(&running->lock);
- pthread_cond_signal(start);
+ for (;;) {
+#ifdef HAVE_NANOSLEEP
+ struct timespec req, rem;
-#define WAIT_FOR_10MS() \
- pthread_cond_timedwait(&running->cond, &running->lock, get_ts(&to, PER_NANO/100))
- while ((err = WAIT_FOR_10MS()) == EINTR || err == ETIMEDOUT) {
+ req.tv_sec = 0;
+ req.tv_nsec = 10000000;
+ nanosleep(&req, &rem);
+#else
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ select(0, NULL, NULL, NULL, &tv);
+#endif
if (!rb_thread_critical) {
rb_thread_pending = 1;
if (rb_trap_immediate) {
@@ -12323,41 +12260,16 @@
}
}
}
-
- pthread_cleanup_pop(1);
-
- return NULL;
}
void
rb_thread_start_timer()
{
- void *args[2];
- static pthread_cond_t start = PTHREAD_COND_INITIALIZER;
-
- if (thread_init) return;
- if (rb_thread_alone()) return;
- CATCH_VTALRM();
- args[0] = &time_thread;
- args[1] = &start;
- safe_mutex_lock(&time_thread.lock);
- if (pthread_create(&time_thread.thread, 0, thread_timer, args) == 0) {
- thread_init = 1;
- pthread_atfork(0, 0, rb_thread_stop_timer);
- pthread_cond_wait(&start, &time_thread.lock);
- }
- pthread_cleanup_pop(1);
}
void
rb_thread_stop_timer()
{
- if (!thread_init) return;
- safe_mutex_lock(&time_thread.lock);
- pthread_cond_signal(&time_thread.cond);
- thread_init = 0;
- pthread_cleanup_pop(1);
- pthread_join(time_thread.thread, NULL);
}
#elif defined(HAVE_SETITIMER)
static void
@@ -12378,14 +12290,11 @@
{
struct itimerval tval;
- if (thread_init) return;
- if (rb_thread_alone()) return;
- CATCH_VTALRM();
+ if (!thread_init) return;
tval.it_interval.tv_sec = 0;
tval.it_interval.tv_usec = 10000;
tval.it_value = tval.it_interval;
setitimer(ITIMER_VIRTUAL, &tval, NULL);
- thread_init = 1;
}
void
@@ -12398,20 +12307,11 @@
tval.it_interval.tv_usec = 0;
tval.it_value = tval.it_interval;
setitimer(ITIMER_VIRTUAL, &tval, NULL);
- thread_init = 0;
}
#else /* !(_THREAD_SAFE || HAVE_SETITIMER) */
int rb_thread_tick = THREAD_TICK;
#endif
-#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
-#define START_TIMER() (thread_init ? (void)0 : rb_thread_start_timer())
-#define STOP_TIMER() (rb_thread_stop_timer())
-#else
-#define START_TIMER() ((void)0)
-#define STOP_TIMER() ((void)0)
-#endif
-
static VALUE
rb_thread_start_0(fn, arg, th)
VALUE (*fn)();
@@ -12429,6 +12329,23 @@
"can't start a new thread (frozen ThreadGroup)");
}
+ if (!thread_init) {
+ thread_init = 1;
+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
+#if defined(POSIX_SIGNAL)
+ posix_signal(SIGVTALRM, catch_timer);
+#else
+ signal(SIGVTALRM, catch_timer);
+#endif
+
+#ifdef _THREAD_SAFE
+ pthread_create(&time_thread, 0, thread_timer, 0);
+#else
+ rb_thread_start_timer();
+#endif
+#endif
+ }
+
if (THREAD_SAVE_CONTEXT(curr_thread)) {
return thread;
}
@@ -12451,7 +12368,6 @@
th->priority = curr_thread->priority;
th->thgroup = curr_thread->thgroup;
}
- START_TIMER();
PUSH_TAG(PROT_THREAD);
if ((state = EXEC_TAG()) == 0) {
@@ -13177,7 +13093,6 @@
main_thread = curr_thread;
curr_thread->next = curr_thread;
curr_thread->prev = curr_thread;
- STOP_TIMER();
}