diff options
Diffstat (limited to 'include/sys')
-rw-r--r-- | include/sys/core.h | 10 | ||||
-rw-r--r-- | include/sys/schedule.h | 142 |
2 files changed, 142 insertions, 10 deletions
diff --git a/include/sys/core.h b/include/sys/core.h index 2d611b3..361ffb1 100644 --- a/include/sys/core.h +++ b/include/sys/core.h @@ -21,16 +21,6 @@ static inline void delay(unsigned long cycles) : "=r"(cycles): [cycles]"0"(cycles) : "cc"); } -static inline void preserveregs(void) -{ - asm volatile("push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11}"); -} - -static inline void restoreregs(void) -{ - asm volatile("pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11}"); -} - static inline void* getsp(void) { void* out; diff --git a/include/sys/schedule.h b/include/sys/schedule.h new file mode 100644 index 0000000..cced851 --- /dev/null +++ b/include/sys/schedule.h @@ -0,0 +1,142 @@ +#ifndef SYS_SCHEDULE_H +#define SYS_SCHEDULE_H +#include <cpu.h> +#include <lib/mem.h> +#include <lib/ll.h> +#include <sys/core.h> + +enum ThreadStatus { + THREAD_READY, + THREAD_WAITING, + THREAD_WAITING_FOR_MUTEX, + THREAD_STACK_ERROR, + THREAD_RUNNING, + THREAD_FINISHED, +}; + +struct ThreadData { + unsigned short status; + void* mutex_waiting; + unsigned long pid; + unsigned char priority; +}; + +struct Thread { + struct ThreadData data; + void (*thread)(void); + void* stack; + void* stack_base; +}; + +#define MAX_THREADS 0x100 +#define STACK_SIZE 0x1000 +#define PRIORITIES 6 +struct Scheduler { + struct LL tlist[PRIORITIES]; + struct LL* rthread_ll; +}; + +#ifndef SYS_SCHEDULE_C +#define SYS_SCHEDULE_C +extern struct Scheduler scheduler; +#endif + +void init_scheduler(void); +void add_thread(void (*thread_fxn)(void), unsigned char priority); +void schedule(void); +void remove_running_thread(void); + +static inline void preserveregs(struct Thread* thread) +{ + // Preserve current stack pointer + void* sp = getsp(); + // Get current mode + unsigned long mode = getmode(); + // Set supervisor mode - "User mode" + setsvc(); + void* ssp = getsp(); + // Move stack to reserved register area + setsp(thread->stack_base - 0x1000 + 16*4); + // Push registers to the stack + asm volatile ("push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}"); + // Restore stack to previous + setsp(ssp); + // Restore mode + setmode(mode); + // Restore current stack pointer + setsp(sp); +} + +static inline void preservestack(struct Thread* thread) +{ + // Get current mode + unsigned long mode = getmode(); + // Set supervisor mode - "User mode" + setsvc(); + // Store the stack pointer + void* ssp = getsp(); + thread->stack = ssp; + // Restore mode + setmode(mode); +} + +static inline void restoreregs(struct Thread* thread) +{ + // Preserve current stack pointer + void* sp = getsp(); + // Get current mode + unsigned long mode = getmode(); + // Set supervisor mode - "User mode" + setsvc(); + void* ssp = getsp(); + // Move stack to reserved register area + setsp(thread->stack_base - 0x1000 + 16*4 - 14*4); + // Restore registers on the stack + asm volatile ("pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}"); + // Restore stack to previous + setsp(ssp); + // Restore mode + setmode(mode); + // Restore current stack pointer + setsp(sp); +} + +static inline void restorestack(struct Thread* thread) +{ + // Get current mode + unsigned long mode = getmode(); + // Set supervisor mode - "User mode" + setsvc(); + // Set stack pointer to thread's stack pointer + asm volatile("mov sp, %0" :: "r"(thread->stack)); + // Restore mode + setmode(mode); +} + +static inline void preservesysstack(unsigned long* sp) +{ + if (*sp == 0) { + unsigned long mode = getmode(); + setsvc(); + *sp = (unsigned long)getsp(); + setmode(mode); + } +} + +static inline void restoresysstack(unsigned long* sp) +{ + if (*sp) { + unsigned long mode = getmode(); + setsvc(); + setsp((void*)*sp); + setmode(mode); + *sp = 0; + } +} + +static inline void preservepc(struct Thread* t) +{ + asm volatile ("mov %0, lr" : "=r"(t->thread)); +} + +#endif |