Commit 371b3931 authored by N1I1's avatar N1I1
Browse files

feat: proc create

parent 9391d089
No related merge requests found
Showing with 323 additions and 0 deletions
+323 -0
#ifndef PROC_H
#define PROC_H
#include "type.h"
#include "riscv.h"
#include "vm.h"
#define MAX_PROC_NUM 16
#define DEFAULT_PRIORITY 1
#define USER_STACK_TOP 0x7FFFFFFFF000UL
#define USER_STACK_SIZE PAGE_SIZE
#define USER_STACK_BASE (USER_STACK_TOP - USER_STACK_SIZE)
// jsut for test, may be changed
#define USER_CODE_BASE 0x1000000UL
#define USER_HEAP_BASE 0x2000000UL
#define PROC_KERNEL_STACK_BASE 0x90000000UL
#define KERNEL_STACK_SIZE PAGE_SIZE
#define KERNEL_STACK_PAGES 4
#define KERNEL_STACK_SHIFT 14
typedef struct Context {
uint64_t gpr[31];
uint64_t sepc;
uint64_t sstatus;
uint64_t satp;
uint64_t scause;
}Context;
typedef enum proc_state {
PROC_UNUSED,
PROC_EMBRYO,
PROC_SLEEPING,
PROC_RUNNABLE,
PROC_RUNNING,
PROC_ZOMBIE,
}State;
typedef struct ProcessControlBlock {
uint64_t *stack;
uint64_t *kstack;
uint64_t pid;
State state;
Context *context;
struct ProcessControlBlock *parent;
uint8_t priority;
pagetable_t *pagetable;
void* chan; // channel for sleep
uint64_t kstack_va;
}PCB;
void init_proc();
PCB* alloc_pcb();
void yield();
void fork();
void exit();
void wait();
void sleep(void* chan);
void wakeup(void* chan);
void schedule();
int alloc_pid();
void switch_context(Context** old_ctx, Context* new_ctx);
#endif
kernel/proc.c 0 → 100644
#include "include/proc.h"
#include "include/page.h"
#include "include/string.h"
#include "include/kmallo.h"
#include "include/printk.h"
static int next_pid = 1;
static PCB proc_table[MAX_PROC_NUM];
static PCB* current = NULL;
inline int alloc_pid() {
return next_pid++;
}
void init_proc() {
for(int i = 0; i < MAX_PROC_NUM; i++) {
proc_table[i].state = PROC_UNUSED;
proc_table[i].pid = 0;
}
}
PCB* alloc_pcb() {
for(int i = 0; i < MAX_PROC_NUM; i++) {
if(proc_table[i].state == PROC_UNUSED) {
PCB* p = &proc_table[i];
memset(p, 0, sizeof(PCB));
p->state = PROC_EMBRYO;
p->pid = alloc_pid();
p->priority = DEFAULT_PRIORITY;
p->kstack = (uint64_t*)alloc_page();
if (!p->kstack) {
goto fail;
}
p->stack = (uint64_t*)alloc_page();
if (!p->stack) {
goto fail;
}
p->kstack_va = PROC_KERNEL_STACK_BASE - (i <<
KERNEL_STACK_SHIFT);
if (p->kstack_va <= (uint64_t)p->kstack) {
goto fail;
}
p->pagetable = create_pagetable();
if(!p->pagetable) {
#ifdef DEBUG
printk(" Failed to create page table!\n");
#endif
goto fail;
}
if(map_page(p->pagetable,
USER_STACK_BASE,
(uint64_t)p->stack,
PTE_R | PTE_W | PTE_U) < 0) {
#ifdef DEBUG
printk(" Failed to map user stack!\n");
#endif
goto fail;
}
// map kernel stack
if(map_page(p->pagetable,
p->kstack_va,
(uint64_t)p->kstack,
PTE_R | PTE_W) < 0) {
#ifdef DEBUG
printk(" Failed to map kernel stack!\n");
#endif
goto fail;
}
p->context = (Context*)(p->kstack_va + KERNEL_STACK_SIZE -
sizeof(Context));
memset((void*)p->kstack, 0, PAGE_SIZE);
return p;
fail:
if(p->stack) free_page(p->stack);
if(p->kstack) free_page(p->kstack);
if(p->pagetable) free_pagetable(p->pagetable, 2);
memset(p, 0, sizeof(PCB));
p->state = PROC_UNUSED;
#ifdef DEBUG
printk("PCB %d allocation failed\n", i);
#endif
return NULL;
}
}
#ifdef DEBUG
printk("No free PCB available!\n");
#endif
return NULL;
}
void schedule() {
PCB* prev = current;
PCB* next = NULL;
while(1) {
for(int i = 0; i < MAX_PROC_NUM; i++) {
if(proc_table[i].state == PROC_RUNNABLE) {
next = &proc_table[i];
break;
}
}
if(next) {
next->state = PROC_RUNNING;
if(prev != next) {
Context** old_ctx = prev ? &prev->context : NULL;
current = next;
switch_context(old_ctx, next->context);
}
break;
}
}
}
void yield() {
if(current) {
current->state = PROC_RUNNABLE;
schedule();
}
}
void exit() {
if(current) {
current->state = PROC_ZOMBIE;
free_pagetable(current->pagetable, 2);
free_page(current->stack);
free_page(current->kstack);
// TODO: clean page table
schedule();
}
}
void fork() {
PCB* child = alloc_pcb();
if(!child) return;
if(current) {
child->parent = current;
child->chan = 0;
child->pagetable = copy_pagetable(current->pagetable);
if (!child->pagetable) {
free_page(child->stack);
free_page(child->kstack);
child->state = PROC_UNUSED;
return;
}
if(map_page(child->pagetable,
USER_STACK_BASE,
(uint64_t)child->stack,
PTE_R | PTE_W | PTE_U) < 0) {
free_pagetable(child->pagetable, 2);
free_page(child->stack);
free_page(child->kstack);
child->state = PROC_UNUSED;
return;
}
memcpy(child->stack, current->stack, PAGE_SIZE);
*(child->context) = *(current->context);
child->state = PROC_RUNNABLE;
}
}
void wait() {
if(!current) return;
for(int i = 0; i < MAX_PROC_NUM; i++) {
if(proc_table[i].parent == current &&
proc_table[i].state == PROC_ZOMBIE) {
proc_table[i].state = PROC_UNUSED;
return;
}
}
current->state = PROC_SLEEPING;
schedule();
}
void sleep(void* chan) {
if(!current)
return;
current->chan = chan;
current->state = PROC_SLEEPING;
schedule();
}
void wakeup(void* chan) {
for(int i = 0; i < MAX_PROC_NUM; i++) {
if(proc_table[i].state == PROC_SLEEPING &&
proc_table[i].chan == chan) {
proc_table[i].state = PROC_RUNNABLE;
proc_table[i].chan = 0;
}
}
}
#define MAP(x, f) f(x)
#define concat_temp(a, b) a ## b
#define concat(a, b) concat_temp(a, b)
#define REGS(f) \
f(1) f(3) f(4) f(5) f(6) f(7) f(8) \
f(9) f(10) f(11) f(12) f(13) f(14) f(15) f(16) \
f(17) f(18) f(19) f(20) f(21) f(22) f(23) f(24) \
f(25) f(26) f(27) f(28) f(29) f(30) f(31)
#define SAVE(n) sd concat(x, n), ((n-1)*8)(sp);
#define RESTORE(n) ld concat(x, n), ((n-1)*8)(sp);
.section .text
.global switch_context
# void switch_context(Context** old_ctx, Context* new_ctx)
# a0: old_ctx
# a1: new_ctx
switch_context:
addi sp, sp, -280
MAP(SAVE, REGS)
//
csrr t0, sepc
sd t0, 31*8(sp)
csrr t0, sstatus
sd t0, 32*8(sp)
csrr t0, satp
sd t0, 33*8(sp)
csrr t0, scause
sd t0, 34*8(sp)
sd sp, (a0)
mv sp, a1
ld t0, 31*8(sp)
csrw sepc, t0
ld t0, 32*8(sp)
csrw sstatus, t0
ld t0, 33*8(sp)
csrw satp, t0
ld t0, 34*8(sp)
csrw scause, t0
MAP(RESTORE, REGS)
sfence.vma zero, zero # flush TLB
addi sp, sp, 280
ret
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment