os/kernel/cpu/i386/tasking.c

181 lines
4.8 KiB
C
Raw Normal View History

2019-02-11 09:30:28 -06:00
#include "tasking_helpers.h"
#include "tasking.h"
#include "../tasking.h"
#include "isr.h"
#include <stdio.h>
2019-05-11 10:11:28 -05:00
#include <string.h>
#include "kmalloc.h"
2019-02-11 09:30:28 -06:00
#include "memory.h"
2019-03-17 12:22:00 -05:00
#include "gdt.h"
2019-04-13 09:23:40 -05:00
#include "paging.h"
2019-02-11 09:30:28 -06:00
#include <stdint.h>
2019-04-13 09:23:40 -05:00
#include <stdlib.h>
2019-06-29 09:04:34 -05:00
#include "../halt.h"
#include "serial.h"
#include "../../vga_err.h"
2019-02-11 09:30:28 -06:00
#define STACK_PAGES 2
2019-05-21 19:16:19 -05:00
extern void task_init();
2019-06-29 09:04:34 -05:00
static uint32_t* kstacks=(uint32_t*)0xF6800000;
2019-05-21 19:16:19 -05:00
2019-02-11 09:30:28 -06:00
uint32_t next_pid;
2019-05-21 19:16:19 -05:00
Task* currentTask;
2019-02-11 09:30:28 -06:00
static Task* headTask;
static Task* tailTask;
static Task* tasks[32768];
Task* tasking_createTaskCr3KmodeParam(void* eip,void* cr3,char kmode,char param1_exists,uint32_t param1_arg,char param2_exists,uint32_t param2_arg);
2019-02-11 09:30:28 -06:00
2019-05-21 19:16:19 -05:00
void tasking_init(void* esp) {
2019-02-11 09:30:28 -06:00
currentTask=NULL;
next_pid=0;
headTask=tasking_createTaskCr3KmodeParam(NULL,paging_new_address_space(),1,0,0,0,0);
2019-02-11 09:30:28 -06:00
currentTask=headTask;
tailTask=headTask;
2019-02-11 09:30:28 -06:00
}
Task* tasking_createTaskCr3KmodeParam(void* eip,void* cr3,char kmode,char param1_exists,uint32_t param1_arg,char param2_exists,uint32_t param2_arg) {
Task* task=kmalloc(sizeof(Task));
map_kstack(next_pid);
uint32_t param1;
if (param1_exists) {
param1=param1_arg;
} else {
param1=1;
}
uint32_t param2;
if (param2_exists) {
param2=param2_arg;
} else {
param2=2;
}
2019-05-11 10:11:28 -05:00
task->cr3=(uint32_t)cr3;
uint32_t old_cr3;
asm volatile("movl %%cr3, %%eax; movl %%eax, %0;":"=m"(old_cr3)::"%eax");
2019-05-11 10:11:28 -05:00
load_address_space(task->cr3);
2019-05-21 19:16:19 -05:00
if (kmode) {
uint32_t top_idx=(1024*(next_pid+1));
task->kernel_esp=((uint32_t)(&kstacks[top_idx-5]));
task->kernel_esp_top=task->kernel_esp;
kstacks[top_idx-5]=0;
kstacks[top_idx-4]=0;
kstacks[top_idx-3]=0;
kstacks[top_idx-2]=0;
2019-06-29 09:04:34 -05:00
kstacks[top_idx-1]=(uint32_t)eip;
2019-05-21 19:16:19 -05:00
} else {
uint32_t top_idx=(1024*(next_pid+1));
task->kernel_esp=((uint32_t)(&kstacks[top_idx-7]));
task->kernel_esp_top=task->kernel_esp;
kstacks[top_idx-7]=0;
kstacks[top_idx-6]=0;
kstacks[top_idx-5]=0;
kstacks[top_idx-4]=0;
2019-06-29 09:04:34 -05:00
kstacks[top_idx-3]=(uint32_t)task_init;
uint32_t* user_stack=(uint32_t*)(((uint32_t)alloc_pages(2))+0x2000);
int buffer_pg_num=(((uint32_t)user_stack)-0x2000)>>12;
make_protector(buffer_pg_num);
// uint32_t* user_stack=(uint32_t*)(((uint32_t)alloc_pages(1))+0x1000);
user_stack-=2;
user_stack[0]=param1;
user_stack[1]=param2;
2019-06-29 09:04:34 -05:00
kstacks[top_idx-2]=(uint32_t)user_stack;
kstacks[top_idx-1]=(uint32_t)eip;
2019-05-11 10:11:28 -05:00
}
load_address_space(old_cr3);
2019-02-11 09:30:28 -06:00
task->next=NULL;
task->pid=next_pid;
tasks[next_pid]=task;
2019-02-25 15:42:23 -06:00
task->priv=0;
2019-04-08 15:58:30 -05:00
task->errno=0;
2019-02-25 15:42:23 -06:00
if (currentTask) {
task->priv=currentTask->priv;
}
if (task->pid==1) {
task->priv=1;
}
2019-02-11 09:30:28 -06:00
next_pid++;
2019-06-22 11:11:12 -05:00
if (next_pid>1024*32) {
serial_printf("Failed to create a task, as 32k tasks have been created already.\n");
2019-06-22 11:11:12 -05:00
halt(); //Cannot ever create more than 32k tasks, as I don't currently reuse PIDs.
}
if (tailTask) {
tailTask->next=task;
2019-08-25 17:06:19 -05:00
task->prev=tailTask;
tailTask=task;
2019-08-25 17:06:19 -05:00
} else {
task->prev=NULL;
2019-02-11 09:30:28 -06:00
}
if (task->pid!=0) {
serial_printf("Created task with PID %d.\n",task->pid);
}
2019-02-11 09:30:28 -06:00
return task;
}
2019-04-08 15:58:30 -05:00
int* tasking_get_errno_address() {
return &(currentTask->errno);
}
2019-02-25 15:42:23 -06:00
char isPrivleged(uint32_t pid) {
for (Task* task=headTask;task!=NULL;task=task->next) {
if (task->pid==pid) {
return task->priv;
}
}
return 0;
}
Task* tasking_createTask(void* eip) {
return tasking_createTaskCr3KmodeParam(eip,paging_new_address_space(),0,0,0,0,0);
2019-02-11 09:30:28 -06:00
}
2019-05-11 10:11:28 -05:00
void tasking_yield(registers_t registers) {
2019-05-21 19:16:19 -05:00
Task* task=currentTask->next;
if (!task) {
task=headTask;
}
serial_printf("Yielding to PID %d.\n",task->pid);
load_smap(task->cr3);
switch_to_task(task);
}
void tasking_yieldToPID(uint32_t pid) {
Task* task=tasks[pid];
if (!task) {
serial_printf("PID %d does not exist.\n",pid);
return;
}
serial_printf("Yielding to PID %d.\n",task->pid);
load_smap(task->cr3);
2019-05-21 19:16:19 -05:00
switch_to_task(task);
2019-02-11 09:30:28 -06:00
}
void tasking_exit(uint8_t code) {
serial_printf("PID %d is exiting with code %d.\n",currentTask->pid,code);
if (currentTask->prev) {
currentTask->prev->next=currentTask->next;
}
if (currentTask->next) {
currentTask->next->prev=currentTask->prev;
}
if (headTask==currentTask) {
if (!currentTask->next) {
serial_write_string("ERROR! Head task exited with no child tasks! Halting!\n");
vga_write_string("ERROR! Head task exited with no child tasks! Halting!\n");
halt();
}
headTask=currentTask->next;
}
Task* task=currentTask->next;
if (task==NULL) {
task=headTask;
}
kfree(currentTask);
serial_printf("Exit yielding to PID %d.\n",task->pid);
load_smap(task->cr3);
switch_to_task(task);
}
uint32_t getPID() {
return currentTask->pid;
}