diff --git a/src/avr/timer.c b/src/avr/timer.c index fb8738cc4d05..d306b7214962 100644 --- a/src/avr/timer.c +++ b/src/avr/timer.c @@ -197,7 +197,7 @@ ISR(TIMER1_COMPA_vect) uint16_t now = timer_get(); if ((int16_t)(next - now) < (int16_t)(-timer_from_us(1000))) try_shutdown("Rescheduled timer in the past"); - if (sched_tasks_busy()) { + if (sched_check_set_tasks_busy()) { timer_repeat_set(now + TIMER_REPEAT_TICKS); next = now + TIMER_DEFER_REPEAT_TICKS; goto done; diff --git a/src/generic/armcm_timer.c b/src/generic/armcm_timer.c index ef38680a9e70..e77081804d65 100644 --- a/src/generic/armcm_timer.c +++ b/src/generic/armcm_timer.c @@ -137,7 +137,7 @@ timer_dispatch_many(void) // Check if there are too many repeat timers if (diff < (int32_t)(-timer_from_us(1000))) try_shutdown("Rescheduled timer in the past"); - if (sched_tasks_busy()) { + if (sched_check_set_tasks_busy()) { timer_repeat_until = now + TIMER_REPEAT_TICKS; return TIMER_DEFER_REPEAT_TICKS; } diff --git a/src/generic/timer_irq.c b/src/generic/timer_irq.c index 40e9336b20c2..7c2e871bdf36 100644 --- a/src/generic/timer_irq.c +++ b/src/generic/timer_irq.c @@ -55,7 +55,7 @@ timer_dispatch_many(void) // Check if there are too many repeat timers if (diff < (int32_t)(-timer_from_us(1000))) try_shutdown("Rescheduled timer in the past"); - if (sched_tasks_busy()) { + if (sched_check_set_tasks_busy()) { timer_repeat_until = now + TIMER_REPEAT_TICKS; return now + TIMER_DEFER_REPEAT_TICKS; } diff --git a/src/linux/timer.c b/src/linux/timer.c index 21be01312460..8eda62a54ddc 100644 --- a/src/linux/timer.c +++ b/src/linux/timer.c @@ -152,7 +152,7 @@ timer_dispatch(void) // Check if there are too many repeat timers if (diff < (int32_t)(-timer_from_us(100000))) try_shutdown("Rescheduled timer in the past"); - if (sched_tasks_busy()) + if (sched_check_set_tasks_busy()) return; repeat_count = TIMER_IDLE_REPEAT_COUNT; } diff --git a/src/sched.c b/src/sched.c index 44cce558ee9e..51d159bc6e5c 100644 --- a/src/sched.c +++ b/src/sched.c @@ -1,6 +1,6 @@ // Basic scheduling functions and startup/shutdown code. // -// Copyright (C) 2016-2021 Kevin O'Connor +// Copyright (C) 2016-2024 Kevin O'Connor // // This file may be distributed under the terms of the GNU GPLv3 license. @@ -19,7 +19,7 @@ static struct timer periodic_timer, sentinel_timer, deleted_timer; static struct { struct timer *timer_list, *last_insert; - int8_t tasks_status; + int8_t tasks_status, tasks_busy; uint8_t shutdown_status, shutdown_reason; } SchedStatus = {.timer_list = &periodic_timer, .last_insert = &periodic_timer}; @@ -205,11 +205,15 @@ sched_wake_tasks(void) SchedStatus.tasks_status = TS_REQUESTED; } -// Check if tasks need to be run +// Check if tasks busy (called from low-level timer dispatch code) uint8_t -sched_tasks_busy(void) +sched_check_set_tasks_busy(void) { - return SchedStatus.tasks_status >= TS_REQUESTED; + // Return busy if tasks never idle between two consecutive calls + if (SchedStatus.tasks_busy >= TS_REQUESTED) + return 1; + SchedStatus.tasks_busy = SchedStatus.tasks_status; + return 0; } // Note that a task is ready to run @@ -243,7 +247,7 @@ run_tasks(void) irq_disable(); if (SchedStatus.tasks_status != TS_REQUESTED) { // Sleep processor (only run timers) until tasks woken - SchedStatus.tasks_status = TS_IDLE; + SchedStatus.tasks_status = SchedStatus.tasks_busy = TS_IDLE; do { irq_wait(); } while (SchedStatus.tasks_status != TS_REQUESTED); diff --git a/src/sched.h b/src/sched.h index 0a2bdc4bcab0..9ec96631eeb4 100644 --- a/src/sched.h +++ b/src/sched.h @@ -31,7 +31,7 @@ void sched_del_timer(struct timer *del); unsigned int sched_timer_dispatch(void); void sched_timer_reset(void); void sched_wake_tasks(void); -uint8_t sched_tasks_busy(void); +uint8_t sched_check_set_tasks_busy(void); void sched_wake_task(struct task_wake *w); uint8_t sched_check_wake(struct task_wake *w); uint8_t sched_is_shutdown(void);