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)
+