aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2016-10-31 11:48:27 -0400
committerKevin O'Connor <kevin@koconnor.net>2016-10-31 11:48:27 -0400
commit77d486f8d273aacdea8e4c7967e182d93f41b5ec (patch)
treea0ff321590fa72bd772e7a36a891a8687625005a /src
parent233a90ce8bb5e920be0fea327409c189b4391630 (diff)
downloadkutter-77d486f8d273aacdea8e4c7967e182d93f41b5ec.tar.gz
kutter-77d486f8d273aacdea8e4c7967e182d93f41b5ec.tar.xz
kutter-77d486f8d273aacdea8e4c7967e182d93f41b5ec.zip
sam3x8e: Rework timer priority code to use time instead of event count
Rework the timer prioritization code so that is compares against the current time instead of the number of repeat timers in a given interrupt. This makes the code slightly faster and it should provide better protection against task starvation. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src')
-rw-r--r--src/sam3x8e/timer.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/src/sam3x8e/timer.c b/src/sam3x8e/timer.c
index e473be9f..ead9c90f 100644
--- a/src/sam3x8e/timer.c
+++ b/src/sam3x8e/timer.c
@@ -89,12 +89,12 @@ timer_set_next(uint32_t next)
return 1;
}
-static uint32_t timer_repeat;
-#define TIMER_MAX_REPEAT 400
-#define TIMER_MAX_NEXT_REPEAT 150
+static uint32_t timer_repeat_until;
+#define TIMER_IDLE_REPEAT_TICKS timer_from_us(500)
+#define TIMER_REPEAT_TICKS timer_from_us(100)
#define TIMER_MIN_TRY_TICKS timer_from_us(1)
-#define TIMER_DEFER_REPEAT_TICKS timer_from_us(2)
+#define TIMER_DEFER_REPEAT_TICKS timer_from_us(5)
// Similar to timer_set_next(), but wait for the given time if it is
// in the near future.
@@ -108,10 +108,9 @@ timer_try_set_next(uint32_t next)
goto done;
// Next timer is in the past or near future - can't reschedule to it
- uint32_t tr = timer_repeat-1;
- if (likely(tr)) {
+ if (likely(sched_is_before(now, timer_repeat_until))) {
+ // Can run more timers from this irq; briefly allow irqs
irq_enable();
- timer_repeat = tr;
while (diff >= 0) {
// Next timer is in the near future - wait for time to occur
now = timer_read_time();
@@ -120,12 +119,12 @@ timer_try_set_next(uint32_t next)
irq_disable();
return 0;
}
+ if (diff < (int32_t)(-timer_from_us(1000)))
+ goto fail;
// Too many repeat timers from a single interrupt - force a pause
- timer_repeat = TIMER_MAX_NEXT_REPEAT;
+ timer_repeat_until = now + TIMER_REPEAT_TICKS;
next = now + TIMER_DEFER_REPEAT_TICKS;
- if (diff < (int32_t)(-timer_from_us(1000)))
- goto fail;
done:
timer_set(next);
@@ -134,9 +133,13 @@ fail:
shutdown("Rescheduled timer in the past");
}
+// Periodic background task that temporarily boosts priority of
+// timers. This helps prioritize timers when tasks are idling.
static void
timer_task(void)
{
- timer_repeat = TIMER_MAX_REPEAT;
+ irq_disable();
+ timer_repeat_until = timer_read_time() + TIMER_IDLE_REPEAT_TICKS;
+ irq_enable();
}
DECL_TASK(timer_task);