Define stack by bottom and size
parent
2f00814666
commit
7201f2ff76
22
inc/utask.h
22
inc/utask.h
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
28
src/utask.c
28
src/utask.c
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue