Turn threads into processes by giving them unique page directories
This commit is contained in:
parent
0272605d36
commit
0e1cf97e19
@ -1,16 +1,19 @@
|
||||
#include <proc.h>
|
||||
#include <sched.h>
|
||||
#include <mittos/graphics.h>
|
||||
#include <memory.h>
|
||||
|
||||
extern gfx_context *term_fb;
|
||||
extern gfx_context kernel_fb;
|
||||
|
||||
int *position = (void *)0x20000;
|
||||
|
||||
void thread1()
|
||||
{
|
||||
int a = 1;
|
||||
gfx_context *ctx = framebuffer_make_subcontext(&kernel_fb, 700, 300, 100, 100);
|
||||
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);
|
||||
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));
|
||||
@ -24,7 +27,7 @@ void thread2()
|
||||
{
|
||||
int a = 0;
|
||||
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);
|
||||
sched_yield();
|
||||
|
||||
@ -34,9 +37,19 @@ void thread2()
|
||||
|
||||
void TEMP_test_scheduler()
|
||||
{
|
||||
struct thread *th1 = new_thread(thread1);
|
||||
struct process *th1 = new_process(thread1);
|
||||
scheduler_insert(th1);
|
||||
|
||||
struct thread *th2 = new_thread(thread2);
|
||||
struct process *th2 = new_process(thread2);
|
||||
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;
|
||||
}
|
@ -3,4 +3,9 @@
|
||||
.global load_idt
|
||||
load_idt:
|
||||
lidt [rdi]
|
||||
ret
|
||||
|
||||
.global write_cr3
|
||||
write_cr3:
|
||||
mov cr3, rdi
|
||||
ret
|
@ -4,4 +4,5 @@
|
||||
void cpu_init();
|
||||
|
||||
// cpu/registers.S
|
||||
void load_idt(void *);
|
||||
void load_idt(void *);
|
||||
void write_cr3(uint64_t);
|
@ -32,7 +32,7 @@
|
||||
extern uint64_t kernel_P4;
|
||||
|
||||
// memory/vmm.c
|
||||
void vmm_init();
|
||||
uint64_t new_P4();
|
||||
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);
|
||||
void vmm_clear_page(uint64_t P4, uint64_t addr, int free);
|
||||
|
@ -1,25 +1,26 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
struct thread
|
||||
struct process
|
||||
{
|
||||
struct thread *q_next;
|
||||
uint64_t tid;
|
||||
uint64_t pid;
|
||||
void *stack_ptr;
|
||||
uint64_t state;
|
||||
uint64_t P4;
|
||||
struct process *q_next;
|
||||
uint8_t stack[];
|
||||
};
|
||||
|
||||
// proc/thread.c
|
||||
extern struct thread *current_thread;
|
||||
// proc/process.c
|
||||
extern struct process *current_proc;
|
||||
|
||||
// proc/swtch.S
|
||||
void *switch_stack(void *out, void *in);
|
||||
|
||||
// proc/thread.c
|
||||
struct thread *new_thread(void (*function)(void));
|
||||
struct thread *thread();
|
||||
// proc/process.c
|
||||
struct process *new_process(void (*function)(void));
|
||||
struct process *proc();
|
||||
|
||||
// proc/scheduler.c
|
||||
void scheduler_insert(struct thread *new);
|
||||
void scheduler_insert(struct process *new);
|
||||
void start_scheduler();
|
@ -42,6 +42,13 @@ static int touch_P1(uint64_t P4, uint64_t addr, uint16_t flags)
|
||||
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)
|
||||
{
|
||||
if(P1_exists(P4, addr))
|
||||
|
39
src/kernel/proc/process.c
Normal file
39
src/kernel/proc/process.c
Normal 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;
|
||||
}
|
@ -1,21 +1,22 @@
|
||||
#include <proc.h>
|
||||
#include <cpu.h>
|
||||
|
||||
static struct {
|
||||
struct thread *first;
|
||||
struct thread *last;
|
||||
struct process *first;
|
||||
struct process *last;
|
||||
} 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))
|
||||
run_q.last = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void scheduler_insert(struct thread *new)
|
||||
void scheduler_insert(struct process *new)
|
||||
{
|
||||
if(run_q.last) {
|
||||
run_q.last->q_next = new;
|
||||
@ -30,28 +31,29 @@ void scheduler()
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
struct thread *new = 0;
|
||||
struct process *new = 0;
|
||||
while(!(new = scheduler_next()));
|
||||
|
||||
current_thread = new;
|
||||
switch_stack(&scheduler_thread->stack_ptr, &new->stack_ptr);
|
||||
current_proc = new;
|
||||
write_cr3(new->P4);
|
||||
switch_stack(&scheduler_proc->stack_ptr, &new->stack_ptr);
|
||||
|
||||
scheduler_insert(current_thread);
|
||||
current_thread = 0;
|
||||
scheduler_insert(current_proc);
|
||||
current_proc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
long k_sched_yield(long, long, long, long, long, long)
|
||||
{
|
||||
switch_stack(¤t_thread->stack_ptr, &scheduler_thread->stack_ptr);
|
||||
switch_stack(¤t_proc->stack_ptr, &scheduler_proc->stack_ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void start_scheduler()
|
||||
{
|
||||
scheduler_thread = new_thread(scheduler);
|
||||
scheduler_thread->tid = (uint64_t)-1;
|
||||
scheduler_proc = new_process(scheduler);
|
||||
scheduler_proc->pid = (uint64_t)-1;
|
||||
|
||||
uint64_t stack;
|
||||
switch_stack(&stack, &scheduler_thread->stack_ptr);
|
||||
switch_stack(&stack, &scheduler_proc->stack_ptr);
|
||||
}
|
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user