Turn threads into processes by giving them unique page directories

This commit is contained in:
Thomas Lovén 2022-01-14 22:01:28 +01:00
parent 0272605d36
commit 0e1cf97e19
9 changed files with 98 additions and 68 deletions

View File

@ -1,16 +1,19 @@
#include <proc.h> #include <proc.h>
#include <sched.h> #include <sched.h>
#include <mittos/graphics.h> #include <mittos/graphics.h>
#include <memory.h>
extern gfx_context *term_fb; extern gfx_context *term_fb;
extern gfx_context kernel_fb; extern gfx_context kernel_fb;
int *position = (void *)0x20000;
void thread1() void thread1()
{ {
int a = 1; int a = 1;
gfx_context *ctx = framebuffer_make_subcontext(&kernel_fb, 700, 300, 100, 100); gfx_context *ctx = framebuffer_make_subcontext(&kernel_fb, 700, 300, 100, 100);
while(1) { while(1) {
putCharacter(term_fb, 0, 0, RGB(255,255,0), RGB(0,0,0), '0'+(a++%10)); putCharacter(term_fb, *position, *position, RGB(255,255,0), RGB(0,0,0), '0'+(a++%10));
flip(term_fb); flip(term_fb);
draw_line(ctx, 0, 100, 50, ((a-1)%100), RGB(0,0,0)); draw_line(ctx, 0, 100, 50, ((a-1)%100), RGB(0,0,0));
draw_line(ctx, 0, 100, 50, (a%100), RGB(255,0,0)); draw_line(ctx, 0, 100, 50, (a%100), RGB(255,0,0));
@ -24,7 +27,7 @@ void thread2()
{ {
int a = 0; int a = 0;
while(1) { while(1) {
putCharacter(term_fb, 10, 10, RGB(0,255,255), RGB(0,0,0), 'A'+(a++%10)); putCharacter(term_fb, *position, *position, RGB(0,255,255), RGB(0,0,0), 'A'+(a++%10));
flip(term_fb); flip(term_fb);
sched_yield(); sched_yield();
@ -34,9 +37,19 @@ void thread2()
void TEMP_test_scheduler() void TEMP_test_scheduler()
{ {
struct thread *th1 = new_thread(thread1); struct process *th1 = new_process(thread1);
scheduler_insert(th1); scheduler_insert(th1);
struct thread *th2 = new_thread(thread2); struct process *th2 = new_process(thread2);
scheduler_insert(th2); scheduler_insert(th2);
uint64_t p1 = pmm_alloc();
uint64_t p2 = pmm_alloc();
vmm_set_page(th1->P4, 0x20000, p1, PAGE_PRESENT);
vmm_set_page(th2->P4, 0x20000, p2, PAGE_PRESENT);
// Write different values into the position variable for the two processes
int *a = P2V(p1);
*a = 20;
a = P2V(p2);
*a = 70;
} }

View File

@ -4,3 +4,8 @@
load_idt: load_idt:
lidt [rdi] lidt [rdi]
ret ret
.global write_cr3
write_cr3:
mov cr3, rdi
ret

View File

@ -5,3 +5,4 @@ void cpu_init();
// cpu/registers.S // cpu/registers.S
void load_idt(void *); void load_idt(void *);
void write_cr3(uint64_t);

View File

@ -32,7 +32,7 @@
extern uint64_t kernel_P4; extern uint64_t kernel_P4;
// memory/vmm.c // memory/vmm.c
void vmm_init(); uint64_t new_P4();
uint64_t vmm_get_page(uint64_t P4, uint64_t addr); uint64_t vmm_get_page(uint64_t P4, uint64_t addr);
int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags); int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags);
void vmm_clear_page(uint64_t P4, uint64_t addr, int free); void vmm_clear_page(uint64_t P4, uint64_t addr, int free);

View File

@ -1,25 +1,26 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
struct thread struct process
{ {
struct thread *q_next; uint64_t pid;
uint64_t tid;
void *stack_ptr; void *stack_ptr;
uint64_t state; uint64_t state;
uint64_t P4;
struct process *q_next;
uint8_t stack[]; uint8_t stack[];
}; };
// proc/thread.c // proc/process.c
extern struct thread *current_thread; extern struct process *current_proc;
// proc/swtch.S // proc/swtch.S
void *switch_stack(void *out, void *in); void *switch_stack(void *out, void *in);
// proc/thread.c // proc/process.c
struct thread *new_thread(void (*function)(void)); struct process *new_process(void (*function)(void));
struct thread *thread(); struct process *proc();
// proc/scheduler.c // proc/scheduler.c
void scheduler_insert(struct thread *new); void scheduler_insert(struct process *new);
void start_scheduler(); void start_scheduler();

View File

@ -42,6 +42,13 @@ static int touch_P1(uint64_t P4, uint64_t addr, uint16_t flags)
return 0; return 0;
} }
uint64_t new_P4()
{
uint64_t p4 = pmm_alloc();
memcpy(P2V(p4), (void *)kernel_P4, PAGE_SIZE);
return p4;
}
uint64_t vmm_get_page(uint64_t P4, uint64_t addr) uint64_t vmm_get_page(uint64_t P4, uint64_t addr)
{ {
if(P1_exists(P4, addr)) if(P1_exists(P4, addr))

39
src/kernel/proc/process.c Normal file
View File

@ -0,0 +1,39 @@
#include <stdint.h>
#include <proc.h>
#include <memory.h>
struct swtch_stack
{
uint64_t RBP;
uint64_t RBX;
uint64_t R12;
uint64_t R13;
uint64_t R14;
uint64_t R15;
uint64_t RBP2;
uint64_t ret;
};
static uint64_t next_pid = 1;
struct process *current_proc;
struct process *new_process(void (*function)(void))
{
struct process *p = P2V(pmm_calloc());
p->pid = next_pid++;
p->stack_ptr = incptr(p, PAGE_SIZE - sizeof(struct swtch_stack));
p->q_next = 0;
p->P4 = new_P4();
struct swtch_stack *stck = p->stack_ptr;
stck->RBP = (uint64_t)&stck->RBP2;
stck->ret = (uint64_t)function;
return p;
}
struct process *proc()
{
return current_proc;
}

View File

@ -1,21 +1,22 @@
#include <proc.h> #include <proc.h>
#include <cpu.h>
static struct { static struct {
struct thread *first; struct process *first;
struct thread *last; struct process *last;
} run_q = {0,0}; } run_q = {0,0};
static struct thread *scheduler_thread; static struct process *scheduler_proc;
static struct thread *scheduler_next() static struct process *scheduler_next()
{ {
struct thread *ret = run_q.first; struct process *ret = run_q.first;
if(run_q.first && !(run_q.first = run_q.first->q_next)) if(run_q.first && !(run_q.first = run_q.first->q_next))
run_q.last = 0; run_q.last = 0;
return ret; return ret;
} }
void scheduler_insert(struct thread *new) void scheduler_insert(struct process *new)
{ {
if(run_q.last) { if(run_q.last) {
run_q.last->q_next = new; run_q.last->q_next = new;
@ -30,28 +31,29 @@ void scheduler()
{ {
while(1) while(1)
{ {
struct thread *new = 0; struct process *new = 0;
while(!(new = scheduler_next())); while(!(new = scheduler_next()));
current_thread = new; current_proc = new;
switch_stack(&scheduler_thread->stack_ptr, &new->stack_ptr); write_cr3(new->P4);
switch_stack(&scheduler_proc->stack_ptr, &new->stack_ptr);
scheduler_insert(current_thread); scheduler_insert(current_proc);
current_thread = 0; current_proc = 0;
} }
} }
long k_sched_yield(long, long, long, long, long, long) long k_sched_yield(long, long, long, long, long, long)
{ {
switch_stack(&current_thread->stack_ptr, &scheduler_thread->stack_ptr); switch_stack(&current_proc->stack_ptr, &scheduler_proc->stack_ptr);
return 0; return 0;
} }
void start_scheduler() void start_scheduler()
{ {
scheduler_thread = new_thread(scheduler); scheduler_proc = new_process(scheduler);
scheduler_thread->tid = (uint64_t)-1; scheduler_proc->pid = (uint64_t)-1;
uint64_t stack; uint64_t stack;
switch_stack(&stack, &scheduler_thread->stack_ptr); switch_stack(&stack, &scheduler_proc->stack_ptr);
} }

View File

@ -1,38 +0,0 @@
#include <stdint.h>
#include <proc.h>
#include <memory.h>
struct swtch_stack
{
uint64_t RBP;
uint64_t RBX;
uint64_t R12;
uint64_t R13;
uint64_t R14;
uint64_t R15;
uint64_t RBP2;
uint64_t ret;
};
static uint64_t next_tid = 1;
struct thread *current_thread;
struct thread *new_thread(void (*function)(void))
{
struct thread *th = P2V(pmm_calloc());
th->tid = next_tid++;
th->stack_ptr = incptr(th, PAGE_SIZE - sizeof(struct swtch_stack));
th->q_next = 0;
struct swtch_stack *stck = th->stack_ptr;
stck->RBP = (uint64_t)&stck->RBP2;
stck->ret = (uint64_t)function;
return th;
}
struct thread *thread()
{
return current_thread;
}