aboutsummaryrefslogtreecommitdiff
path: root/include/sys/schedule.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/sys/schedule.h')
-rw-r--r--include/sys/schedule.h142
1 files changed, 142 insertions, 0 deletions
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