Mercurial > lcfOS
changeset 25:d3c4bf3720a3
Beginning of multitasking
author | windel |
---|---|
date | Tue, 27 Dec 2011 13:31:38 +0100 |
parents | d8627924d40d |
children | dcce92b1efbc |
files | cos/Makefile cos/hello/Makefile cos/hello/hello.c cos/hello/hello.ld cos/kernel/asmcode.asm cos/kernel/kernel.h cos/kernel/malloc.c cos/kernel/task.c cos/kernel/timer.c cos/utils/bin2c.py |
diffstat | 10 files changed, 198 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/cos/Makefile Fri Dec 02 14:00:02 2011 +0100 +++ b/cos/Makefile Tue Dec 27 13:31:38 2011 +0100 @@ -26,6 +26,7 @@ kernel/keyboard.o \ kernel/klib.o \ kernel/malloc.o \ + kernel/task.o \ kernel/timer.o lcfosc.bin: $(CRT0) $(OBJECTS) linker.ld
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/hello/Makefile Tue Dec 27 13:31:38 2011 +0100 @@ -0,0 +1,19 @@ +# vim: set noexpandtab: + +CFLAGS = -m64 \ + -nostdinc \ + -nostdlib \ + -nostartfiles \ + -mno-red-zone \ + -fno-builtin \ + -mcmodel=large \ + -Wall \ + -Wextra \ + -Werror + +hello.bin: hello.o + ld -T hello.ld -s -o hello.bin hello.o + +%.o: %.c + gcc $(CFLAGS) -o $@ -c $< +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/hello/hello.c Tue Dec 27 13:31:38 2011 +0100 @@ -0,0 +1,14 @@ +/* Uber simple program that prints directly to video memory */ + +int main() +{ + unsigned char * const screen = (unsigned char*)0xB8000; + screen[0] = 'H'; + screen[2] = 'o'; + screen[4] = 'i'; + while (1==1) + { + } + return 0; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/hello/hello.ld Tue Dec 27 13:31:38 2011 +0100 @@ -0,0 +1,24 @@ +OUTPUT_FORMAT("binary") + +SECTIONS { + .text 0x100000: + { + *(.text) + } + + .rodata ALIGN (4096) : + { + *(.rodata) + } + + .data ALIGN (4096) : + { + *(.data) + } + + .bss : { + *(.bss) + } + +} +
--- a/cos/kernel/asmcode.asm Fri Dec 02 14:00:02 2011 +0100 +++ b/cos/kernel/asmcode.asm Tue Dec 27 13:31:38 2011 +0100 @@ -10,6 +10,12 @@ cli hlt +; Function to read the current instruction pointer value: +global read_rip +read_rip: + pop rax + jmp rax + global magicBochsBreak magicBochsBreak: xchg bx, bx
--- a/cos/kernel/kernel.h Fri Dec 02 14:00:02 2011 +0100 +++ b/cos/kernel/kernel.h Tue Dec 27 13:31:38 2011 +0100 @@ -31,6 +31,11 @@ void* kmalloc(uint64_t size); void kfree(void* ptr); +// task related functions: +void initialize_tasking(); +void new_task(); +void task_scheduler(); + // STDout funcs: void printf(const char* fmt, ... ); void memset(void* ptr, uint32_t value, uint32_t num); @@ -56,6 +61,7 @@ // ASM helper: void loadIDT(void); +uint64_t read_rip(); // Panic exit: void halt(void); @@ -78,7 +84,6 @@ // Memory functions: void mappage(uint64_t address); -int querymode(void); void loadPageTable(void* tableAddress); // Variable argument list things: @@ -122,14 +127,17 @@ unsigned char screendata[80*25]; // All chars in the console! } console_t; -typedef struct { - uint32_t esp; - uint32_t ss; +typedef struct task_t { + struct task_t* next; uint32_t kstack; uint32_t ustack; - uint32_t cr3; - uint32_t number; + uint64_t cr3; + uint64_t rip; + uint64_t rsp; + uint64_t rbp; + + uint32_t pid; uint32_t parent; uint32_t owner; uint32_t groups; @@ -140,7 +148,7 @@ char naam[32]; console_t *console; -} programma_t; +} task_t; #endif
--- a/cos/kernel/malloc.c Fri Dec 02 14:00:02 2011 +0100 +++ b/cos/kernel/malloc.c Tue Dec 27 13:31:38 2011 +0100 @@ -74,3 +74,4 @@ kernel_heap->state = HEAP_FREE; kernel_heap->size = HEAP_SIZE - sizeof(heap_t); } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/kernel/task.c Tue Dec 27 13:31:38 2011 +0100 @@ -0,0 +1,98 @@ +#include "kernel.h" + +// global variables: +uint64_t next_pid = 1; +task_t* ready_queue = 0; // Head of the queue of tasks. +task_t* current_task = 0; // Pointer to the currently running task. + +void initialize_tasking() +{ + next_pid = 1; +} + +/* + Create a new task with some loaded program. +*/ +void new_task() +{ + task_t* newtask = (task_t*)kmalloc(sizeof(task_t)); + newtask->pid = next_pid++; + newtask->rip = 0; + newtask->next = 0; + + // Append the new task to the ready queue: + task_t* task = ready_queue; + while (task->next != 0) + { + task = task->next; + } + task->next = newtask; +} + +/* Fork function duplicates the process */ +void task_fork() +{ + asm volatile("cli"); // Disable interrupts + task_t *parent_task = current_task; + + // Create new task: + task_t *new_task = (task_t*)kmalloc(sizeof(task_t)); + new_task->pid = next_pid++; + new_task->rsp = 0; + new_task->rbp = 0; + new_task->rip = 0; + new_task->next = 0; + + // Append to the queue: + task_t* tmp_task = ready_queue; + while (tmp_task->next != 0) + { + tmp_task = tmp_task->next; + } + tmp_task->next = new_task; + + uint64_t rip = read_rip(); + + if (current_task == parent_task) + { + uint64_t rbp, rsp; + asm volatile("mov %%rsp, %0" : "=r"(rsp)); + asm volatile("mov %%rbp, %0" : "=r"(rbp)); + new_task->rip = rip; + + asm volatile("sti"); + } +} + +/* + Scheduler function that switches tasks for multi tasking. +*/ +void task_scheduler() +{ + if (current_task == 0) + { + return; + } + + uint64_t rbp, rsp, rip; + + rip = 0; + rsp = 0; + rbp = 0; + + current_task->rip = rip; // TODO + current_task->rsp = rsp; + current_task->rbp = rbp; + + // Select next task: + current_task = current_task->next; + if (current_task == 0) + { + current_task = ready_queue; + } + + // Set the rbp, rsp and rip registers: + rsp = current_task->rsp; + rbp = current_task->rbp; +} +
--- a/cos/kernel/timer.c Fri Dec 02 14:00:02 2011 +0100 +++ b/cos/kernel/timer.c Tue Dec 27 13:31:38 2011 +0100 @@ -5,6 +5,7 @@ void timerDriverUpdate() { ticks++; + task_scheduler(); } uint64_t getTimeMS()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/utils/bin2c.py Tue Dec 27 13:31:38 2011 +0100 @@ -0,0 +1,19 @@ +#!/usr/bin/python + +import sys +print(sys.argv) +if len(sys.argv) < 2: + print('Usage: {0} binfile [headerfile]'.format(sys.argv[0])) + sys.exit(-1) + +with open(sys.argv[1], 'rb') as f: + data = f.read() + +s = ', '.join(hex(b) for b in data) +output = 'unsigned char[] data = {{{0}}};'.format(s) +if len(sys.argv) < 3: + print(output) +else: + with open(sys.argv[2], 'w') as f: + f.write(output) +