diff --git a/src/include/86box/timer.h b/src/include/86box/timer.h index 4ade8aab0..91f903a0f 100644 --- a/src/include/86box/timer.h +++ b/src/include/86box/timer.h @@ -43,7 +43,7 @@ typedef struct pc_timer_t { ts_t ts; #endif int flags; /* The flags are defined above. */ - int pad; + int in_callback; double period; /* This is used for large period timers to count the microseconds and split the period. */ diff --git a/src/timer.c b/src/timer.c index fa8376bde..d7102ffc3 100644 --- a/src/timer.c +++ b/src/timer.c @@ -94,6 +94,7 @@ timer_disable(pc_timer_t *timer) fatal("timer_disable - !timer->next\n"); timer->flags &= ~TIMER_ENABLED; + timer->in_callback = 0; if (timer->prev) timer->prev->next = timer->next; @@ -127,11 +128,15 @@ timer_process(void) if (timer->flags & TIMER_SPLIT) timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into - multiple <= 1 s periods. */ - else if (timer->callback != NULL) /* Make sure it's not NULL, so that we can - have a NULL callback when no operation - is needed. */ + multiple <= 1 s periods. */ + else if (timer->callback != NULL) { + /* Make sure it's not NULL, so that we can + have a NULL callback when no operation + is needed. */ + timer->in_callback = 1; timer->callback(timer->priv); + timer->in_callback = 0; + } } timer_target = timer_head->ts.ts32.integer; @@ -171,10 +176,11 @@ timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *priv, int start { memset(timer, 0, sizeof(pc_timer_t)); - timer->callback = callback; - timer->priv = priv; - timer->flags = 0; - timer->prev = timer->next = NULL; + timer->callback = callback; + timer->in_callback = 0; + timer->priv = priv; + timer->flags = 0; + timer->prev = timer->next = NULL; if (start_timer) timer_set_delay_u64(timer, 0); } @@ -189,6 +195,7 @@ timer_stop(pc_timer_t *timer) timer->period = 0.0; timer_disable(timer); timer->flags &= ~TIMER_SPLIT; + timer->in_callback = 0; } static void @@ -240,7 +247,9 @@ timer_on_auto(pc_timer_t *timer, double period) return; if (period > 0.0) - timer_on(timer, period, timer->period <= 0.0); + /* If the timer is in the callback, signal that, so that timer_advance_u64() + is used instead of timer_set_delay_u64(). */ + timer_on(timer, period, (timer->period <= 0.0) && !timer->in_callback); else timer_stop(timer); }