*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#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
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);
}
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));
}
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);
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;
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);
}
{
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
*/
if (ao_cur_task->wchan == NULL)
ao_task_to_run_queue(ao_cur_task);
- ao_cur_task = NULL;
for (;;) {
ao_arch_memory_barrier();
if (!ao_list_is_empty(&run_queue))
void
ao_wakeup(__xdata void *wchan) __reentrant
{
+ ao_validate_cur_stack();
#if HAS_TASK_QUEUE
struct ao_task *sleep, *next;
struct ao_list *sleep_queue;
}
ao_arch_irqrestore(flags);
#else
+ {
uint8_t i;
for (i = 0; i < ao_num_tasks; i++)
if (ao_tasks[i]->wchan == wchan)
ao_tasks[i]->wchan = NULL;
+ }
#endif
ao_check_stack();
}
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
void
ao_delay(uint16_t ticks)
{
+ if (!ticks)
+ ticks = 1;
ao_sleep_for(&ao_forever, ticks);
}
{
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();