* cont.c: add rb_context_t#type.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13843 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2007-11-09 01:11:49 +00:00
parent 0303c1d42b
commit 9f6de20f58
2 changed files with 43 additions and 22 deletions

View File

@ -1,3 +1,7 @@
Fri Nov 9 10:10:21 2007 Koichi Sasada <ko1@atdot.net>
* cont.c: add rb_context_t#type.
Fri Nov 9 10:05:54 2007 Koichi Sasada <ko1@atdot.net> Fri Nov 9 10:05:54 2007 Koichi Sasada <ko1@atdot.net>
* ruby.c (set_arg0): fix breaking environ bugs. * ruby.c (set_arg0): fix breaking environ bugs.

61
cont.c
View File

@ -15,6 +15,12 @@
#include "gc.h" #include "gc.h"
#include "eval_intern.h" #include "eval_intern.h"
enum context_type {
CONTINUATION_CONTEXT = 0,
FIBER_CONTEXT = 1,
ROOT_FIBER_CONTEXT = 2,
};
typedef struct rb_context_struct { typedef struct rb_context_struct {
VALUE self; VALUE self;
VALUE value; VALUE value;
@ -29,9 +35,9 @@ typedef struct rb_context_struct {
rb_thread_t saved_thread; rb_thread_t saved_thread;
rb_jmpbuf_t jmpbuf; rb_jmpbuf_t jmpbuf;
int machine_stack_size; int machine_stack_size;
/* for cont */
VALUE prev; VALUE prev;
int alive; int alive;
enum context_type type;
} rb_context_t; } rb_context_t;
static VALUE rb_cContinuation; static VALUE rb_cContinuation;
@ -86,10 +92,11 @@ cont_free(void *ptr)
RUBY_FREE_UNLESS_NULL(cont->machine_register_stack); RUBY_FREE_UNLESS_NULL(cont->machine_register_stack);
#endif #endif
RUBY_FREE_UNLESS_NULL(cont->vm_stack); RUBY_FREE_UNLESS_NULL(cont->vm_stack);
if (cont->vm_stack && cont->saved_thread.local_storage) {
/* fiber */ if (cont->type == FIBER_CONTEXT) {
st_free_table(cont->saved_thread.local_storage); st_free_table(cont->saved_thread.local_storage);
} }
ruby_xfree(ptr); ruby_xfree(ptr);
} }
RUBY_FREE_LEAVE("cont"); RUBY_FREE_LEAVE("cont");
@ -205,14 +212,7 @@ cont_restore_1(rb_context_t *cont)
rb_thread_t *th = GET_THREAD(), *sth = &cont->saved_thread; rb_thread_t *th = GET_THREAD(), *sth = &cont->saved_thread;
/* restore thread context */ /* restore thread context */
if (sth->stack) { if (cont->type == CONTINUATION_CONTEXT) {
/* fiber */
th->stack = sth->stack;
th->stack_size = sth->stack_size;
th->local_storage = sth->local_storage;
th->fiber = cont->self;
}
else {
/* continuation */ /* continuation */
VALUE fib; VALUE fib;
@ -227,6 +227,13 @@ cont_restore_1(rb_context_t *cont)
} }
MEMCPY(th->stack, cont->vm_stack, VALUE, sth->stack_size); MEMCPY(th->stack, cont->vm_stack, VALUE, sth->stack_size);
} }
else {
/* fiber */
th->stack = sth->stack;
th->stack_size = sth->stack_size;
th->local_storage = sth->local_storage;
th->fiber = cont->self;
}
th->cfp = sth->cfp; th->cfp = sth->cfp;
th->safe_level = sth->safe_level; th->safe_level = sth->safe_level;
@ -476,15 +483,25 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
#define FIBER_VM_STACK_SIZE (4 * 1024) #define FIBER_VM_STACK_SIZE (4 * 1024)
static VALUE static rb_context_t *
fiber_alloc(VALUE klass, VALUE proc) fiber_alloc(VALUE klass)
{ {
rb_context_t *cont = cont_new(klass); rb_context_t *cont = cont_new(klass);
cont->type = FIBER_CONTEXT;
cont->prev = Qnil;
return cont;
}
static VALUE
fiber_new(VALUE klass, VALUE proc)
{
rb_context_t *cont = fiber_alloc(klass);
VALUE contval = cont->self; VALUE contval = cont->self;
rb_thread_t *th = &cont->saved_thread; rb_thread_t *th = &cont->saved_thread;
/* initialize */ /* initialize */
cont->prev = Qnil;
cont->vm_stack = 0; cont->vm_stack = 0;
th->stack = 0; th->stack = 0;
@ -517,13 +534,13 @@ fiber_alloc(VALUE klass, VALUE proc)
VALUE VALUE
rb_fiber_new(VALUE (*func)(ANYARGS), VALUE obj) rb_fiber_new(VALUE (*func)(ANYARGS), VALUE obj)
{ {
return fiber_alloc(rb_cFiber, rb_proc_new(func, obj)); return fiber_new(rb_cFiber, rb_proc_new(func, obj));
} }
static VALUE static VALUE
rb_fiber_s_new(VALUE self) rb_fiber_s_new(VALUE self)
{ {
return fiber_alloc(self, rb_block_proc()); return fiber_new(self, rb_block_proc());
} }
static VALUE static VALUE
@ -604,15 +621,15 @@ rb_fiber_current()
rb_thread_t *th = GET_THREAD(); rb_thread_t *th = GET_THREAD();
if (th->fiber == 0) { if (th->fiber == 0) {
/* save root */ /* save root */
rb_context_t *cont = cont_new(rb_cFiber); rb_context_t *cont = fiber_alloc(rb_cFiber);
cont->prev = Qnil; cont->type = ROOT_FIBER_CONTEXT;
th->root_fiber = th->fiber = cont->self; th->root_fiber = th->fiber = cont->self;
} }
return th->fiber; return th->fiber;
} }
static VALUE static VALUE
cont_store(rb_context_t *next_cont) fiber_store(rb_context_t *next_cont)
{ {
rb_thread_t *th = GET_THREAD(); rb_thread_t *th = GET_THREAD();
rb_context_t *cont; rb_context_t *cont;
@ -623,8 +640,8 @@ cont_store(rb_context_t *next_cont)
} }
else { else {
/* create current fiber */ /* create current fiber */
cont = cont_new(rb_cFiber); /* no need to allocate vm stack */ cont = fiber_alloc(rb_cFiber); /* no need to allocate vm stack */
cont->prev = Qnil; cont->type = ROOT_FIBER_CONTEXT;
th->root_fiber = th->fiber = cont->self; th->root_fiber = th->fiber = cont->self;
} }
@ -665,7 +682,7 @@ fiber_switch(VALUE fib, int argc, VALUE *argv, int is_resume)
cont->value = make_passing_arg(argc, argv); cont->value = make_passing_arg(argc, argv);
if ((value = cont_store(cont)) == Qundef) { if ((value = fiber_store(cont)) == Qundef) {
cont_restore_0(cont, &value); cont_restore_0(cont, &value);
rb_bug("rb_fiber_resume: unreachable"); rb_bug("rb_fiber_resume: unreachable");
} }