diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2017-08-07 12:33:08 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2017-08-08 00:27:28 -0400 |
commit | 2c272f99a3fac49d8acd4b49a1aa3302225f17b8 (patch) | |
tree | 07998c722ed20fa812de26e1941daf57a030271f /src/sched.c | |
parent | a9982beacf184ccdc4bf1221852c900b0809537d (diff) | |
download | kutter-2c272f99a3fac49d8acd4b49a1aa3302225f17b8.tar.gz kutter-2c272f99a3fac49d8acd4b49a1aa3302225f17b8.tar.xz kutter-2c272f99a3fac49d8acd4b49a1aa3302225f17b8.zip |
sched: Implement generic sleep mechanism based on tasks pending
Track when tasks are pending and spin in irq_wait() when no tasks are
pending. This improves the mechanism for sleeping the processor -
it's simpler for the board specific code and it reduces the
possibility of the processor sleeping when tasks are busy.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/sched.c')
-rw-r--r-- | src/sched.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/src/sched.c b/src/sched.c index a2f5fea8..e6401bbb 100644 --- a/src/sched.c +++ b/src/sched.c @@ -6,6 +6,7 @@ #include <setjmp.h> // setjmp #include "autoconf.h" // CONFIG_* +#include "basecmd.h" // stats_update #include "board/io.h" // readb #include "board/irq.h" // irq_save #include "board/misc.h" // timer_from_us @@ -177,13 +178,23 @@ sched_timer_reset(void) /**************************************************************** - * Task waking + * Tasks ****************************************************************/ +static int_fast8_t tasks_pending; + // Note that at least one task is ready to run void sched_wake_tasks(void) { + tasks_pending = 0; +} + +// Check if tasks need to be run +uint8_t +sched_tasks_busy(void) +{ + return tasks_pending >= 0; } // Note that a task is ready to run @@ -204,6 +215,40 @@ sched_check_wake(struct task_wake *w) return 1; } +// Main task dispatch loop +static void +run_tasks(void) +{ + uint32_t start = timer_read_time(); + for (;;) { + // Check if can sleep + irq_disable(); + if (!tasks_pending) { + // Tasks are busy - don't sleep + irq_enable(); + } else { + // Sleep processor (only run timers) until tasks pending + tasks_pending = -1; + uint32_t sleep_start = timer_read_time(); + do { + irq_wait(); + } while (!sched_tasks_busy()); + irq_enable(); + start += timer_read_time() - sleep_start; + } + tasks_pending = 1; + + // Run all tasks + extern void ctr_run_taskfuncs(void); + ctr_run_taskfuncs(); + + // Update statistics + uint32_t cur = timer_read_time(); + stats_update(start, cur); + start = cur; + } +} + /**************************************************************** * Shutdown processing @@ -274,23 +319,19 @@ sched_shutdown(uint_fast8_t reason) /**************************************************************** - * Startup and background task processing + * Startup ****************************************************************/ -// Auto-generated code in out/compile_time_requests.c -extern void ctr_run_initfuncs(void); -extern void ctr_run_taskfuncs(void); - // Main loop of program void sched_main(void) { + extern void ctr_run_initfuncs(void); ctr_run_initfuncs(); int ret = setjmp(shutdown_jmp); if (ret) run_shutdown(ret); - for (;;) - ctr_run_taskfuncs(); + run_tasks(); } |