From 474914ab1ef3e8ca7f9a8c8f2268e55cea575ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Fri, 18 Nov 2016 09:36:01 +0100 Subject: [PATCH] [SMP] SMP synchronization and scheduling --- kernel/boot/debug.c | 4 ++++ kernel/boot/kmain.c | 26 ++++++++++++-------------- kernel/cpu/cpu.c | 4 +++- kernel/cpu/smp.c | 2 ++ kernel/cpu/sync.S | 16 ++++++++++++++++ kernel/include/cpu.h | 2 ++ kernel/include/debug.h | 5 ++++- kernel/include/process.h | 2 ++ kernel/include/sync.h | 6 ++++++ kernel/proc/process.c | 7 +++++++ kernel/proc/scheduler.c | 12 +++++++++++- kernel/proc/thread.c | 1 - 12 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 kernel/cpu/sync.S create mode 100644 kernel/include/sync.h diff --git a/kernel/boot/debug.c b/kernel/boot/debug.c index 6d28e3f..4c6146a 100644 --- a/kernel/boot/debug.c +++ b/kernel/boot/debug.c @@ -6,9 +6,13 @@ #include #include #include +#include + +lock_t debug_lock; void debug_init() { + spin_unlock(&debug_lock); vga_init(); serial_init(PORT_COM1); } diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index 15c7253..0ac14c7 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -30,25 +30,23 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data) pit_init(); process_t *p1 = process_spawn(0); - process_t *p2 = process_spawn(p1); thread_t *t1 = new_thread(thread_function); - thread_t *t2 = new_thread(thread_function); - thread_t *t3 = new_thread(thread_function); - process_attach(p1, t1); - process_attach(p2, t2); - process_attach(p1, t3); - - vmm_set_page(p1->P4, 0x10000, pmm_alloc(), PAGE_PRESENT | PAGE_WRITE); - vmm_set_page(p2->P4, 0x10000, pmm_alloc(), PAGE_PRESENT | PAGE_WRITE); - - vmm_p4_memcpy(p1->P4, (void *)0x10000, 0, "Hello, 1", 9); - vmm_p4_memcpy(p2->P4, (void *)0x10000, 0, "Hello, 2", 9); scheduler_insert(t1); - scheduler_insert(t2); - scheduler_insert(t3); + t1 = new_thread(thread_function); + process_attach(p1, t1); + scheduler_insert(t1); + t1 = new_thread(thread_function); + process_attach(p1, t1); + scheduler_insert(t1); + t1 = new_thread(thread_function); + process_attach(p1, t1); + scheduler_insert(t1); + t1 = new_thread(thread_function); + process_attach(p1, t1); + scheduler_insert(t1); asm("sti"); debug_info("BOOT COMPLETE\n"); diff --git a/kernel/cpu/cpu.c b/kernel/cpu/cpu.c index 1b1a186..0e7bf34 100644 --- a/kernel/cpu/cpu.c +++ b/kernel/cpu/cpu.c @@ -62,7 +62,9 @@ void cpu_init() all_ap_started = 1; vmm_set_page(0, TRAMPOLINE_ADDR, 0, 0); - pmm_free(page); + // Keep the GDT mapped for now + /* vmm_set_page(0, TRAMPOLINE_GDT, 0, 0); */ + /* pmm_free(page); */ debug_info("CPU - Status\n"); for(unsigned int i = 0; i < num_cpu; i++) diff --git a/kernel/cpu/smp.c b/kernel/cpu/smp.c index 36f4905..7ffd948 100644 --- a/kernel/cpu/smp.c +++ b/kernel/cpu/smp.c @@ -49,5 +49,7 @@ void ap_start() while(!all_ap_started); cpu_t *cpu = get_cpu(); debug_ok("STARTED CPU:%x\n", cpu->id); + schedule(); + debug_error("PANIC: SMP - This line should be unreachable\n"); for(;;)asm("hlt"); } diff --git a/kernel/cpu/sync.S b/kernel/cpu/sync.S new file mode 100644 index 0000000..741fc32 --- /dev/null +++ b/kernel/cpu/sync.S @@ -0,0 +1,16 @@ +.intel_syntax noprefix +.global spin_lock +spin_lock: + mov rdx, rdi + mov rax, 0x0 + mov rcx, 0x1 +.retry: + xor rax, rax + lock cmpxchg [rdx], cl + jnz .retry + ret + +.global spin_unlock +spin_unlock: + movq [rdi], 0x0 + ret diff --git a/kernel/include/cpu.h b/kernel/include/cpu.h index f2053b9..ca17aa7 100644 --- a/kernel/include/cpu.h +++ b/kernel/include/cpu.h @@ -20,6 +20,7 @@ #include #include #include +#include typedef struct cpu_t { @@ -51,6 +52,7 @@ void ap_init(cpu_t *cpu); void trampoline(); void trampoline_GDT(); + #endif diff --git a/kernel/include/debug.h b/kernel/include/debug.h index dd7a35b..6a61f52 100644 --- a/kernel/include/debug.h +++ b/kernel/include/debug.h @@ -1,9 +1,10 @@ #pragma once #include #include +#include #ifndef NDEBUG - #define debug(...) debug_printf(__VA_ARGS__) + #define debug(...) ({spin_lock(&debug_lock);debug_printf(__VA_ARGS__);spin_unlock(&debug_lock);}) #else #define debug(...) ((void)0) #endif @@ -12,6 +13,8 @@ #define debug_warning(...) do{debug("[WARNING] ");debug(__VA_ARGS__);}while(0) #define debug_error(...) do{debug("[ERROR] ");debug(__VA_ARGS__);}while(0) +extern lock_t debug_lock; + void debug_init(); void debug_putch(char c); void debug_putsn(char *s, size_t n); diff --git a/kernel/include/process.h b/kernel/include/process.h index 8e4d5c0..a6ef285 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -4,12 +4,14 @@ typedef struct process_st process_t; #include #include #include +#include typedef struct process_st { uint64_t pid; uint64_t state; uint64_t status; + lock_t lock; struct process_st *parent; page_table *P4; LIST(struct process_st, children); diff --git a/kernel/include/sync.h b/kernel/include/sync.h new file mode 100644 index 0000000..f2ee429 --- /dev/null +++ b/kernel/include/sync.h @@ -0,0 +1,6 @@ +#pragma once + +typedef uint64_t lock_t; + +void spin_lock(lock_t *lock); +void spin_unlock(lock_t *lock); diff --git a/kernel/proc/process.c b/kernel/proc/process.c index 8c4905c..94d8071 100644 --- a/kernel/proc/process.c +++ b/kernel/proc/process.c @@ -2,6 +2,7 @@ #include #include #include +#include uint64_t pid = 1; process_t *init_proc = 0; @@ -20,7 +21,9 @@ process_t *process_spawn(process_t *parent) if(parent) { + spin_lock(&parent->lock); LIST_APPEND(parent->children, proc, siblings); + spin_unlock(&parent->lock); } if(proc->pid == 1) @@ -31,8 +34,10 @@ process_t *process_spawn(process_t *parent) void process_attach(process_t *proc, thread_t *th) { + spin_lock(&proc->lock); LIST_APPEND(proc->threads, th, process_threads); th->process = proc; + spin_unlock(&proc->lock); } void switch_process(process_t *proc) @@ -60,6 +65,7 @@ void switch_process(process_t *proc) void process_exit(process_t *proc, uint64_t status) { + spin_lock(&proc->lock); proc->status = status; LIST_FOREACH(proc->children, process_t, c, siblings) { @@ -69,6 +75,7 @@ void process_exit(process_t *proc, uint64_t status) LIST_APPEND(init_proc->children, c, siblings); } proc->state = PROC_STATE_ZOMBIE; + spin_unlock(&proc->lock); } void process_free(process_t *proc) diff --git a/kernel/proc/scheduler.c b/kernel/proc/scheduler.c index 0dcf8c0..f404316 100644 --- a/kernel/proc/scheduler.c +++ b/kernel/proc/scheduler.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include LIST(thread_t, ready_queue); @@ -11,29 +13,37 @@ thread_t *scheduler_th; #define set_last_thread(new) (get_cpu()->last_thread = (new)) int scheduler_started = 0; +lock_t scheduler_lock = 0; void scheduler_insert(thread_t *th) { // Append thread to the ready queue and prepare it for running + spin_lock(&scheduler_lock); LIST_APPEND(ready_queue, th, ready_queue); th->state = THREAD_STATE_READY; + spin_unlock(&scheduler_lock); } void scheduler_remove(thread_t *th) { // Remove thread from the ready queue + spin_lock(&scheduler_lock); LIST_REMOVE(ready_queue, th, ready_queue); + spin_unlock(&scheduler_lock); } thread_t *scheduler_next() { // Get the next thread from the ready queue + spin_lock(&scheduler_lock); if(!LIST_EMPTY(ready_queue)) { thread_t *th = LIST_FIRST(ready_queue); - scheduler_remove(th); + LIST_REMOVE(ready_queue, th, ready_queue); + spin_unlock(&scheduler_lock); return th; } + spin_unlock(&scheduler_lock); return 0; } diff --git a/kernel/proc/thread.c b/kernel/proc/thread.c index 3c92103..0fe1635 100644 --- a/kernel/proc/thread.c +++ b/kernel/proc/thread.c @@ -8,7 +8,6 @@ uint64_t tid = 1; - thread_t *new_thread(void (*func)(void)) { // Set up original stack of thread