summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--thread.c35
-rw-r--r--thread_pthread.c81
-rw-r--r--thread_win32.c23
4 files changed, 92 insertions, 62 deletions
diff --git a/ChangeLog b/ChangeLog
index 71c407fefa..5e1e788368 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Sat May 7 02:29:41 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ mutex: deadlock check timeout use monotonic time.
+
+ * thread_pthread.c (native_cond_timeout): new internal api.
+ it calculate a proper time for argument of native_cond_timedwait().
+ * thread_win32.c (native_cond_timeout): ditto.
+
+ * thread_pthread.c (thread_timer): use native_cond_timeout()
+ instead of get_ts.
+ * thread.c (lock_func): ditto.
+
+ * thread_pthread.c (get_ts): removed. use native_cond_timeout().
+ * thread.c (init_lock_timeout): ditto.
+
Sat May 7 01:54:21 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* thread_pthread.c (get_ts): add monotonic clock capability.
diff --git a/thread.c b/thread.c
index 1e3b957dd8..0bdc4ef6bf 100644
--- a/thread.c
+++ b/thread.c
@@ -3336,7 +3336,7 @@ mutex_alloc(VALUE klass)
obj = TypedData_Make_Struct(klass, mutex_t, &mutex_data_type, mutex);
native_mutex_initialize(&mutex->lock);
- native_cond_initialize(&mutex->cond, 0);
+ native_cond_initialize(&mutex->cond, RB_CONDATTR_CLOCK_MONOTONIC);
return obj;
}
@@ -3410,26 +3410,6 @@ rb_mutex_trylock(VALUE self)
return locked;
}
-static struct timespec init_lock_timeout(int timeout_ms)
-{
- struct timespec ts;
- struct timeval tv;
- int ret;
-
- ret = gettimeofday(&tv, NULL);
- if (ret < 0)
- rb_sys_fail(0);
-
- ts.tv_sec = tv.tv_sec;
- ts.tv_nsec = tv.tv_usec * 1000 + timeout_ms * 1000 * 1000;
- if (ts.tv_nsec >= 1000000000) {
- ts.tv_sec++;
- ts.tv_nsec -= 1000000000;
- }
-
- return ts;
-}
-
static int
lock_func(rb_thread_t *th, mutex_t *mutex, int timeout_ms)
{
@@ -3438,9 +3418,6 @@ lock_func(rb_thread_t *th, mutex_t *mutex, int timeout_ms)
native_mutex_lock(&mutex->lock);
th->transition_for_lock = 0;
for (;;) {
- struct timespec ts;
- int ret;
-
if (!mutex->th) {
mutex->th = th;
break;
@@ -3448,8 +3425,14 @@ lock_func(rb_thread_t *th, mutex_t *mutex, int timeout_ms)
mutex->cond_waiting++;
if (timeout_ms) {
- ts = init_lock_timeout(timeout_ms);
- ret = native_cond_timedwait(&mutex->cond, &mutex->lock, &ts);
+ int ret;
+ struct timespec timeout_rel;
+ struct timespec timeout;
+
+ timeout_rel.tv_sec = 0;
+ timeout_rel.tv_nsec = timeout_ms * 1000 * 1000;
+ timeout = native_cond_timeout(&mutex->cond, timeout_rel);
+ ret = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
if (ret == ETIMEDOUT) {
interrupted = 2;
break;
diff --git a/thread_pthread.c b/thread_pthread.c
index 7d55ba2763..ba2b954388 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -295,6 +295,41 @@ native_cond_timedwait(rb_thread_cond_t *cond, pthread_mutex_t *mutex, struct tim
return r;
}
+static struct timespec
+native_cond_timeout(rb_thread_cond_t *cond, struct timespec timeout_rel)
+{
+ int ret;
+ struct timeval tv;
+ struct timespec timeout;
+
+#if USE_MONOTONIC_COND
+ if (cond->clockid == CLOCK_MONOTONIC) {
+ ret = clock_gettime(cond->clockid, &timeout);
+ if (ret != 0)
+ rb_sys_fail("clock_gettime()");
+ goto out;
+ }
+#endif
+
+ if (cond->clockid != CLOCK_REALTIME)
+ rb_bug("unsupported clockid %d", cond->clockid);
+
+ ret = gettimeofday(&tv, 0);
+ if (ret != 0)
+ rb_sys_fail(0);
+ timeout.tv_sec = tv.tv_sec;
+ timeout.tv_nsec = tv.tv_usec * 1000;
+
+ out:
+ timeout.tv_sec += timeout_rel.tv_sec;
+ timeout.tv_nsec += timeout_rel.tv_nsec;
+ if (timeout.tv_nsec >= 1000*1000*1000) {
+ timeout.tv_sec++;
+ timeout.tv_nsec -= 1000*1000*1000;
+ }
+ return timeout;
+}
+
#define native_cleanup_push pthread_cleanup_push
#define native_cleanup_pop pthread_cleanup_pop
#ifdef HAVE_SCHED_YIELD
@@ -917,49 +952,23 @@ static pthread_t timer_thread_id;
static rb_thread_cond_t timer_thread_cond;
static pthread_mutex_t timer_thread_lock = PTHREAD_MUTEX_INITIALIZER;
-static struct timespec *
-get_ts(struct timespec *ts, unsigned long nsec)
-{
- int ret;
- struct timeval tv;
-
-#if USE_MONOTONIC_COND
- if (timer_thread_cond.clockid == CLOCK_MONOTONIC) {
- ret = clock_gettime(CLOCK_MONOTONIC, ts);
- if (ret != 0)
- rb_sys_fail("clock_gettime(CLOCK_MONOTONIC)");
- goto out;
- }
-#endif
-
- if (timer_thread_cond.clockid != CLOCK_REALTIME)
- rb_bug("unsupported clockid %d", timer_thread_cond.clockid);
-
- ret = gettimeofday(&tv, 0);
- if (ret != 0)
- rb_sys_fail(0);
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_usec * 1000;
-
- out:
- ts->tv_nsec += nsec;
- if (ts->tv_nsec >= PER_NANO) {
- ts->tv_sec++;
- ts->tv_nsec -= PER_NANO;
- }
- return ts;
-}
-
static void *
thread_timer(void *dummy)
{
- struct timespec ts;
+ struct timespec timeout_10ms;
+
+ timeout_10ms.tv_sec = 0;
+ timeout_10ms.tv_nsec = 10 * 1000 * 1000;
native_mutex_lock(&timer_thread_lock);
native_cond_broadcast(&timer_thread_cond);
-#define WAIT_FOR_10MS() native_cond_timedwait(&timer_thread_cond, &timer_thread_lock, get_ts(&ts, PER_NANO/100))
while (system_working > 0) {
- int err = WAIT_FOR_10MS();
+ int err;
+ struct timespec timeout;
+
+ timeout = native_cond_timeout(&timer_thread_cond, timeout_10ms);
+ err = native_cond_timedwait(&timer_thread_cond, &timer_thread_lock,
+ &timeout);
if (err == ETIMEDOUT);
else if (err == 0 || err == EINTR) {
if (rb_signal_buff_size() == 0) break;
diff --git a/thread_win32.c b/thread_win32.c
index 287f637911..62f78fd850 100644
--- a/thread_win32.c
+++ b/thread_win32.c
@@ -489,6 +489,29 @@ native_cond_timedwait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex, struct ti
return __cond_timedwait(cond, mutex, timeout_ms);
}
+static struct timespec
+native_cond_timeout(rb_thread_cond_t *cond, struct timespec timeout_rel)
+{
+ int ret;
+ struct timeval tv;
+ struct timespec timeout;
+
+ ret = gettimeofday(&tv, 0);
+ if (ret != 0)
+ rb_sys_fail(0);
+ timeout.tv_sec = tv.tv_sec;
+ timeout.tv_nsec = tv.tv_usec * 1000;
+
+ timeout.tv_sec += timeout_rel.tv_sec;
+ timeout.tv_nsec += timeout_rel.tv_nsec;
+ if (timeout.tv_nsec >= 1000*1000*1000) {
+ timeout.tv_sec++;
+ timeout.tv_nsec -= 1000*1000*1000;
+ }
+ return timeout;
+}
+
+
static void
native_cond_initialize(rb_thread_cond_t *cond, int flags)
{