From be1486568abac364c12e36d8dc49018ba8918c73 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 2 Feb 2021 18:23:07 +0900 Subject: add debug code for timer_posix timer_posix mode is managed by timer_posix.state. This patch adds some debug code for the transition of the state. --- thread_pthread.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 8 deletions(-) (limited to 'thread_pthread.c') diff --git a/thread_pthread.c b/thread_pthread.c index 894341c2a5..8149ee57f5 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -103,13 +103,52 @@ enum rtimer_state { #if UBF_TIMER == UBF_TIMER_POSIX static const struct itimerspec zero; static struct { - rb_atomic_t state; /* rtimer_state */ + rb_atomic_t state_; /* rtimer_state */ rb_pid_t owner; timer_t timerid; } timer_posix = { /* .state = */ RTIMER_DEAD, }; +#define TIMER_STATE_DEBUG 0 + +static const char * +rtimer_state_name(enum rtimer_state state) +{ + switch (state) { + case RTIMER_DISARM: return "disarm"; + case RTIMER_ARMING: return "arming"; + case RTIMER_ARMED: return "armed"; + case RTIMER_DEAD: return "dead"; + default: rb_bug("unreachable"); + } +} + +static enum rtimer_state +timer_state_exchange(enum rtimer_state state) +{ + enum rtimer_state prev = ATOMIC_EXCHANGE(timer_posix.state_, state); + if (TIMER_STATE_DEBUG) fprintf(stderr, "state (exc): %s->%s\n", rtimer_state_name(prev), rtimer_state_name(state)); + return prev; +} + +static enum rtimer_state +timer_state_cas(enum rtimer_state expected_prev, enum rtimer_state state) +{ + enum rtimer_state prev = ATOMIC_CAS(timer_posix.state_, expected_prev, state); + + if (TIMER_STATE_DEBUG) { + if (prev == expected_prev) { + fprintf(stderr, "state (cas): %s->%s\n", rtimer_state_name(prev), rtimer_state_name(state)); + } + else { + fprintf(stderr, "state (cas): %s (expected:%s)\n", rtimer_state_name(prev), rtimer_state_name(expected_prev)); + } + } + + return prev; +} + #elif UBF_TIMER == UBF_TIMER_PTHREAD static void *timer_pthread_fn(void *); static struct { @@ -1423,7 +1462,7 @@ ubf_timer_arm(rb_pid_t current) /* async signal safe */ { #if UBF_TIMER == UBF_TIMER_POSIX if ((!current || timer_posix.owner == current) && - !ATOMIC_CAS(timer_posix.state, RTIMER_DISARM, RTIMER_ARMING)) { + timer_state_cas(RTIMER_DISARM, RTIMER_ARMING) == RTIMER_DISARM) { struct itimerspec it; it.it_interval.tv_sec = it.it_value.tv_sec = 0; @@ -1432,7 +1471,7 @@ ubf_timer_arm(rb_pid_t current) /* async signal safe */ if (timer_settime(timer_posix.timerid, 0, &it, 0)) rb_async_bug_errno("timer_settime (arm)", errno); - switch (ATOMIC_CAS(timer_posix.state, RTIMER_ARMING, RTIMER_ARMED)) { + switch (timer_state_cas(RTIMER_ARMING, RTIMER_ARMED)) { case RTIMER_DISARM: /* somebody requested a disarm while we were arming */ /* may race harmlessly with ubf_timer_destroy */ @@ -1714,7 +1753,7 @@ ubf_timer_create(rb_pid_t current) sev.sigev_value.sival_ptr = &timer_posix; if (!timer_create(UBF_TIMER_CLOCK, &sev, &timer_posix.timerid)) { - rb_atomic_t prev = ATOMIC_EXCHANGE(timer_posix.state, RTIMER_DISARM); + rb_atomic_t prev = timer_state_exchange(RTIMER_DISARM); if (prev != RTIMER_DEAD) { rb_bug("timer_posix was not dead: %u\n", (unsigned)prev); @@ -1759,7 +1798,7 @@ ubf_timer_disarm(void) #if UBF_TIMER == UBF_TIMER_POSIX rb_atomic_t prev; - prev = ATOMIC_CAS(timer_posix.state, RTIMER_ARMED, RTIMER_DISARM); + prev = timer_state_cas(RTIMER_ARMED, RTIMER_DISARM); switch (prev) { case RTIMER_DISARM: return; /* likely */ case RTIMER_ARMING: return; /* ubf_timer_arm will disarm itself */ @@ -1768,7 +1807,7 @@ ubf_timer_disarm(void) int err = errno; if (err == EINVAL) { - prev = ATOMIC_CAS(timer_posix.state, RTIMER_DISARM, RTIMER_DISARM); + prev = timer_state_cas(RTIMER_DISARM, RTIMER_DISARM); /* main thread may have killed the timer */ if (prev == RTIMER_DEAD) return; @@ -1797,7 +1836,7 @@ ubf_timer_destroy(void) /* prevent signal handler from arming: */ for (i = 0; i < max; i++) { - switch (ATOMIC_CAS(timer_posix.state, expect, RTIMER_DEAD)) { + switch (timer_state_cas(expect, RTIMER_DEAD)) { case RTIMER_DISARM: if (expect == RTIMER_DISARM) goto done; expect = RTIMER_DISARM; @@ -1823,7 +1862,7 @@ done: if (timer_delete(timer_posix.timerid) < 0) rb_sys_fail("timer_delete"); - VM_ASSERT(ATOMIC_EXCHANGE(timer_posix.state, RTIMER_DEAD) == RTIMER_DEAD); + VM_ASSERT(timer_state_exchange(RTIMER_DEAD) == RTIMER_DEAD); } #elif UBF_TIMER == UBF_TIMER_PTHREAD int err; -- cgit v1.2.1