summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--DESIGN2
-rw-r--r--src/Makefile6
-rw-r--r--src/drivers/driver.c2
-rw-r--r--src/kernel/kernel.c3
-rw-r--r--src/kernel/tasks.c76
-rw-r--r--src/kernel/tasks.h64
6 files changed, 150 insertions, 3 deletions
diff --git a/DESIGN b/DESIGN
index 3b76393..8b67f8f 100644
--- a/DESIGN
+++ b/DESIGN
@@ -16,7 +16,7 @@ minimum.
Use only as much assembly as needed, if necessary call a stub function
from C doing the things we would normally do in inlined assembly.
-Make sure it compiles with every ANSI C99 compiler (gcc, clang, tcc, ...).
+Make sure it compiles with every ANSI C99 compiler (gcc, clang, tcc, pcc, ...).
Use only what is needed, nothing fancy.
Try to compile as often as possible with different compilers on different
host systems.
diff --git a/src/Makefile b/src/Makefile
index bcb0da7..c256605 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -33,10 +33,11 @@ kernel.bin: kernel.elf
kernel.sym: kernel.elf
$(OBJCOPY) --only-keep-debug kernel.elf kernel.sym
-kernel.elf: kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext.o kernel/serial.o hardware/port.o hardware/port_asm.o hardware/interrupts.o hardware/interrupts_asm.o hardware/pci.o drivers/driver.o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o drivers/video/vga.o drivers/video/vga_font.o gui/widget.o gui/composite_widget.o gui/window.o gui/desktop.o gui/text_widget.o libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o
+kernel.elf: kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext.o kernel/serial.o kernel/tasks.o hardware/port.o hardware/port_asm.o hardware/interrupts.o hardware/interrupts_asm.o hardware/pci.o drivers/driver.o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o drivers/video/vga.o drivers/video/vga_font.o gui/widget.o gui/composite_widget.o gui/window.o gui/desktop.o gui/text_widget.o libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o
$(LD) -o kernel.elf -N -n -Ttext 0x8800 --oformat elf32-i386 \
kernel/kernel.o kernel/kernel_asm.o \
kernel/console.o kernel/vgatext.o kernel/serial.o \
+ kernel/tasks.o \
hardware/port.o hardware/port_asm.o \
hardware/interrupts.o hardware/interrupts_asm.o \
hardware/pci.o \
@@ -71,6 +72,9 @@ kernel/vgatext.o: kernel/vgatext.c kernel/vgatext.h
kernel/serial.o: kernel/serial.c kernel/serial.h
$(CC) $(CFLAGS) -c -o kernel/serial.o kernel/serial.c
+kernel/tasks.o: kernel/tasks.c kernel/tasks.h
+ $(CC) $(CFLAGS) -c -o kernel/tasks.o kernel/tasks.c
+
hardware/interrupts.o: hardware/interrupts.c hardware/interrupts.h
$(CC) $(CFLAGS) -c -o hardware/interrupts.o hardware/interrupts.c
diff --git a/src/drivers/driver.c b/src/drivers/driver.c
index d0a2f5d..8c20676 100644
--- a/src/drivers/driver.c
+++ b/src/drivers/driver.c
@@ -13,7 +13,7 @@ void driver_manager_init( driver_manager_t *manager )
void driver_manager_add_driver( driver_manager_t *manager, driver_t *driver )
{
if( manager->nof_drivers >= MAX_NOF_DRIVERS - 1 ) {
- kernel_panic( "Allocating more than %d drivers.. increase kernel constant", MAX_NOF_DRIVERS );
+ kernel_panic( "Allocating more than %d drivers.. increase kernel constant MAX_NOF_DRIVERS", MAX_NOF_DRIVERS );
}
manager->driver[manager->nof_drivers] = driver;
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index 55dd6f9..9a9f32e 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -128,6 +128,9 @@ void kernel_main( void )
// graphical one..
puts( "Enabling interrupt handing now.." );
+
+ // TODO: if enabling tasks, this could be our really last execution
+ // in the main kernel thread
interrupts_enable( );
puts( "Running.." );
diff --git a/src/kernel/tasks.c b/src/kernel/tasks.c
new file mode 100644
index 0000000..164409a
--- /dev/null
+++ b/src/kernel/tasks.c
@@ -0,0 +1,76 @@
+#include "tasks.h"
+
+#include "kernel.h"
+#include "string.h"
+
+void task_init( task_t *task, uint16_t gdt_code_segment_selector, task_func_t *entrypoint )
+{
+ memset( task, 0, sizeof( task_t ) );
+
+ task->cpu_state = (cpu_state_t *)( task->stack + TASK_STACK_SIZE - sizeof( cpu_state_t ) );
+
+ task->cpu_state->eax = 0;
+ task->cpu_state->ebx = 0;
+ task->cpu_state->ecx = 0;
+ task->cpu_state->edx = 0;
+ task->cpu_state->esi = 0;
+ task->cpu_state->edi = 0;
+ task->cpu_state->ebp = 0;
+
+ // neded for security spaces and users
+ //~ task->cpu_state->esp = 0;
+ //~ task->cpu_state->ss = 0;
+
+ task->cpu_state->eip = (uint32_t)entrypoint;
+ task->cpu_state->cs = gdt_code_segment_selector;
+
+ // TODO: why?
+ task->cpu_state->eflags = 0x202;
+
+ //~ task->cpu_state->error = 0;
+
+ //~ task->cpu_state->gs = 0;
+ //~ task->cpu_state->fs = 0;
+ //~ task->cpu_state->es = 0;
+ //~ task->cpu_state->ds = 0;
+}
+
+void task_manager_init( task_manager_t *manager )
+{
+ memset( manager, 0, sizeof( task_manager_t ) );
+
+ manager->nof_tasks = 0;
+ manager->current_task = -1;
+ memset( manager->task, 0, MAX_NOF_TASKS * sizeof( task_t * ) );
+}
+
+void task_manager_add_task( task_manager_t *manager, task_t *task )
+{
+ if( manager->nof_tasks >= MAX_NOF_TASKS - 1 ) {
+ kernel_panic( "Allocating more than %d tasks.. increase kernel constant MAX_NOF_TASKS", MAX_NOF_TASKS );
+ }
+
+ manager->task[manager->nof_tasks] = task;
+ manager->nof_tasks++;
+}
+
+cpu_state_t *task_manager_schedule_task( task_manager_t *manager, cpu_state_t *cpu_state )
+{
+ // no tasks, no task switch
+ if( manager->nof_tasks == 0 ) {
+ return cpu_state;
+ }
+
+ // store state of the current task
+ if( manager->current_task >= 0 ) {
+ manager->task[manager->current_task]->cpu_state = cpu_state;
+ }
+
+ // pick next task (simple round robin)
+ manager->current_task++;
+ if( manager->current_task >= manager->nof_tasks ) {
+ manager->current_task = 0;
+ }
+
+ return manager->task[manager->current_task]->cpu_state;
+}
diff --git a/src/kernel/tasks.h b/src/kernel/tasks.h
new file mode 100644
index 0000000..604c463
--- /dev/null
+++ b/src/kernel/tasks.h
@@ -0,0 +1,64 @@
+#ifndef TASKS_H
+#define TASKS_H
+
+#include <stdint.h>
+
+#define TASK_STACK_SIZE 4096
+
+#if defined( __TINYC__ )
+#pragma pack(1)
+#endif
+
+typedef struct {
+ // pushed by us
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t ebp;
+
+ // really needed?
+ //~ uint32_t gs;
+ //~ uint32_t fs;
+ //~ uint32_t es;
+ //~ uint32_t ds;
+
+ // ?
+ uint32_t error;
+
+ // pushed by the CPU
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t ss;
+} __attribute__( ( packed ) ) cpu_state_t;
+
+#if defined( __TINYC__ )
+#pragma pack()
+#endif
+
+typedef struct {
+ uint8_t stack[TASK_STACK_SIZE];
+ cpu_state_t *cpu_state;
+} task_t;
+
+typedef void (*task_func_t)( void );
+
+void task_init( task_t *task, uint16_t gdt_code_segment_selector, task_func_t *entrypoint );
+
+#define MAX_NOF_TASKS 256
+
+typedef struct {
+ int nof_tasks;
+ int current_task;
+ task_t *task[MAX_NOF_TASKS];
+} task_manager_t;
+
+void task_manager_init( task_manager_t *manager );
+void task_manager_add_task( task_manager_t *manager, task_t *task );
+cpu_state_t *task_manager_schedule_task( task_manager_t *manager, cpu_state_t *cpu_state );
+
+#endif // TASKS_H