[MULTITASKING] Processes

This commit is contained in:
Thomas Lovén 2016-12-16 19:22:33 +01:00
parent 5e8fbcbb78
commit 5ca2b6994a
8 changed files with 177 additions and 8 deletions

View File

@ -4,12 +4,19 @@
#include <mem.h>
#include <gdt.h>
#include <scheduler.h>
#include <thread.h>
#include <process.h>
void thread_function()
{
char *str = (char *)0x10000;
str[0] = (char)((unsigned int)'0' + get_current_process()->pid);
str[1] = (char)((unsigned int)'0' + get_current_thread()->tid);
str[3] = '-';
str[2] = '\0';
while(1)
{
debug("%d", get_current_thread()->tid);
debug((char *)0x10000);
schedule();
}
}
@ -28,12 +35,23 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
gdt_init();
scheduler_init();
process_t *p1 = process_spawn(0);
process_t *p2 = process_spawn(p1);
scheduler_insert(new_thread(thread_function));
scheduler_insert(new_thread(thread_function));
scheduler_insert(new_thread(thread_function));
scheduler_insert(new_thread(thread_function));
scheduler_insert(new_thread(thread_function));
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);
scheduler_insert(t1);
scheduler_insert(t2);
scheduler_insert(t3);
debug_info("BOOT COMPLETE\n");
schedule();

34
kernel/include/process.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
typedef struct process_st process_t;
#include <stdint.h>
#include <thread.h>
#include <mem.h>
typedef struct process_st
{
uint64_t pid;
uint64_t state;
uint64_t status;
struct process_st *parent;
page_table *P4;
LIST(struct process_st, children);
LIST(struct process_st, siblings);
LIST(thread_t, threads);
} process_t;
#define PROC_STATE_READY 1
#define PROC_STATE_RUNNING 2
#define PROC_STATE_ZOMBIE 3
#define PROC_STATE_DONE 4
#define process_alive(proc) ((proc)->state == PROC_STATE_READY || (proc)->state == PROC_STATE_RUNNING)
process_t *current_process;
#define get_current_process() (current_process)
#define set_current_process(proc) (current_process = (proc))
process_t *process_spawn(process_t *parent);
void process_attach(process_t *proc, thread_t *th);
void switch_process(process_t *proc);
void process_exit(process_t *proc, uint64_t status);
void process_free(process_t *proc);

View File

@ -1,6 +1,8 @@
#pragma once
typedef struct thread_st thread_t;
#include <stdint.h>
#include <list.h>
#include <process.h>
#define THREAD_STACK_SIZE 0x1000-sizeof(thread_t)
@ -9,6 +11,8 @@ typedef struct thread_st
uint64_t stack_pointer; // Top of the kernel stack for thread
uint64_t tid;
uint64_t state;
process_t *process;
LIST(struct thread_st, process_threads);
LIST(struct thread_st, ready_queue);
} thread_t;

View File

@ -63,6 +63,8 @@ registers_t *int_handler(registers_t *r)
#ifndef NDEBUG
thread_t *th = get_current_thread();
(void)th;
process_t *proc = get_current_process();
(void)proc;
asm("int_handler_breakpoint:");
#endif

View File

@ -22,7 +22,10 @@ page_table *vmm_new_P4()
void vmm_set_P4(page_table *P4)
{
write_cr3((uint64_t)P4);
if(P4)
write_cr3((uint64_t)P4);
else
write_cr3(V2P(&BootP4));
}
void vmm_free_P4(page_table *P4)
@ -145,6 +148,8 @@ registers_t *page_fault_handler(registers_t *r)
#ifndef NDEBUG
thread_t *th = get_current_thread();
(void)th;
process_t *proc = get_current_process();
(void)proc;
asm("page_fault_breakpoint:");
#endif
for(;;);

91
kernel/proc/process.c Normal file
View File

@ -0,0 +1,91 @@
#include <process.h>
#include <thread.h>
#include <debug.h>
#include <scheduler.h>
uint64_t pid = 1;
process_t *init_proc = 0;
process_t *process_spawn(process_t *parent)
{
process_t *proc = kcalloc(1, sizeof(process_t));
proc->pid = pid++;
proc->parent = parent;
proc->P4 = vmm_new_P4();
proc->state = PROC_STATE_READY;
LIST_INIT(proc, children);
LIST_INIT(proc, siblings);
LIST_INIT(proc, threads);
if(parent)
{
LIST_APPEND(parent->children, proc, siblings);
}
if(proc->pid == 1)
init_proc = proc;
return proc;
}
void process_attach(process_t *proc, thread_t *th)
{
LIST_APPEND(proc->threads, th, process_threads);
th->process = proc;
}
void switch_process(process_t *proc)
{
process_t *old = get_current_process();
if(old)
{
if(old == proc)
return;
if(old->state == PROC_STATE_RUNNING)
old->state = PROC_STATE_READY;
}
set_current_process(proc);
if(proc)
{
proc->state = PROC_STATE_RUNNING;
vmm_set_P4(proc->P4);
}
else
{
vmm_set_P4(0);
}
}
void process_exit(process_t *proc, uint64_t status)
{
proc->status = status;
LIST_FOREACH(proc->children, process_t, c, siblings)
{
// Make init process adopt orphaned children
LIST_REMOVE(proc->children, c, siblings);
c->parent = init_proc;
LIST_APPEND(init_proc->children, c, siblings);
}
proc->state = PROC_STATE_ZOMBIE;
}
void process_free(process_t *proc)
{
if(proc->state != PROC_STATE_ZOMBIE)
{
debug_error("Trying to free an unfinished process!\n");
for(;;);
}
LIST_FOREACH(proc->threads, thread_t, th, process_threads)
{
while(th->state == THREAD_STATE_RUNNING || th->state == THREAD_STATE_READY) schedule();
free_thread(th);
}
LIST_REMOVE(proc->parent->children, proc, siblings);
// Free page directory
vmm_free_P4(proc->P4);
// Free process structure
kfree(proc);
}

View File

@ -41,15 +41,25 @@ void scheduler()
thread_t *old = 0, *new = 0;
if((old = get_last_thread()))
{
if(old->state == THREAD_STATE_RUNNING)
if(old->state != THREAD_STATE_FINISHED && process_alive(old->process))
{
old->state = THREAD_STATE_READY;
scheduler_insert(old);
} else {
old->state = THREAD_STATE_FINISHED;
}
}
while(!(new = scheduler_next()));
if(!process_alive(new->process))
{
new->state = THREAD_STATE_FINISHED;
continue;
}
new->state = THREAD_STATE_RUNNING;
set_last_thread(new);
switch_process(new->process);
switch_thread(scheduler_th, new);
}
}
@ -60,6 +70,7 @@ void schedule()
thread_t *old = get_current_thread();
switch_process(0);
switch_thread(old, scheduler_th);
}

View File

@ -1,5 +1,6 @@
#include <thread.h>
#include <stdint.h>
#include <process.h>
#include <mem.h>
#include <list.h>
#include <debug.h>
@ -23,6 +24,7 @@ thread_t *new_thread(void (*func)(void))
th->stack_pointer = (uint64_t)&stack->RBP;
LIST_INIT(th, ready_queue);
LIST_INIT(th, process_threads);
return th;
}
@ -42,6 +44,8 @@ void free_thread(thread_t *th)
debug_error("Trying to free a live thread!\n");
for(;;);
}
if(!LIST_EMPTY(th->process_threads))
LIST_REMOVE(th->process->threads, th, process_threads);
thread_stack_t *stack = incptr(th, -offsetof(thread_stack_t, tcb));
kfree(stack);
}