From 99cd3c512b78774c8c4ecb92ca4c6278577a58c5 Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 11 Nov 2008 18:28:47 +0000 Subject: [PATCH] * load.c (rb_require_safe): destroys barrier after successfully loaded, to get rid of loading same library again. [ruby-core:19798] * thread.c (rb_barrier_wait): can not wait destroyed barrier. * thread.c (rb_barrier_destroy): destroys barrier so that no longer waited. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20223 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 ++++++++++ include/ruby/intern.h | 1 + load.c | 12 ++++++++---- thread.c | 36 +++++++++++++++++++++++++++++++----- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 374d57ca7c..db0576455b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Wed Nov 12 03:28:41 2008 Nobuyoshi Nakada + + * load.c (rb_require_safe): destroys barrier after successfully + loaded, to get rid of loading same library again. [ruby-core:19798] + + * thread.c (rb_barrier_wait): can not wait destroyed barrier. + + * thread.c (rb_barrier_destroy): destroys barrier so that no longer + waited. + Tue Nov 11 23:02:27 2008 Yuki Sonoda (Yugui) * man/ruby.1 (RUBYOPT): wrote which option can appear. diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 739ff1e834..a04ae309b8 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -680,6 +680,7 @@ VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg); VALUE rb_barrier_new(void); VALUE rb_barrier_wait(VALUE self); VALUE rb_barrier_release(VALUE self); +VALUE rb_barrier_destroy(VALUE self); /* time.c */ VALUE rb_time_new(time_t, long); VALUE rb_time_nano_new(time_t, long); diff --git a/load.c b/load.c index d550f2c2c4..dbca370576 100644 --- a/load.c +++ b/load.c @@ -366,7 +366,7 @@ load_lock(const char *ftptr) } static void -load_unlock(const char *ftptr) +load_unlock(const char *ftptr, int done) { if (ftptr) { st_data_t key = (st_data_t)ftptr; @@ -374,8 +374,12 @@ load_unlock(const char *ftptr) st_table *loading_tbl = get_loading_table(); if (st_delete(loading_tbl, &key, &data)) { + VALUE barrier = (VALUE)data; xfree((char *)key); - rb_barrier_release((VALUE)data); + if (done) + rb_barrier_destroy(barrier); + else + rb_barrier_release(barrier); } } } @@ -561,7 +565,7 @@ rb_require_safe(VALUE fname, int safe) } } POP_TAG(); - load_unlock(ftptr); + load_unlock(ftptr, !state); rb_set_safe_level_force(saved.safe); if (state) { @@ -600,7 +604,7 @@ ruby_init_ext(const char *name, void (*init)(void)) rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call, (VALUE)init, 0, rb_str_new2(name)); rb_provide(name); - load_unlock(name); + load_unlock(name, 1); } } diff --git a/thread.c b/thread.c index f6bcc9801f..f0a26df7ed 100644 --- a/thread.c +++ b/thread.c @@ -3125,6 +3125,14 @@ rb_barrier_new(void) return barrier_alloc(rb_cBarrier); } +static int +rb_barrier_signal(rb_barrier_t *barrier, unsigned int maxth) +{ + int n = thlist_signal(&barrier->waiting, maxth, &barrier->owner); + if (!barrier->waiting) barrier->tail = &barrier->waiting; + return n; +} + VALUE rb_barrier_wait(VALUE self) { @@ -3133,9 +3141,10 @@ rb_barrier_wait(VALUE self) rb_thread_t *th = GET_THREAD(); Data_Get_Struct(self, rb_barrier_t, barrier); + if (!barrier->tail) return Qfalse; if (!barrier->owner || barrier->owner->status == THREAD_KILLED) { barrier->owner = 0; - if (thlist_signal(&barrier->waiting, 1, &barrier->owner)) return Qfalse; + if (rb_barrier_signal(barrier, 1)) return Qfalse; barrier->owner = th; return Qtrue; } @@ -3148,21 +3157,38 @@ rb_barrier_wait(VALUE self) q->next = 0; barrier->tail = &q->next; rb_thread_sleep_forever(); + if (!barrier->tail) return Qfalse; return barrier->owner == th ? Qtrue : Qfalse; } } -VALUE -rb_barrier_release(VALUE self) +static rb_barrier_t * +rb_barrier_owned_ptr(VALUE self) { rb_barrier_t *barrier; - unsigned int n; Data_Get_Struct(self, rb_barrier_t, barrier); if (barrier->owner != GET_THREAD()) { rb_raise(rb_eThreadError, "not owned"); } - n = thlist_signal(&barrier->waiting, 0, &barrier->owner); + return barrier; +} + +VALUE +rb_barrier_release(VALUE self) +{ + rb_barrier_t *barrier = rb_barrier_owned_ptr(self); + unsigned int n = rb_barrier_signal(barrier, 0); + return n ? UINT2NUM(n) : Qfalse; +} + +VALUE +rb_barrier_destroy(VALUE self) +{ + rb_barrier_t *barrier = rb_barrier_owned_ptr(self); + int n = thlist_signal(&barrier->waiting, 0, 0); + barrier->owner = 0; + barrier->tail = 0; return n ? UINT2NUM(n) : Qfalse; }