142 lines
2.4 KiB
C
142 lines
2.4 KiB
C
|
#include <kernel/task.h>
|
||
|
#include <kernel/heap.h>
|
||
|
|
||
|
struct Task* tasks;
|
||
|
size_t tasks_capacity;
|
||
|
size_t num_tasks;
|
||
|
|
||
|
size_t current_task = 0;
|
||
|
|
||
|
void setup_tasks()
|
||
|
{
|
||
|
tasks = malloc(sizeof(*tasks));
|
||
|
tasks_capacity = 1;
|
||
|
num_tasks = 1;
|
||
|
}
|
||
|
|
||
|
void add_task(struct Task task)
|
||
|
{
|
||
|
if (num_tasks == tasks_capacity) {
|
||
|
struct Task* temp = malloc(sizeof(*tasks) * tasks_capacity * 2);
|
||
|
|
||
|
for (size_t i = 0; i < num_tasks; i++) {
|
||
|
temp[i] = tasks[i];
|
||
|
}
|
||
|
|
||
|
tasks_capacity *= 2;
|
||
|
|
||
|
free(tasks);
|
||
|
tasks = temp;
|
||
|
}
|
||
|
|
||
|
tasks[num_tasks] = task;
|
||
|
num_tasks++;
|
||
|
}
|
||
|
|
||
|
size_t ss;
|
||
|
size_t esp;
|
||
|
size_t eflags;
|
||
|
size_t cs;
|
||
|
size_t eip;
|
||
|
|
||
|
void jump_kernel(size_t eax, size_t ebx, size_t ecx, size_t edx, size_t ebp, size_t esp);
|
||
|
void jump_user(size_t eax, size_t ebx, size_t ecx, size_t edx, size_t ebp);
|
||
|
|
||
|
static void save_state(
|
||
|
size_t eax,
|
||
|
size_t ebx,
|
||
|
size_t ecx,
|
||
|
size_t edx,
|
||
|
|
||
|
size_t esp,
|
||
|
size_t ebp,
|
||
|
|
||
|
size_t eip,
|
||
|
|
||
|
size_t cs,
|
||
|
size_t ds,
|
||
|
|
||
|
size_t eflags
|
||
|
) {
|
||
|
struct CPUState state = {
|
||
|
.eax = eax,
|
||
|
.ebx = ebx,
|
||
|
.ecx = ecx,
|
||
|
.edx = edx,
|
||
|
|
||
|
.esp = esp,
|
||
|
.ebp = ebp,
|
||
|
|
||
|
.eip = eip,
|
||
|
|
||
|
.cs = cs,
|
||
|
.ds = ds,
|
||
|
|
||
|
.eflags = eflags,
|
||
|
};
|
||
|
|
||
|
tasks[current_task].state = state;
|
||
|
|
||
|
current_task++;
|
||
|
current_task %= num_tasks;
|
||
|
}
|
||
|
|
||
|
void next_task() {
|
||
|
struct CPUState s = tasks[current_task].state;
|
||
|
|
||
|
ss = s.ds;
|
||
|
esp = s.esp;
|
||
|
eflags = s.eflags;
|
||
|
cs = s.cs;
|
||
|
eip = s.eip;
|
||
|
|
||
|
if ((cs & 3) == 0) {
|
||
|
jump_kernel(s.eax, s.ebx, s.ecx, s.edx, s.ebp, s.esp);
|
||
|
} else {
|
||
|
jump_user(s.eax, s.ebx, s.ecx, s.edx, s.ebp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void _switch_task(
|
||
|
size_t eax,
|
||
|
size_t ebx,
|
||
|
size_t ecx,
|
||
|
size_t edx,
|
||
|
|
||
|
size_t ebp,
|
||
|
|
||
|
size_t esp_current,
|
||
|
|
||
|
size_t eip_passed,
|
||
|
size_t cs_passed,
|
||
|
size_t eflags_passed,
|
||
|
size_t esp_passed,
|
||
|
size_t ds_passed
|
||
|
)
|
||
|
{
|
||
|
if (num_tasks == 0) {
|
||
|
return;
|
||
|
};
|
||
|
|
||
|
size_t ds;
|
||
|
if ((cs & 3) == 0) {
|
||
|
ds = 0x10;
|
||
|
esp_current = esp_current + sizeof(size_t) * 3;
|
||
|
} else {
|
||
|
ds = ds_passed;
|
||
|
esp_current = esp_passed;
|
||
|
}
|
||
|
|
||
|
ss = ds_passed;
|
||
|
esp = esp_passed;
|
||
|
eflags = eflags_passed;
|
||
|
cs = cs_passed;
|
||
|
eip = eip_passed;
|
||
|
|
||
|
save_state(eax, ebx, ecx, edx, esp, ebp, eip_passed, cs_passed, ds, eflags_passed);
|
||
|
|
||
|
next_task();
|
||
|
}
|
||
|
|
||
|
|