diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2024-10-21 14:26:48 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2024-10-26 22:09:14 -0400 |
commit | ea546c789b4d1278078187b386ba85f324267892 (patch) | |
tree | e8259e73ac8385ff1644026c5da24c9c8c38634c | |
parent | f0a779771249948429e9c88dbec93cb467b606c5 (diff) | |
download | kutter-ea546c789b4d1278078187b386ba85f324267892.tar.gz kutter-ea546c789b4d1278078187b386ba85f324267892.tar.xz kutter-ea546c789b4d1278078187b386ba85f324267892.zip |
sched: Improve timer vs task priority check
Rename sched_tasks_busy() to sched_check_set_tasks_busy() and change
it to only return true if tasks are active (running or requested) for
two consecutive calls. This makes it less likely that timers will
yield to tasks except when tasks really are notably backlogged.
This also makes it less likely that multiple steppers controlling the
same rail will be interrupted by tasks mid-step. This should slightly
improve the timing, and make it less likely that a halt during
homing/probing will occur with these steppers taking a different
number of total steps.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r-- | src/avr/timer.c | 2 | ||||
-rw-r--r-- | src/generic/armcm_timer.c | 2 | ||||
-rw-r--r-- | src/generic/timer_irq.c | 2 | ||||
-rw-r--r-- | src/linux/timer.c | 2 | ||||
-rw-r--r-- | src/sched.c | 16 | ||||
-rw-r--r-- | src/sched.h | 2 |
6 files changed, 15 insertions, 11 deletions
diff --git a/src/avr/timer.c b/src/avr/timer.c index fb8738cc..d306b721 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 ef38680a..e7708180 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 40e9336b..7c2e871b 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 21be0131..8eda62a5 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 44cce558..51d159bc 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 <kevin@koconnor.net> +// Copyright (C) 2016-2024 Kevin O'Connor <kevin@koconnor.net> // // 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 0a2bdc4b..9ec96631 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); |