aboutsummaryrefslogtreecommitdiff
path: root/src/sys/schedule.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/schedule.c')
-rw-r--r--src/sys/schedule.c128
1 files changed, 126 insertions, 2 deletions
diff --git a/src/sys/schedule.c b/src/sys/schedule.c
index 3aca0ff..e20abe7 100644
--- a/src/sys/schedule.c
+++ b/src/sys/schedule.c
@@ -1,18 +1,55 @@
#include <globals.h>
+#include <drivers/uart.h>
#include <sys/schedule.h>
+#include <util/mutex.h>
+
+void loop(void);
+void cleanup(void);
void init_scheduler(void)
{
// Set rthread to usrloopthread - an infinitely running thread so that the pointer will never be null
usrloopthread.pc = (void*)loop;
- usrloopthread.sp = 0x0FCC;
- usrloopthread.sp_base = 0x1000;
+ usrloopthread.sp = (void*)0x5FC8;
+ *(unsigned long**)usrloopthread.sp = (unsigned long*)loop;
+ usrloopthread.sp_base = (void*)0x6000;
usrloopthread.mptr = 0;
usrloopthread.pid = -1;
usrloopthread.priority = -1;
usrloopthread.status = THREAD_READY;
scheduler.rthread = &usrloopthread;
// Initialize Rotating Buffers
+ struct ThreadQueues* tq;
+ for (int i = 0; i < PRIORITIES; i++) {
+ tq = &scheduler.thread_queues[i];
+ struct ThreadRotBuffer* trb = &tq->ready;
+ trb->roffset = 0;
+ trb->woffset = 0;
+ for (int j = 0; j < TQUEUE_MAX; j++)
+ trb->queue[j] = 0;
+ trb = &tq->mwait;
+ trb->roffset = 0;
+ trb->woffset = 0;
+ for (int j = 0; j < TQUEUE_MAX; j++)
+ trb->queue[j] = 0;
+ trb = &tq->swait;
+ trb->roffset = 0;
+ trb->woffset = 0;
+ for (int j = 0; j < TQUEUE_MAX; j++)
+ trb->queue[j] = 0;
+ trb = &tq->finish;
+ trb->roffset = 0;
+ trb->woffset = 0;
+ for (int j = 0; j < TQUEUE_MAX; j++)
+ trb->queue[j] = 0;
+ trb = &tq->serror;
+ trb->roffset = 0;
+ trb->woffset = 0;
+ for (int j = 0; j < TQUEUE_MAX; j++)
+ trb->queue[j] = 0;
+ }
+ // Initialize nextpid
+ nextpid = SCHED_PID + 1;
}
void loop(void)
@@ -20,3 +57,90 @@ void loop(void)
while(1)
asm volatile ("wfe");
}
+
+void* get_stack(void)
+{
+ for (int i = 0; i < MAX_THREADS; i++) {
+ if (stacks_table[i] == 0) {
+ stacks_table[i] = 1;
+ return (void*)0x20000000 - STACK_SIZE*i;
+ }
+ }
+ return 0;
+}
+
+void add_thread(void* pc, void* arg, unsigned char priority)
+{
+ void* sp = get_stack();
+ struct Thread* thread = (struct Thread*)malloca(sizeof(struct Thread), 4);
+ thread->pc = pc;
+ if (sp) {
+ thread->sp_base = sp;
+ unsigned long* argp = sp;
+ argp -= 1;
+ *argp = (unsigned long)arg; // Set r0 to the argument
+ argp -= 13;
+ *(unsigned long**)argp = (unsigned long*)cleanup; // Set lr to the cleanup function
+ thread->sp = (void*)argp;
+ thread->status = THREAD_READY;
+ } else {
+ thread->sp_base = 0;
+ thread->sp = 0;
+ thread->status = THREAD_SERROR;
+ }
+ thread->mptr = (void*)0;
+ thread->pid = nextpid++;
+ thread->priority = priority % PRIORITIES;
+ thread->preempt = 0;
+ // Add Thread* to scheduler's appropriate buffer
+ struct ThreadQueues* tq = &scheduler.thread_queues[thread->priority];
+ struct ThreadRotBuffer* trb;
+ if (thread->status == THREAD_SERROR) {
+ trb = &tq->serror;
+ } else {
+ trb = &tq->ready;
+ }
+ trb->queue[trb->woffset++] = thread;
+ trb->woffset %= TQUEUE_MAX;
+}
+
+void uart_scheduler(void)
+{
+ uart_string("Scheduler Info\n==============\nCurrent\n");
+ uart_hex((unsigned long)scheduler.rthread);
+ uart_char(' ');
+ memshow32((void*)scheduler.rthread, 6);
+ struct ThreadQueues* tq;
+ for(int p = 0; p < PRIORITIES; p++) {
+ uart_string("Priority ");
+ uart_10(p);
+ uart_char('\n');
+ tq = &scheduler.thread_queues[p];
+ struct ThreadRotBuffer* trb;
+ trb = &tq->ready;
+ for(int i = 0; i < TQUEUE_CNT; i++) {
+ if (trb->roffset == trb->woffset) {
+ trb += 1;
+ continue;
+ }
+ uart_string("Queue ");
+ uart_10(i);
+ uart_char('\n');
+ unsigned long roffset = trb->roffset;
+ while (roffset != trb->woffset) {
+ uart_hex((unsigned long)&trb->queue[roffset]);
+ uart_char(' ');
+ memshow32((void*)trb->queue[roffset], 6);
+ memshow32((void*)trb->queue[roffset]->sp, 14);
+ roffset++;
+ roffset %= TQUEUE_MAX;
+ }
+ trb += 1;
+ }
+ }
+ uart_string("==============\n");
+}
+
+void cleanup(void)
+{
+}