os/cpu/i386/tasking.c

157 lines
3.6 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>
#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-02-11 09:30:28 -06:00
#define STACK_PAGES 2
uint32_t next_pid;
static Task* currentTask;
static Task* headTask;
2019-02-25 15:42:23 -06:00
static Task* createTaskKmode(void* eip,char kmode);
2019-02-11 09:30:28 -06:00
void tasking_init() {
currentTask=NULL;
next_pid=0;
2019-02-25 15:42:23 -06:00
headTask=createTaskKmode(NULL,1);
2019-02-11 09:30:28 -06:00
currentTask=headTask;
}
2019-02-25 15:42:23 -06:00
static Task* createTaskKmode(void* eip,char kmode) {
Task* task=kmalloc(sizeof(Task));
2019-02-25 15:42:23 -06:00
task->kmode=kmode;
task->regs.eax=0;
2019-02-11 09:30:28 -06:00
task->regs.ebx=0;
task->regs.ecx=0;
task->regs.edx=0;
task->regs.esi=0;
task->regs.edi=0;
asm volatile("pushfl; movl (%%esp), %%eax; movl %%eax, %0; popfl;":"=m"(task->regs.eflags)::"%eax");
task->regs.eip=(uint32_t)eip;
task->regs.cr3=new_address_space();
uint32_t cr3;
asm volatile("movl %%cr3, %%eax; movl %%eax, %0;":"=m"(cr3)::"%eax");
load_address_space(task->regs.cr3);
2019-04-13 09:23:40 -05:00
task->regs.esp=((uint32_t)alloc_pages(1))+0xfff;
load_address_space(cr3);
2019-02-11 09:30:28 -06:00
task->regs.ebp=0;
task->msg_store=NULL;
task->rd=0;
task->wr=0;
task->next=NULL;
task->pid=next_pid;
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++;
if (currentTask) {
currentTask->next=task;
}
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 createTaskKmode(eip,0);
2019-02-11 09:30:28 -06:00
}
2019-03-15 18:53:50 -05:00
void send_msg(uint32_t pid,void* msg) {
2019-03-11 09:32:55 -05:00
for (Task* task=headTask;task!=NULL;task=task->next) {
2019-02-11 09:30:28 -06:00
if (task->pid==pid) {
if (task->msg_store==NULL) {
2019-03-15 18:53:50 -05:00
task->msg_store=malloc(sizeof(void*)*256);
2019-02-11 09:30:28 -06:00
task->sender_store=malloc(sizeof(uint32_t)*256);
}
task->msg_store[task->wr]=msg;
task->sender_store[task->wr]=currentTask->pid;
task->wr++;
if (task->wr==task->rd) {
task->wr--;
}
}
}
}
2019-03-15 18:53:50 -05:00
void* get_msg(uint32_t* sender) {
2019-02-11 09:30:28 -06:00
if (!currentTask->msg_store) {
return NULL;
}
if (currentTask->msg_store[currentTask->rd]==NULL) {
currentTask->rd++;
if (currentTask->msg_store[currentTask->rd]==NULL) {
currentTask->rd--;
return NULL;
}
}
*sender=currentTask->sender_store[currentTask->rd];
char* data=currentTask->msg_store[currentTask->rd];
currentTask->msg_store[currentTask->rd]=NULL;
currentTask->sender_store[currentTask->rd]=0;
currentTask->rd++;
if (currentTask->rd>currentTask->wr) {
currentTask->rd=currentTask->wr-1;
}
return data;
}
void tasking_yield() {
2019-02-11 09:30:28 -06:00
Task* task=currentTask->next;
if (!task) {
task=headTask;
}
Task* oldCurr=currentTask;
currentTask=task;
2019-03-23 11:14:59 -05:00
load_address_space(task->regs.cr3);
if (task->priv) {
allow_all_ports();
} else {
block_all_ports();
}
2019-02-25 15:42:23 -06:00
if (!task->kmode) {
asm volatile(" \
cli; \
mov $0x23, %ax; \
mov %ax, %ds; \
mov %ax, %es; \
mov %ax, %fs; \
mov %ax, %gs; \
\
mov %esp, %eax; \
pushl $0x23; \
pushl %eax; \
pushf; \
pop %eax; \
or $0x200,%eax; \
push %eax; \
2019-02-25 15:42:23 -06:00
pushl $0x1B; \
push $1f; \
iret; \
1: \
");
}
2019-02-11 09:30:28 -06:00
switchTask(&oldCurr->regs, &currentTask->regs);
}