Skip to content

Commit

Permalink
sched: Improve timer vs task priority check
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
KevinOConnor committed Oct 24, 2024
1 parent 0855994 commit d597361
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/avr/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/generic/armcm_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/generic/timer_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/linux/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
16 changes: 10 additions & 6 deletions src/sched.c
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -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};

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d597361

Please sign in to comment.