зеркало из https://github.com/github/ruby.git
* thread.c: introduce spurious wakeup safe deadlock check.
[Bug #4696][ruby-dev:43554] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32021 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
3c9187a2ad
Коммит
614fcdf66c
|
@ -1,3 +1,8 @@
|
||||||
|
Sun Jun 12 15:47:35 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
|
||||||
|
|
||||||
|
* thread.c: introduce spurious wakeup safe deadlock check.
|
||||||
|
[Bug #4696][ruby-dev:43554]
|
||||||
|
|
||||||
Sun Jun 12 13:33:52 2011 Koichi Sasada <ko1@atdot.net>
|
Sun Jun 12 13:33:52 2011 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* benchmark/bm_vm3_thread_mutex.rb: remove it.
|
* benchmark/bm_vm3_thread_mutex.rb: remove it.
|
||||||
|
|
53
thread.c
53
thread.c
|
@ -335,7 +335,7 @@ typedef struct rb_mutex_struct
|
||||||
rb_thread_lock_t lock;
|
rb_thread_lock_t lock;
|
||||||
rb_thread_cond_t cond;
|
rb_thread_cond_t cond;
|
||||||
struct rb_thread_struct volatile *th;
|
struct rb_thread_struct volatile *th;
|
||||||
volatile int cond_waiting, cond_notified;
|
int cond_waiting;
|
||||||
struct rb_mutex_struct *next_mutex;
|
struct rb_mutex_struct *next_mutex;
|
||||||
} mutex_t;
|
} mutex_t;
|
||||||
|
|
||||||
|
@ -3457,41 +3457,42 @@ static int
|
||||||
lock_func(rb_thread_t *th, mutex_t *mutex, int timeout_ms)
|
lock_func(rb_thread_t *th, mutex_t *mutex, int timeout_ms)
|
||||||
{
|
{
|
||||||
int interrupted = 0;
|
int interrupted = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
native_mutex_lock(&mutex->lock);
|
native_mutex_lock(&mutex->lock);
|
||||||
th->transition_for_lock = 0;
|
th->transition_for_lock = 0;
|
||||||
|
|
||||||
|
mutex->cond_waiting++;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!mutex->th) {
|
if (!mutex->th) {
|
||||||
mutex->th = th;
|
mutex->th = th;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (RUBY_VM_INTERRUPTED(th)) {
|
||||||
|
interrupted = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (err == ETIMEDOUT) {
|
||||||
|
interrupted = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mutex->cond_waiting++;
|
|
||||||
if (timeout_ms) {
|
if (timeout_ms) {
|
||||||
int ret;
|
|
||||||
struct timespec timeout_rel;
|
struct timespec timeout_rel;
|
||||||
struct timespec timeout;
|
struct timespec timeout;
|
||||||
|
|
||||||
timeout_rel.tv_sec = 0;
|
timeout_rel.tv_sec = 0;
|
||||||
timeout_rel.tv_nsec = timeout_ms * 1000 * 1000;
|
timeout_rel.tv_nsec = timeout_ms * 1000 * 1000;
|
||||||
timeout = native_cond_timeout(&mutex->cond, timeout_rel);
|
timeout = native_cond_timeout(&mutex->cond, timeout_rel);
|
||||||
ret = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
|
err = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
|
||||||
if (ret == ETIMEDOUT) {
|
|
||||||
interrupted = 2;
|
|
||||||
mutex->cond_waiting--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
native_cond_wait(&mutex->cond, &mutex->lock);
|
native_cond_wait(&mutex->cond, &mutex->lock);
|
||||||
|
err = 0;
|
||||||
}
|
}
|
||||||
mutex->cond_notified--;
|
}
|
||||||
|
mutex->cond_waiting--;
|
||||||
|
|
||||||
if (RUBY_VM_INTERRUPTED(th)) {
|
|
||||||
interrupted = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
th->transition_for_lock = 1;
|
th->transition_for_lock = 1;
|
||||||
native_mutex_unlock(&mutex->lock);
|
native_mutex_unlock(&mutex->lock);
|
||||||
|
|
||||||
|
@ -3503,11 +3504,8 @@ lock_interrupt(void *ptr)
|
||||||
{
|
{
|
||||||
mutex_t *mutex = (mutex_t *)ptr;
|
mutex_t *mutex = (mutex_t *)ptr;
|
||||||
native_mutex_lock(&mutex->lock);
|
native_mutex_lock(&mutex->lock);
|
||||||
if (mutex->cond_waiting > 0) {
|
if (mutex->cond_waiting > 0)
|
||||||
native_cond_broadcast(&mutex->cond);
|
native_cond_broadcast(&mutex->cond);
|
||||||
mutex->cond_notified = mutex->cond_waiting;
|
|
||||||
mutex->cond_waiting = 0;
|
|
||||||
}
|
|
||||||
native_mutex_unlock(&mutex->lock);
|
native_mutex_unlock(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3593,12 +3591,8 @@ mutex_unlock(mutex_t *mutex, rb_thread_t volatile *th)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mutex->th = 0;
|
mutex->th = 0;
|
||||||
if (mutex->cond_waiting > 0) {
|
if (mutex->cond_waiting > 0)
|
||||||
/* waiting thread */
|
|
||||||
native_cond_signal(&mutex->cond);
|
native_cond_signal(&mutex->cond);
|
||||||
mutex->cond_waiting--;
|
|
||||||
mutex->cond_notified++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
native_mutex_unlock(&mutex->lock);
|
native_mutex_unlock(&mutex->lock);
|
||||||
|
@ -4742,7 +4736,7 @@ check_deadlock_i(st_data_t key, st_data_t val, int *found)
|
||||||
GetMutexPtr(th->locking_mutex, mutex);
|
GetMutexPtr(th->locking_mutex, mutex);
|
||||||
|
|
||||||
native_mutex_lock(&mutex->lock);
|
native_mutex_lock(&mutex->lock);
|
||||||
if (mutex->th == th || (!mutex->th && mutex->cond_notified)) {
|
if (mutex->th == th || (!mutex->th && mutex->cond_waiting)) {
|
||||||
*found = 1;
|
*found = 1;
|
||||||
}
|
}
|
||||||
native_mutex_unlock(&mutex->lock);
|
native_mutex_unlock(&mutex->lock);
|
||||||
|
@ -4751,7 +4745,7 @@ check_deadlock_i(st_data_t key, st_data_t val, int *found)
|
||||||
return (*found) ? ST_STOP : ST_CONTINUE;
|
return (*found) ? ST_STOP : ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* for debug */
|
#ifdef DEBUG_DEADLOCK_CHECK
|
||||||
static int
|
static int
|
||||||
debug_i(st_data_t key, st_data_t val, int *found)
|
debug_i(st_data_t key, st_data_t val, int *found)
|
||||||
{
|
{
|
||||||
|
@ -4765,10 +4759,11 @@ debug_i(st_data_t key, st_data_t val, int *found)
|
||||||
GetMutexPtr(th->locking_mutex, mutex);
|
GetMutexPtr(th->locking_mutex, mutex);
|
||||||
|
|
||||||
native_mutex_lock(&mutex->lock);
|
native_mutex_lock(&mutex->lock);
|
||||||
printf(" %p %d\n", mutex->th, mutex->cond_notified);
|
printf(" %p %d\n", mutex->th, mutex->cond_waiting);
|
||||||
native_mutex_unlock(&mutex->lock);
|
native_mutex_unlock(&mutex->lock);
|
||||||
}
|
}
|
||||||
else puts("");
|
else
|
||||||
|
puts("");
|
||||||
|
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -4788,7 +4783,7 @@ rb_check_deadlock(rb_vm_t *vm)
|
||||||
VALUE argv[2];
|
VALUE argv[2];
|
||||||
argv[0] = rb_eFatal;
|
argv[0] = rb_eFatal;
|
||||||
argv[1] = rb_str_new2("deadlock detected");
|
argv[1] = rb_str_new2("deadlock detected");
|
||||||
#if 0 /* for debug */
|
#ifdef DEBUG_DEADLOCK_CHECK
|
||||||
printf("%d %d %p %p\n", vm->living_threads->num_entries, vm->sleeper, GET_THREAD(), vm->main_thread);
|
printf("%d %d %p %p\n", vm->living_threads->num_entries, vm->sleeper, GET_THREAD(), vm->main_thread);
|
||||||
st_foreach(vm->living_threads, debug_i, (st_data_t)0);
|
st_foreach(vm->living_threads, debug_i, (st_data_t)0);
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче