Thread queueing/unqueuing

This commit is contained in:
Mark
2020-01-30 12:40:58 +02:00
parent 603a8064a3
commit fd374087b0
5 changed files with 103 additions and 69 deletions
+2 -1
View File
@@ -11,5 +11,6 @@ struct thread {
} data;
int pid;
struct thread *next;
struct thread *prev, *next;
};
+2
View File
@@ -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");
-6
View File
@@ -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"
+2 -2
View File
@@ -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
+97 -60
View File
@@ -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);
}