diff options
Diffstat (limited to 'src/kernel/tasks.c')
-rw-r--r-- | src/kernel/tasks.c | 76 |
1 files changed, 76 insertions, 0 deletions
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; +} |