feat: introduced tasking, added paging (no vm), moved malloc, added
syscalls, other stuff
This commit is contained in:
42
kernel/tasks/task.S
Normal file
42
kernel/tasks/task.S
Normal file
@@ -0,0 +1,42 @@
|
||||
.code32
|
||||
|
||||
.global __task_entry_point
|
||||
__task_entry_point:
|
||||
# Load segments
|
||||
popl %eax
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
movw %ax,%fs
|
||||
movw %ax,%gs
|
||||
# pop isr_registers
|
||||
popa
|
||||
# Remove errono etc.
|
||||
addl $8,%esp # Cleans up the pushed error code and pushed ISR number
|
||||
sti
|
||||
# return to program
|
||||
iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
||||
.global __task_entry_point_inner
|
||||
__task_entry_point_inner:
|
||||
add $8, %esp # Remove useresp and ss (only exists in user space)
|
||||
call task_entry_point
|
||||
.global switch_task
|
||||
switch_task:
|
||||
movl 4(%esp), %eax
|
||||
movl 8(%esp), %edx
|
||||
test %eax, %eax
|
||||
jz _st_no_store
|
||||
pushl %ebp
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
movl %esp, (%eax)
|
||||
_st_no_store:
|
||||
movl %edx, %esp
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
|
||||
|
||||
131
kernel/tasks/task.c
Normal file
131
kernel/tasks/task.c
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// Created by rick on 22-02-21.
|
||||
//
|
||||
|
||||
#include "task.h"
|
||||
#include <cpu/cpu.h>
|
||||
#include <stdbool.h>
|
||||
#include <libc/libc.h>
|
||||
#include <mem/malloc.h>
|
||||
#include <mem/pmm.h>
|
||||
|
||||
#include <attributes.h>
|
||||
|
||||
#define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE))
|
||||
|
||||
typedef struct task {
|
||||
bool present: 1;
|
||||
uint8_t wait_irq: 4;
|
||||
|
||||
uint32_t tid;
|
||||
|
||||
struct task *next;
|
||||
|
||||
void* stack;
|
||||
uint32_t stack_page_count;
|
||||
|
||||
task_registers_t *task_registers;
|
||||
} task_t;
|
||||
|
||||
typedef struct {
|
||||
task_registers_t task_registers;
|
||||
isr_registers_t isr_registers;
|
||||
task_entrypoint entrypoint;
|
||||
void *entry_data;
|
||||
char alignment[4];
|
||||
} packed task_stack_start;
|
||||
|
||||
bool task_locked = false;
|
||||
|
||||
task_t *first_task = NULL;
|
||||
task_t *last_task = NULL;
|
||||
task_t *current_task = NULL;
|
||||
|
||||
uint32_t last_tid = 0;
|
||||
|
||||
extern switch_task(task_registers_t**, task_registers_t*);
|
||||
extern cdecl noreturn void __task_entry_point();
|
||||
extern noreturn void __task_entry_point_inner();
|
||||
// explicit cdecl calling convention
|
||||
void cdecl noreturn task_entry_point(task_entrypoint entrypoint, void *entry_data) {
|
||||
entrypoint(entry_data);
|
||||
// task_end_self();
|
||||
while (true); // halt
|
||||
}
|
||||
|
||||
void task_lock_acquire() {
|
||||
task_locked = true;
|
||||
}
|
||||
|
||||
void task_lock_free() {
|
||||
task_locked = false;
|
||||
}
|
||||
|
||||
void task_switch_next_inner(task_t *next_task) {
|
||||
if (task_locked) {
|
||||
return; // don't switch while the task is locked
|
||||
}
|
||||
if (next_task == current_task) {
|
||||
return;
|
||||
}
|
||||
task_t *previous_task = current_task;
|
||||
current_task = next_task;
|
||||
// switch task
|
||||
switch_task(previous_task == NULL ? NULL : &previous_task->task_registers, current_task->task_registers);
|
||||
}
|
||||
|
||||
void task_start_first() {
|
||||
task_switch_next_inner(first_task);
|
||||
}
|
||||
|
||||
void task_switch_next() {
|
||||
if (current_task == NULL) {
|
||||
return;
|
||||
}
|
||||
task_switch_next_inner(current_task->next == NULL ? first_task : current_task->next);
|
||||
}
|
||||
|
||||
uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
|
||||
task_t *new_task = malloc(sizeof(task_t));
|
||||
memset((uint8_t *) new_task, 0, sizeof(task_t));
|
||||
new_task->tid = last_tid++;
|
||||
|
||||
new_task->stack = pmm_get_pages(16);
|
||||
new_task->stack_page_count = 16;
|
||||
// todo check for null
|
||||
|
||||
|
||||
if (first_task == NULL) {
|
||||
// first task
|
||||
first_task = new_task;
|
||||
} else {
|
||||
last_task->next = new_task;
|
||||
}
|
||||
last_task = new_task;
|
||||
|
||||
// prepare stack
|
||||
// cdecl format
|
||||
task_stack_start* stack = (task_stack_start *) (stack_end(new_task) - sizeof(task_stack_start));
|
||||
memset((uint8_t *) stack, 0, sizeof(task_stack_start));
|
||||
// setup isr return frame
|
||||
stack->isr_registers.cs = 0x08; // todo proper gdt setup
|
||||
stack->isr_registers.ds = 0x10; // todo
|
||||
// stack->isr_registers.ss = 0x10; // todo
|
||||
|
||||
stack->isr_registers.eip = (uint32_t) __task_entry_point_inner;
|
||||
stack->isr_registers.eflags = 0x200;
|
||||
// setup task switch frame
|
||||
stack->task_registers.eip = (uint32_t) __task_entry_point;
|
||||
stack->task_registers.ebp = (uint32_t) stack_end(new_task);
|
||||
// setup entrypoint
|
||||
stack->entrypoint = entrypoint;
|
||||
stack->entry_data = entry_data;
|
||||
|
||||
new_task->task_registers = &stack->task_registers;
|
||||
|
||||
new_task->present = true;
|
||||
return new_task->tid;
|
||||
}
|
||||
|
||||
void task_end(uint32_t pid) {
|
||||
}
|
||||
24
kernel/tasks/task.h
Normal file
24
kernel/tasks/task.h
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by rick on 22-02-21.
|
||||
//
|
||||
|
||||
#ifndef NEW_KERNEL_TASK_H
|
||||
#define NEW_KERNEL_TASK_H
|
||||
|
||||
#include <cpu/cpu.h>
|
||||
|
||||
typedef void (*task_entrypoint)(void *entry_data);
|
||||
|
||||
void task_start_first();
|
||||
|
||||
void task_switch_next();
|
||||
|
||||
uint32_t task_spawn(task_entrypoint, void *entry_data);
|
||||
|
||||
void task_end(uint32_t pid);
|
||||
|
||||
void task_lock_acquire();
|
||||
|
||||
void task_lock_free();
|
||||
|
||||
#endif //NEW_KERNEL_TASK_H
|
||||
Reference in New Issue
Block a user