From 576a32d92fd802768e773aa9807d195207a93c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Mon, 10 Jan 2022 23:31:23 +0100 Subject: [PATCH] Scheduler and multiple threads --- src/kernel/boot/TEMP-test_scheduler.c | 38 ++++++++++++++++++ src/kernel/boot/kmain.c | 5 +++ src/kernel/drivers/terminal/fbterm.c | 2 +- src/kernel/include/musl-glue.h | 6 ++- src/kernel/include/proc.h | 11 +++++- src/kernel/lib/musl-glue.c | 7 ++-- src/kernel/proc/scheduler.c | 57 +++++++++++++++++++++++++++ src/kernel/proc/thread.c | 42 ++------------------ 8 files changed, 123 insertions(+), 45 deletions(-) create mode 100644 src/kernel/boot/TEMP-test_scheduler.c create mode 100644 src/kernel/proc/scheduler.c diff --git a/src/kernel/boot/TEMP-test_scheduler.c b/src/kernel/boot/TEMP-test_scheduler.c new file mode 100644 index 0000000..63772c7 --- /dev/null +++ b/src/kernel/boot/TEMP-test_scheduler.c @@ -0,0 +1,38 @@ +#include +#include +#include + +extern gfx_context *term_fb; +void drawCharacter(gfx_context *ctx, uint64_t x, uint64_t y, uint32_t clr_fg, uint32_t clr_bg, char c); + + + +void thread1() +{ + int a = 0; + while(1) { + drawCharacter(term_fb, 0, 0, RGB(255,0,0), RGB(0,0,0), '0'+(a++%10)); + flip(term_fb); + sched_yield(); + } +} + +void thread2() +{ + int a = 0; + while(1) { + drawCharacter(term_fb, 10, 10, RGB(0,0,255), RGB(0,0,0), 'A'+(a++%10)); + flip(term_fb); + sched_yield(); + } +} + + +void TEMP_test_scheduler() +{ + struct thread *th1 = new_thread(thread1); + scheduler_insert(th1); + + struct thread *th2 = new_thread(thread2); + scheduler_insert(th2); +} \ No newline at end of file diff --git a/src/kernel/boot/kmain.c b/src/kernel/boot/kmain.c index a5890af..74486b6 100644 --- a/src/kernel/boot/kmain.c +++ b/src/kernel/boot/kmain.c @@ -9,6 +9,7 @@ #include #include +void TEMP_test_scheduler(); struct kernel_boot_data_st kernel_boot_data; @@ -30,6 +31,10 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data) debug_info("Boot complete\n"); + + TEMP_test_scheduler(); + + start_scheduler(); PANIC("End of kernel function!"); diff --git a/src/kernel/drivers/terminal/fbterm.c b/src/kernel/drivers/terminal/fbterm.c index b3d41e5..4e0a578 100644 --- a/src/kernel/drivers/terminal/fbterm.c +++ b/src/kernel/drivers/terminal/fbterm.c @@ -105,7 +105,7 @@ char font[95][16] = { gfx_context *term_fb; static int setup = 0; -static void drawCharacter(gfx_context *ctx, uint64_t x, uint64_t y, uint32_t clr_fg, uint32_t clr_bg, char c) +void drawCharacter(gfx_context *ctx, uint64_t x, uint64_t y, uint32_t clr_fg, uint32_t clr_bg, char c) { char *chr = c ? font[(int)c-0x20]: font[0]; diff --git a/src/kernel/include/musl-glue.h b/src/kernel/include/musl-glue.h index 128e5e6..c2569f0 100644 --- a/src/kernel/include/musl-glue.h +++ b/src/kernel/include/musl-glue.h @@ -3,6 +3,7 @@ #define SYSCALL_BRK 12 #define SYSCALL_IOCTL 16 #define SYSCALL_WRITEV 20 +#define SYSCALL_SCHED_YIELD 24 typedef long (*syscall_handler)(long, long, long, long, long, long); @@ -14,4 +15,7 @@ long k_ioctl(long fd, long cmd, long arg3, long, long, long); long k_writev(long fd, long iov, long iovcnt, long, long, long); // memory/kbrk.c -long k_brk(long brk, long, long, long, long, long); \ No newline at end of file +long k_brk(long brk, long, long, long, long, long); + +// proc/scheduler.c +long k_sched_yield(long, long, long, long, long, long); \ No newline at end of file diff --git a/src/kernel/include/proc.h b/src/kernel/include/proc.h index b1455a2..09a0367 100644 --- a/src/kernel/include/proc.h +++ b/src/kernel/include/proc.h @@ -5,12 +5,21 @@ struct thread { struct thread *q_next; uint64_t tid; - void *stack; + void *stack_ptr; uint64_t state; + uint8_t stack[]; }; +// proc/thread.c +extern struct thread *current_thread; + // proc/swtch.S void *switch_stack(void *out, void *in); // proc/thread.c +struct thread *new_thread(void (*function)(void)); +struct thread *thread(); + +// proc/scheduler.c +void scheduler_insert(struct thread *new); void start_scheduler(); \ No newline at end of file diff --git a/src/kernel/lib/musl-glue.c b/src/kernel/lib/musl-glue.c index b845831..50f6f15 100644 --- a/src/kernel/lib/musl-glue.c +++ b/src/kernel/lib/musl-glue.c @@ -2,9 +2,10 @@ #include syscall_handler syscall_handlers[440] = { - [SYSCALL_BRK] = &k_brk, - [SYSCALL_IOCTL] = &k_ioctl, - [SYSCALL_WRITEV] = &k_writev, + [SYSCALL_BRK] = k_brk, + [SYSCALL_IOCTL] = k_ioctl, + [SYSCALL_WRITEV] = k_writev, + [SYSCALL_SCHED_YIELD] = k_sched_yield, }; syscall_handler set_syscall_handler(long num, syscall_handler handler) diff --git a/src/kernel/proc/scheduler.c b/src/kernel/proc/scheduler.c new file mode 100644 index 0000000..e195e14 --- /dev/null +++ b/src/kernel/proc/scheduler.c @@ -0,0 +1,57 @@ +#include + +static struct { + struct thread *first; + struct thread *last; +} run_q = {0,0}; + +static struct thread *scheduler_thread; + +static struct thread *scheduler_next() +{ + struct thread *ret = run_q.first; + if(run_q.first && !(run_q.first = run_q.first->q_next)) + run_q.last = 0; + return ret; +} + +void scheduler_insert(struct thread *new) +{ + if(run_q.last) { + run_q.last->q_next = new; + run_q.last = new; + } else { + run_q.first = run_q.last = new; + } + new->q_next = 0; +} + +void scheduler() +{ + while(1) + { + struct thread *new = 0; + while(!(new = scheduler_next())); + + current_thread = new; + switch_stack(&scheduler_thread->stack_ptr, &new->stack_ptr); + + scheduler_insert(current_thread); + current_thread = 0; + } +} + +long k_sched_yield(long, long, long, long, long, long) +{ + switch_stack(¤t_thread->stack_ptr, &scheduler_thread->stack_ptr); + return 0; +} + +void start_scheduler() +{ + scheduler_thread = new_thread(scheduler); + scheduler_thread->tid = (uint64_t)-1; + + uint64_t stack; + switch_stack(&stack, &scheduler_thread->stack_ptr); +} \ No newline at end of file diff --git a/src/kernel/proc/thread.c b/src/kernel/proc/thread.c index 9fd9cf6..bf1a81a 100644 --- a/src/kernel/proc/thread.c +++ b/src/kernel/proc/thread.c @@ -16,18 +16,16 @@ struct swtch_stack static uint64_t next_tid = 1; -static struct thread *run_queue = 0; -static struct thread *current_thread; -static struct thread *scheduler_thread; +struct thread *current_thread; struct thread *new_thread(void (*function)(void)) { struct thread *th = P2V(pmm_calloc()); th->tid = next_tid++; - th->stack = incptr(th, PAGE_SIZE - sizeof(struct swtch_stack)); + th->stack_ptr = incptr(th, PAGE_SIZE - sizeof(struct swtch_stack)); th->q_next = 0; - struct swtch_stack *stck = th->stack; + struct swtch_stack *stck = th->stack_ptr; stck->RBP = (uint64_t)&stck->RBP2; stck->ret = (uint64_t)function; @@ -37,38 +35,4 @@ struct thread *new_thread(void (*function)(void)) struct thread *thread() { return current_thread; -} - -void k_yield() -{ - switch_stack(¤t_thread->stack, &scheduler_thread->stack); -} - -struct thread *scheduler_next() -{ - if(!current_thread) return run_queue; - return current_thread->q_next; -} - -void scheduler() -{ - while(1) - { - struct thread *new = 0; - while(!(new = scheduler_next())); - - current_thread = new; - switch_stack(&scheduler_thread->stack, &new->stack); - - current_thread = 0; - } -} - -void start_scheduler() -{ - scheduler_thread = new_thread(scheduler); - scheduler_thread->tid = (uint64_t)-1; - - uint64_t stack; - switch_stack(&stack, &scheduler_thread->stack); } \ No newline at end of file