summaryrefslogtreecommitdiff
path: root/thread_pthread.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2021-02-02 18:23:07 +0900
committerKoichi Sasada <ko1@atdot.net>2021-02-02 20:20:39 +0900
commitbe1486568abac364c12e36d8dc49018ba8918c73 (patch)
tree67b7ea0a1c8d9678c53cf6152bccc93bfebec7df /thread_pthread.c
parentf92b7b7b97d57ad3f58034556224141d2f0e65c7 (diff)
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.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4145
Diffstat (limited to 'thread_pthread.c')
-rw-r--r--thread_pthread.c55
1 files changed, 47 insertions, 8 deletions
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;