From e6efe69c614d7781d18a7189831e8243abf57664 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 2 Jul 2017 21:39:09 +0200 Subject: started to add task scheduling --- src/kernel/kernel.c | 3 +++ src/kernel/tasks.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel/tasks.h | 64 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 src/kernel/tasks.c create mode 100644 src/kernel/tasks.h (limited to 'src/kernel') 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 + +#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 -- cgit v1.2.3-54-g00ecf