[SMP] SMP synchronization and scheduling

This commit is contained in:
Thomas Lovén 2016-11-18 09:36:01 +01:00
parent 8961ae33eb
commit 474914ab1e
12 changed files with 69 additions and 18 deletions

View File

@ -6,9 +6,13 @@
#include <vga.h>
#include <serial.h>
#include <registers.h>
#include <cpu.h>
lock_t debug_lock;
void debug_init()
{
spin_unlock(&debug_lock);
vga_init();
serial_init(PORT_COM1);
}

View File

@ -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");

View File

@ -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++)

View File

@ -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");
}

16
kernel/cpu/sync.S Normal file
View File

@ -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

View File

@ -20,6 +20,7 @@
#include <gdt.h>
#include <process.h>
#include <thread.h>
#include <scheduler.h>
typedef struct cpu_t
{
@ -51,6 +52,7 @@ void ap_init(cpu_t *cpu);
void trampoline();
void trampoline_GDT();
#endif

View File

@ -1,9 +1,10 @@
#pragma once
#include <string.h>
#include <int.h>
#include <sync.h>
#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);

View File

@ -4,12 +4,14 @@ typedef struct process_st process_t;
#include <thread.h>
#include <mem.h>
#include <cpu.h>
#include <sync.h>
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);

6
kernel/include/sync.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
typedef uint64_t lock_t;
void spin_lock(lock_t *lock);
void spin_unlock(lock_t *lock);

View File

@ -2,6 +2,7 @@
#include <thread.h>
#include <debug.h>
#include <scheduler.h>
#include <sync.h>
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)

View File

@ -3,6 +3,8 @@
#include <debug.h>
#include <sse.h>
#include <apic.h>
#include <sync.h>
#include <debug.h>
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;
}

View File

@ -8,7 +8,6 @@
uint64_t tid = 1;
thread_t *new_thread(void (*func)(void))
{
// Set up original stack of thread