[SMP] SMP synchronization and scheduling
This commit is contained in:
parent
8961ae33eb
commit
474914ab1e
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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++)
|
||||
|
@ -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
16
kernel/cpu/sync.S
Normal 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
|
@ -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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
6
kernel/include/sync.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
typedef uint64_t lock_t;
|
||||
|
||||
void spin_lock(lock_t *lock);
|
||||
void spin_unlock(lock_t *lock);
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
uint64_t tid = 1;
|
||||
|
||||
|
||||
thread_t *new_thread(void (*func)(void))
|
||||
{
|
||||
// Set up original stack of thread
|
||||
|
Loading…
x
Reference in New Issue
Block a user