From a7e0bb5eb661cfde31c383d605cb9cb8ca568bc7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 17:04:59 -0700 Subject: altos: Block interrupts while waking tasks sleeping on timers. Interrupts may not be blocked in the timer ISR, but they need to be while walking the pending timer list and moving tasks back to the run queue. Signed-off-by: Keith Packard --- src/kernel/ao_task.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/kernel/ao_task.c') diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index e430edc6..03d69caa 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -165,13 +165,14 @@ ao_task_check_alarm(uint16_t tick) { struct ao_task *alarm, *next; - ao_list_for_each_entry_safe(alarm, next, &alarm_queue, struct ao_task, alarm_queue) { - if ((int16_t) (tick - alarm->alarm) < 0) - break; - alarm->alarm = 0; - ao_task_from_alarm_queue(alarm); - ao_task_to_run_queue(alarm); - } + ao_arch_critical( + ao_list_for_each_entry_safe(alarm, next, &alarm_queue, struct ao_task, alarm_queue) { + if ((int16_t) (tick - alarm->alarm) < 0) + break; + alarm->alarm = 0; + ao_task_from_alarm_queue(alarm); + ao_task_to_run_queue(alarm); + }); } void -- cgit v1.2.3 From 974aaf73cbb720f1b1183cc239001528b6c7a5b9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 17:09:00 -0700 Subject: altos: Move comment in ao_sleep_for next to related code The comment got moved to the wrong place Signed-off-by: Keith Packard --- src/kernel/ao_task.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/kernel/ao_task.c') diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index 03d69caa..5b8f9356 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -460,11 +460,11 @@ ao_sleep_for(__xdata void *wchan, uint16_t timeout) if (timeout) { #if HAS_TASK_QUEUE uint32_t flags; + flags = ao_arch_irqsave(); +#endif /* Make sure we sleep *at least* delay ticks, which means adding * one to account for the fact that we may be close to the next tick */ - flags = ao_arch_irqsave(); -#endif if (!(ao_cur_task->alarm = ao_time() + timeout + 1)) ao_cur_task->alarm = 1; #if HAS_TASK_QUEUE -- cgit v1.2.3 From 658d8be170f9aea683fe62b68368736a177411a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 17:03:34 -0700 Subject: altos: Add debug check for irq block when editing task queues List manipulation operations are not atomic, so interrupts need to be blocked while changing them. Signed-off-by: Keith Packard --- src/kernel/ao_task.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/kernel/ao_task.c') diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index 5b8f9356..47352fc1 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -54,6 +54,12 @@ static inline void ao_check_stack(void) { #define ao_check_stack() #endif +#if DEBUG +#define ao_task_irq_check() ao_arch_irq_check() +#else +#define ao_task_irq_check() +#endif + #if HAS_TASK_QUEUE #define SLEEP_HASH_SIZE 17 @@ -65,6 +71,7 @@ static struct ao_list sleep_queue[SLEEP_HASH_SIZE]; static void ao_task_to_run_queue(struct ao_task *task) { + ao_task_irq_check(); ao_list_del(&task->queue); ao_list_append(&task->queue, &run_queue); } @@ -78,6 +85,7 @@ ao_task_sleep_queue(void *wchan) static void ao_task_to_sleep_queue(struct ao_task *task, void *wchan) { + ao_task_irq_check(); ao_list_del(&task->queue); ao_list_append(&task->queue, ao_task_sleep_queue(wchan)); } @@ -122,6 +130,7 @@ static void ao_task_to_alarm_queue(struct ao_task *task) { struct ao_task *alarm; + ao_task_irq_check(); ao_list_for_each_entry(alarm, &alarm_queue, struct ao_task, alarm_queue) { if ((int16_t) (alarm->alarm - task->alarm) >= 0) { ao_list_insert(&task->alarm_queue, alarm->alarm_queue.prev); @@ -138,6 +147,7 @@ ao_task_to_alarm_queue(struct ao_task *task) static void ao_task_from_alarm_queue(struct ao_task *task) { + ao_task_irq_check(); ao_list_del(&task->alarm_queue); if (ao_list_is_empty(&alarm_queue)) ao_task_alarm_tick = 0; @@ -156,6 +166,7 @@ ao_task_init_queue(struct ao_task *task) static void ao_task_exit_queue(struct ao_task *task) { + ao_task_irq_check(); ao_list_del(&task->queue); ao_list_del(&task->alarm_queue); } -- cgit v1.2.3 From 349a63aeed6cdeb89bf18c7b2e2c40782c79cc00 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Jun 2016 12:52:37 -0700 Subject: altos: Make ao_delay(0) not wait forever ao_delay() is implemented on top of ao_sleep_for, and ao_sleep_for uses the timeout value of 0 to indicate an infinite timeout. Calls to ao_delay for 0 ticks would unintentionally hit this case and end up waiting forever.x Signed-off-by: Keith Packard --- src/kernel/ao_task.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/kernel/ao_task.c') diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index 47352fc1..0a790ccd 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -504,6 +504,8 @@ static __xdata uint8_t ao_forever; void ao_delay(uint16_t ticks) { + if (!ticks) + ticks = 1; ao_sleep_for(&ao_forever, ticks); } -- cgit v1.2.3 From a35424cd48205af89ba023db979959dc75b06706 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Jun 2016 12:54:31 -0700 Subject: altos: Make task list output more useful Add the timeout value and task id Signed-off-by: Keith Packard --- src/kernel/ao_task.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/kernel/ao_task.c') diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index 0a790ccd..cf0b58ed 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -537,12 +537,15 @@ ao_task_info(void) { uint8_t i; __xdata struct ao_task *task; + uint16_t now = ao_time(); for (i = 0; i < ao_num_tasks; i++) { task = ao_tasks[i]; - printf("%12s: wchan %04x\n", - task->name, - (int) task->wchan); + printf("%2d: wchan %08x alarm %5d %s\n", + task->task_id, + (int) task->wchan, + task->alarm ? (int16_t) (task->alarm - now) : 9999, + task->name); } #if HAS_TASK_QUEUE && DEBUG ao_task_validate(); -- cgit v1.2.3