diff --git a/include/sys/thread.h b/include/sys/thread.h index 3df4b43..34114ab 100644 --- a/include/sys/thread.h +++ b/include/sys/thread.h @@ -11,5 +11,6 @@ struct thread { } data; int pid; - struct thread *next; + + struct thread *prev, *next; }; diff --git a/sys/amd64/hw/exc.c b/sys/amd64/hw/exc.c index 32f821e..8a6ec17 100644 --- a/sys/amd64/hw/exc.c +++ b/sys/amd64/hw/exc.c @@ -97,6 +97,8 @@ void amd64_exception(struct amd64_exception_frame *frame) { kfatal(" Backtrace:\n"); kfatal("0: %p <%s + %04x>\n", frame->rip, sym_name, frame->rip - sym_base); debug_backtrace(frame->rbp, 1, 10); + } else { + kfatal("%rip is in unknown location\n"); } panic("Exception without resolution\n"); diff --git a/sys/amd64/hw/irq0.S b/sys/amd64/hw/irq0.S index a176cce..71f8a7c 100644 --- a/sys/amd64/hw/irq0.S +++ b/sys/amd64/hw/irq0.S @@ -12,9 +12,6 @@ amd64_irq0_early: popq %rax iretq -_addr: .quad 0xFFFFFF00000B8000 -_msg0: .string "CPU stopped!\n" - amd64_irq0: cli @@ -50,6 +47,3 @@ amd64_irq2_counting: irq_eoi_lapic 0 pop %rax iretq - -_fmt0: - .string "RSP = %p\n" diff --git a/sys/amd64/sched_s.S b/sys/amd64/sched_s.S index cea9d49..0d4117f 100644 --- a/sys/amd64/sched_s.S +++ b/sys/amd64/sched_s.S @@ -15,11 +15,10 @@ context_enter: .global context_switch_first .global context_switch_to +.type context_switch_to, %function context_switch_to: // %rdi - new thread // %rsi - from - cli - pushq %r15 pushq %r14 pushq %r13 @@ -42,3 +41,4 @@ context_switch_first: popq %r15 ret +.size context_switch_to, . - context_switch_to diff --git a/sys/sched.c b/sys/sched.c index 3c05c91..c24622d 100644 --- a/sys/sched.c +++ b/sys/sched.c @@ -3,6 +3,7 @@ #include "sys/amd64/hw/idt.h" #include "sys/assert.h" #include "sys/thread.h" +#include "sys/debug.h" #include "sys/mm.h" // Enter a newly-created task @@ -14,12 +15,58 @@ extern void context_switch_first(struct thread *thr); void yield(void); +//// Thread queueing + +static struct thread *queue_head = NULL; +static struct thread *thread_current = NULL; +static struct thread thread_idle = {0}; + +void sched_queue(struct thread *thr) { + if (queue_head) { + struct thread *queue_tail = queue_head->prev; + + queue_tail->next = thr; + thr->prev = queue_tail; + queue_head->prev = thr; + thr->next = queue_head; + } else { + thr->next = thr; + thr->prev = thr; + + queue_head = thr; + } +} + +void sched_unqueue(struct thread *thr) { + struct thread *prev = thr->prev; + struct thread *next = thr->next; + + if (next == thr) { + queue_head = NULL; + thread_current = &thread_idle; + context_switch_to(&thread_idle, thr); + return; + } + + if (thr == queue_head) { + queue_head = next; + } + + next->prev = prev; + prev->next = next; + + thr->prev = NULL; + thr->next = NULL; + + if (thr == thread_current) { + thread_current = next; + context_switch_to(next, thr); + } +} + //// -static struct thread sched_threads[3] = {0}; -static int cntr = 0; - -static void init_thread(struct thread *thr, void *(*entry)(void *)) { +static void init_thread(struct thread *thr, void *(*entry)(void *), void *arg) { uintptr_t stack_pages = amd64_phys_alloc_page(); _assert(stack_pages != MM_NADDR); @@ -59,7 +106,7 @@ static void init_thread(struct thread *thr, void *(*entry)(void *)) { // rsi *--stack = 0; // rdi - *--stack = 0x12345678; + *--stack = (uintptr_t) arg; // rax *--stack = 0; @@ -96,77 +143,67 @@ static void init_thread(struct thread *thr, void *(*entry)(void *)) { thr->data.rsp0 = (uintptr_t) stack; } +static void *idle(void *arg) { + while (1) { + asm volatile ("hlt"); + } + return 0; +} + static void *t0(void *arg) { - size_t count = 0; - int v = 0; + size_t cntr = 0; while (1) { - if ((count % 100000) == 0) { - if (v) { - *(uint16_t *) MM_VIRTUALIZE(0xB8000) = 'A' | 0x700; - } else { - *(uint16_t *) MM_VIRTUALIZE(0xB8000) = 0; - } - v = !v; + for (size_t i = 0; i < 10000000; ++i); + + *((uint16_t *) MM_VIRTUALIZE(0xB8000 + (uint64_t) arg * 2)) ^= 'A'; + ++cntr; + + if (cntr == 50 * (((uint64_t) arg) +1)) { + kdebug("[%d] Død\n", arg); + sched_unqueue(thread_current); } - - ++count; - } - return 0; -} - -static void *t1(void *arg) { - size_t count = 0; - int v = 0; - while (1) { - if ((count % 100000) == 0) { - if (v) { - *(uint16_t *) MM_VIRTUALIZE(0xB8002) = 'B' | 0x700; - } else { - *(uint16_t *) MM_VIRTUALIZE(0xB8002) = 0; - } - v = !v; - } - - ++count; - } - return 0; -} - -static void *t2(void *arg) { - size_t count = 0; - int v = 0; - while (1) { - if ((count % 100000) == 0) { - if (v) { - *(uint16_t *) MM_VIRTUALIZE(0xB8004) = 'C' | 0x700; - } else { - *(uint16_t *) MM_VIRTUALIZE(0xB8004) = 0; - } - v = !v; - } - - ++count; } return 0; } void yield(void) { - struct thread *from = &sched_threads[cntr]; + struct thread *from = thread_current; + struct thread *to; - cntr = (cntr + 1) % 3; + if (from && from->next) { + to = from->next; + } else if (queue_head) { + to = queue_head; + } else { + to = &thread_idle; + } - struct thread *next = &sched_threads[cntr]; - context_switch_to(next, from); + thread_current = to; + context_switch_to(to, from); } +static struct thread t_n[3] = {0}; + void sched_init(void) { - init_thread(&sched_threads[0], t0); - init_thread(&sched_threads[1], t1); - init_thread(&sched_threads[2], t2); + init_thread(&t_n[0], t0, (void *) 0); + init_thread(&t_n[1], t0, (void *) 1); + init_thread(&t_n[2], t0, (void *) 2); + init_thread(&thread_idle, idle, NULL); + + thread_idle.pid = -1; + + t_n[0].pid = 1; + t_n[1].pid = 2; + t_n[2].pid = 3; + + sched_queue(&t_n[0]); + sched_queue(&t_n[1]); + sched_queue(&t_n[2]); } void sched_enter(void) { extern void amd64_irq0(void); amd64_idt_set(0, 32, (uintptr_t) amd64_irq0, 0x08, IDT_FLG_P | IDT_FLG_R0 | IDT_FLG_INT32); - context_switch_first(&sched_threads[0]); + thread_current = queue_head; + context_switch_first(thread_current); }