summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-09-23 00:01:50 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-09-23 00:01:50 +0000
commit50b224dd15c5e4aab0d04c5c5ad7d224fbeb1855 (patch)
treed58048fc2956c1c21f97cdc390a0da894a94f82f /ext
parent13d5a288271077f74547b803443d821b2cfa0bfb (diff)
* eval.c, intern.h, ext/thread/thread.c: should not free queue while
any live threads are waiting. [ruby-dev:30653] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@13495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/thread/thread.c50
1 files changed, 19 insertions, 31 deletions
diff --git a/ext/thread/thread.c b/ext/thread/thread.c
index 3dba9ba..bca8077 100644
--- a/ext/thread/thread.c
+++ b/ext/thread/thread.c
@@ -24,11 +24,12 @@ static VALUE rb_cSizedQueue;
static VALUE set_critical(VALUE value);
static VALUE
-thread_exclusive_do(void)
+thread_exclusive(VALUE (*func)(ANYARGS), VALUE arg)
{
- rb_thread_critical = 1;
+ VALUE critical = rb_thread_critical;
- return rb_yield(Qundef);
+ rb_thread_critical = 1;
+ return rb_ensure(func, arg, set_critical, (VALUE)critical);
}
/*
@@ -43,7 +44,7 @@ thread_exclusive_do(void)
static VALUE
rb_thread_exclusive(void)
{
- return rb_ensure(thread_exclusive_do, Qundef, set_critical, rb_thread_critical);
+ return thread_exclusive(rb_yield, Qundef);
}
typedef struct _Entry {
@@ -147,7 +148,7 @@ shift_list(List *list)
VALUE value;
entry = list->entries;
- if (!entry) return Qundef;
+ if (!entry) return Qnil;
list->entries = entry->next;
if (entry == list->last_entry) {
@@ -269,20 +270,12 @@ wait_list(List *list)
}
static void
-assert_no_survivors(List *waiting, const char *label, void *addr)
+kill_waiting_threads(List *waiting)
{
Entry *entry;
- VALUE ths = 0;
for (entry = waiting->entries; entry; entry = entry->next) {
- if (RTEST(wake_thread(entry->value))) {
- if (!ths) ths = rb_ary_new();
- rb_ary_push(ths, entry->value);
- }
- }
- if (ths) {
- rb_bug("%s %p freed with live thread(s) %s waiting",
- label, addr, RSTRING_PTR(rb_inspect(ths)));
+ rb_thread_kill(entry->value);
}
}
@@ -334,7 +327,7 @@ finalize_mutex(Mutex *mutex)
static void
free_mutex(Mutex *mutex)
{
- assert_no_survivors(&mutex->waiting, "mutex", mutex);
+ kill_waiting_threads(&mutex->waiting);
finalize_mutex(mutex);
xfree(mutex);
}
@@ -493,10 +486,8 @@ set_critical(VALUE value)
static VALUE
unlock_mutex(Mutex *mutex)
{
- VALUE waking;
+ VALUE waking = thread_exclusive(unlock_mutex_inner, (VALUE)mutex);
- rb_thread_critical = 1;
- waking = rb_ensure(unlock_mutex_inner, (VALUE)mutex, set_critical, 0);
if (!RTEST(waking)) {
return Qfalse;
}
@@ -544,10 +535,9 @@ rb_mutex_exclusive_unlock(VALUE self)
VALUE waking;
Data_Get_Struct(self, Mutex, mutex);
- rb_thread_critical = 1;
- waking = rb_ensure(rb_mutex_exclusive_unlock_inner, (VALUE)mutex, set_critical, 0);
+ waking = thread_exclusive(rb_mutex_exclusive_unlock_inner, (VALUE)mutex);
- if (waking == Qundef || !RTEST(waking)) {
+ if (!RTEST(waking)) {
return Qnil;
}
@@ -622,7 +612,7 @@ finalize_condvar(ConditionVariable *condvar)
static void
free_condvar(ConditionVariable *condvar)
{
- assert_no_survivors(&condvar->waiting, "condition variable", condvar);
+ kill_waiting_threads(&condvar->waiting);
finalize_condvar(condvar);
xfree(condvar);
}
@@ -732,8 +722,7 @@ rb_condvar_broadcast(VALUE self)
Data_Get_Struct(self, ConditionVariable, condvar);
- rb_thread_critical = 1;
- rb_ensure(wake_all, (VALUE)&condvar->waiting, set_critical, 0);
+ thread_exclusive(wake_all, (VALUE)&condvar->waiting);
rb_thread_schedule();
return self;
@@ -750,9 +739,8 @@ rb_condvar_broadcast(VALUE self)
static void
signal_condvar(ConditionVariable *condvar)
{
- VALUE waking;
- rb_thread_critical = 1;
- waking = rb_ensure(wake_one, (VALUE)&condvar->waiting, set_critical, 0);
+ VALUE waking = thread_exclusive(wake_one, (VALUE)&condvar->waiting);
+
if (RTEST(waking)) {
run_thread(waking);
}
@@ -827,9 +815,9 @@ finalize_queue(Queue *queue)
static void
free_queue(Queue *queue)
{
- assert_no_survivors(&queue->mutex.waiting, "queue", queue);
- assert_no_survivors(&queue->space_available.waiting, "queue", queue);
- assert_no_survivors(&queue->value_available.waiting, "queue", queue);
+ kill_waiting_threads(&queue->mutex.waiting);
+ kill_waiting_threads(&queue->space_available.waiting);
+ kill_waiting_threads(&queue->value_available.waiting);
finalize_queue(queue);
xfree(queue);
}