We use a separate stack pointer for task code, which means we can
verify that it is in range in any interrupt handler. This adds checks
for the task stack (under #ifdef DEBUG) that run in ao_wakeup as well
as at every timer interrupt.
Signed-off-by: Keith Packard <keithp@keithp.com>
*/
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;
extern __xdata struct ao_task *__data ao_cur_task;
extern __data uint8_t ao_task_minimize_latency; /* Reduce IRQ latency */
+#ifndef HAS_ARCH_VALIDATE_CUR_STACK
+#define ao_validate_cur_stack()
+#endif
+
/*
ao_task.c
*/
#define HAS_SAMPLE_PROFILE 0
#endif
+#if DEBUG
+#define HAS_ARCH_VALIDATE_CUR_STACK 1
+
+static inline void
+ao_validate_cur_stack(void)
+{
+ uint8_t *psp;
+
+ asm("mrs %0,psp" : "=&r" (psp));
+ if (ao_cur_task &&
+ psp <= ao_cur_task->stack &&
+ psp >= ao_cur_task->stack - 256)
+ ao_panic(AO_PANIC_STACK);
+}
+#endif
+
#if !HAS_SAMPLE_PROFILE
#define HAS_ARCH_START_SCHEDULER 1
void stm_systick_isr(void)
{
+ ao_validate_cur_stack();
if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
++ao_tick_count;
#if HAS_TASK_QUEUE