Define stack by bottom and size

trunk
alexis 2023-02-03 19:48:22 -07:00
parent 2f00814666
commit 7201f2ff76
3 changed files with 43 additions and 15 deletions

View File

@ -32,9 +32,9 @@ struct utask_s;
typedef struct utask_s {
void (*func)(uintptr_t arg);
uintptr_t * stack_btm;
uintptr_t * stack_top;
char const * name; // Optional
uint8_t * stack; // May be adjusted on task start
size_t stack_size; // May be adjusted on task start
char const * name; // Optional
// -- Private - user need not initialize --
uintptr_t _arg;
@ -64,9 +64,9 @@ void utask_add(utask_t * task, uintptr_t arg);
// Run. Never returns.
void utask_run(void);
// Query task high water mark. Returns how many free words of stack are
// Query task high water mark. Returns how many free bytes of stack are
// untouched.
size_t utask_stack_free_words(utask_t * task);
size_t utask_stack_free_bytes(utask_t * task);
// Inhibit sleep. When this is called, a task_sleep_allow() must follow or the
// system will never go to sleep. May nest indefinitely. Preemption-safe, may
@ -83,11 +83,21 @@ void utask_stack_overflow_cb(utask_t * task);
// interrupts, override this and insert whatever sleep code you want to use.
void utask_sleep_cb(void);
#ifndef utask_yield
// These are defined in the architecture-specific header.
#if !UTASK_ARCH_INCLUDED
// Yield from this task. It will be run the next time around.
#define utask_yield()
// Define a stack for a task. The architecture-specific macro will ensure it
// is defined in the correct section, with the correct alignment, etc.
//
// Defined such that you may prepend `static` if desired.
//
// name: Name of the stack variable
// size: Size in bytes
#define utask_decl_stack(name, size)
#endif
// Yield until a condition is true.

View File

@ -6,6 +6,7 @@
#ifndef IN_UTASK_H
# error "Do not use utask_riscv.h by itself. Instead, include utask.h"
#endif
#define UTASK_ARCH_INCLUDED 1
// To get the fastest possible context switches, this implementation uses a
// special "micro-longjmp". Normally, setjmp/longjmp saves and restores an
@ -36,7 +37,7 @@ void utask_riscv_continue(void * tas);
void utask_riscv_yield(void * tas);
#define utask_start(task) do { \
(task)->_arch.sp = (uintptr_t) (task)->stack_top; \
(task)->_arch.sp = (uintptr_t) (task)->stack + (task)->stack_size; \
__sync_synchronize(); \
utask_riscv_start((task)->_arg, (task), &(task)->_arch); \
asm volatile("" ::: "memory", "cc", \
@ -69,4 +70,9 @@ void utask_riscv_yield(void * tas);
); \
} while (0)
#define utask_decl_stack(name, size) \
unsigned char __attribute__((aligned(4))) name[size]
#define utask_fixup_stack_len(len) ((((len) + 3) / 4) * 4)
#endif // !defined(UTASK_RISCV_H)

View File

@ -16,6 +16,13 @@ UTASK_ARCH_SPECIFIC_DEFS
static void _init_stack(utask_t * task);
static const uint8_t _canary[4] = {
(UTASK_STACK_CANARY) & 0xFF,
(UTASK_STACK_CANARY >> 8) & 0xFF,
(UTASK_STACK_CANARY >> 16) & 0xFF,
(UTASK_STACK_CANARY >> 24) & 0xFF,
};
void utask_add(utask_t * task, uintptr_t arg)
{
task->_next = task_list;
@ -43,7 +50,10 @@ void utask_run(void)
utask_start(task);
}
if (*task->stack_btm != UTASK_STACK_CANARY)
if (task->stack[0] != _canary[0]
|| task->stack[1] != _canary[1]
|| task->stack[2] != _canary[2]
|| task->stack[3] != _canary[3])
utask_stack_overflow_cb(task);
}
@ -74,21 +84,23 @@ void utask_sleep_cb(void)
{
}
size_t utask_stack_free_words(utask_t * task)
size_t utask_stack_free_bytes(utask_t * task)
{
for (uintptr_t * i = task->stack_btm; i < task->stack_top; i++)
for (size_t i = 0; i < task->stack_size; i++)
{
if (*i != UTASK_STACK_CANARY)
return i - task->stack_btm;
if (task->stack[i] != _canary[i & 3])
return i;
}
return task->stack_top - task->stack_btm;
return task->stack_size;
}
static void _init_stack(utask_t * task)
{
for (uintptr_t * i = task->stack_btm; i < task->stack_top; i++)
task->stack_size = utask_fixup_stack_len(task->stack_size);
for (size_t i = 0; i < task->stack_size; i++)
{
*i = UTASK_STACK_CANARY;
task->stack[i] = _canary[i & 3];
}
}