altos: Add debugging code to check for stack overflow
[fw/altos] / src / core / ao_task.c
index 32826114c4e5e855fa6e1159378c57321cb2c9ae..4011a36e06297f7423c85aabed8d6f2f2a0561d9 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#include "ao.h"
+#include <ao.h>
 
 #define AO_NO_TASK_INDEX       0xff
 
@@ -28,6 +28,20 @@ __xdata struct ao_task *__data ao_cur_task;
 ao_arch_task_globals
 #endif
 
+#define AO_CHECK_STACK 0
+
+#if AO_CHECK_STACK
+static uint8_t in_yield;
+
+static inline void ao_check_stack(void) {
+       uint8_t q;
+       if (!in_yield && ao_cur_task && &q < &ao_cur_task->stack[0])
+               ao_panic(AO_PANIC_STACK);
+}
+#else
+#define ao_check_stack()
+#endif
+
 void
 ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant
 {
@@ -68,6 +82,9 @@ ao_yield(void) ao_arch_naked_define
 
        ao_arch_isr_stack();
 
+#if CHECK_STACK
+       in_yield = 1;
+#endif
        /* Find a task to run. If there isn't any runnable task,
         * this loop will run forever, which is just fine
         */
@@ -97,17 +114,18 @@ ao_yield(void) ao_arch_naked_define
                        }
                }
        }
+#if CHECK_STACK
+       cli();
+       in_yield = 0;
+#endif
        ao_arch_restore_stack();
 }
 
 uint8_t
 ao_sleep(__xdata void *wchan)
 {
-       ao_arch_critical(
-               ao_cur_task->wchan = wchan;
-               );
+       ao_cur_task->wchan = wchan;
        ao_yield();
-       ao_cur_task->alarm = 0;
        if (ao_cur_task->wchan) {
                ao_cur_task->wchan = NULL;
                return 1;
@@ -120,6 +138,7 @@ ao_wakeup(__xdata void *wchan)
 {
        uint8_t i;
 
+       ao_check_stack();
        for (i = 0; i < ao_num_tasks; i++)
                if (ao_tasks[i]->wchan == wchan)
                        ao_tasks[i]->wchan = NULL;
@@ -135,6 +154,12 @@ ao_alarm(uint16_t delay)
                ao_cur_task->alarm = 1;
 }
 
+void
+ao_clear_alarm(void)
+{
+       ao_cur_task->alarm = 0;
+}
+
 void
 ao_exit(void)
 {
@@ -159,7 +184,7 @@ ao_task_info(void)
                task = ao_tasks[i];
                printf("%12s: wchan %04x\n",
                       task->name,
-                      (int16_t) task->wchan);
+                      (int) task->wchan);
        }
 }