starting to work on pty drivers, fork(), and scheduler redesign
This commit is contained in:
@@ -11,12 +11,11 @@
|
||||
#include "scheduler.h"
|
||||
#include "gdt.h"
|
||||
|
||||
static process_t* process_table;
|
||||
|
||||
static int current_process = 0;
|
||||
static int total_processes = 0;
|
||||
static process_t* process_table = NULL;
|
||||
static process_t* current_process = NULL;
|
||||
static process_t* idle_task = NULL;
|
||||
|
||||
#define IDLE_TASK_PID 0
|
||||
static int total_processes = 0;
|
||||
|
||||
static void lock_scheduler() {
|
||||
disable_interrupts();
|
||||
@@ -26,9 +25,8 @@ static void unlock_scheduler() {
|
||||
enable_interrupts();
|
||||
}
|
||||
|
||||
// called from isr and yield, interrupts are already disabled and re enabled in the isr/yield func
|
||||
uint32_t switch_context(uint32_t current_esp) {
|
||||
process_table[current_process].esp = current_esp;
|
||||
current_process->esp = current_esp;
|
||||
|
||||
for (int i = 0; i < total_processes; i++) {
|
||||
if (process_table[i].state == STATE_SLEEPING) {
|
||||
@@ -42,12 +40,12 @@ uint32_t switch_context(uint32_t current_esp) {
|
||||
}
|
||||
}
|
||||
|
||||
int next_process = current_process;
|
||||
process_t* next_process = current_process;
|
||||
int found_ready = 0;
|
||||
|
||||
while (1) {
|
||||
next_process = (next_process + 1) % total_processes;
|
||||
if (next_process != IDLE_TASK_PID && process_table[next_process].state == STATE_READY) {
|
||||
next_process = (process_t*)next_process->sched_next;
|
||||
if (next_process != idle_task && next_process->state == STATE_READY) {
|
||||
found_ready = 1;
|
||||
break;
|
||||
}
|
||||
@@ -58,53 +56,52 @@ uint32_t switch_context(uint32_t current_esp) {
|
||||
}
|
||||
|
||||
if (!found_ready) {
|
||||
if (process_table[current_process].state == STATE_READY) {
|
||||
if (current_process->state == STATE_READY) {
|
||||
next_process = current_process;
|
||||
} else {
|
||||
next_process = IDLE_TASK_PID;
|
||||
next_process = idle_task;
|
||||
}
|
||||
}
|
||||
|
||||
current_process = next_process;
|
||||
|
||||
uint32_t current_cr3 = fetch_cr3();
|
||||
if (current_cr3 != process_table[current_process].cr3) {
|
||||
load_pd((void*)process_table[current_process].cr3);
|
||||
if (current_cr3 != current_process->cr3) {
|
||||
load_pd((void*)current_process->cr3);
|
||||
}
|
||||
|
||||
if (process_table[current_process].flags & PROCESS_FLAG_USER) {
|
||||
tss.esp0 = process_table[current_process].kstack_top;
|
||||
if (current_process->flags & PROCESS_FLAG_USER) {
|
||||
tss.esp0 = current_process->kstack_top;
|
||||
}
|
||||
|
||||
return process_table[current_process].esp;
|
||||
return current_process->esp;
|
||||
}
|
||||
|
||||
void init_scheduler() {
|
||||
process_table = kalloc(16 * sizeof(process_t));
|
||||
memset((void*)process_table, 0, 16 * sizeof(process_t));
|
||||
total_processes = 0;
|
||||
process_t* root = kalloc(sizeof(process_t));
|
||||
root->pid = 0;
|
||||
root->esp = 0;
|
||||
root->cr3 = fetch_cr3();
|
||||
root->state = STATE_READY;
|
||||
root->sleep = 0;
|
||||
root->flags = PROCESS_FLAG_KERNEL;
|
||||
root->sched_next = NULL;
|
||||
|
||||
process_t* process = &process_table[total_processes];
|
||||
process->pid = total_processes;
|
||||
process->esp = 0;
|
||||
process->cr3 = fetch_cr3();
|
||||
process->state = STATE_READY;
|
||||
process->sleep = 0;
|
||||
process->flags = PROCESS_FLAG_KERNEL;
|
||||
total_processes++;
|
||||
current_process = root;
|
||||
idle_task = root;
|
||||
process_table = root;
|
||||
|
||||
current_process = 0;
|
||||
total_processes = 1;
|
||||
}
|
||||
|
||||
int create_task(uint32_t entry_point, uint32_t cr3, int user, uint32_t u_esp) {
|
||||
if (total_processes >= 16) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// default to a new task, but if we find a dead one, re use it
|
||||
process_t* process = &process_table[total_processes];
|
||||
uint32_t pid = total_processes;
|
||||
process->pid = pid;
|
||||
void init_task (
|
||||
process_t* process,
|
||||
uint32_t entry_point,
|
||||
uint32_t cr3,
|
||||
int user,
|
||||
uint32_t u_esp
|
||||
) {
|
||||
process->pid = get_next_pid();
|
||||
process->cr3 = cr3;
|
||||
process->state = STATE_READY;
|
||||
process->sleep = 0;
|
||||
@@ -145,32 +142,61 @@ int create_task(uint32_t entry_point, uint32_t cr3, int user, uint32_t u_esp) {
|
||||
}
|
||||
|
||||
process->esp = (uint32_t)esp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_next_pid() {
|
||||
lock_scheduler();
|
||||
int pid = total_processes;
|
||||
total_processes++;
|
||||
unlock_scheduler();
|
||||
return pid;
|
||||
}
|
||||
|
||||
void add_task(process_t* task) {
|
||||
lock_scheduler();
|
||||
|
||||
if (!task) {
|
||||
unlock_scheduler();
|
||||
return;
|
||||
}
|
||||
|
||||
if (process_table->sched_next == NULL) {
|
||||
process_table->sched_next = task;
|
||||
task->sched_next = process_table;
|
||||
unlock_scheduler();
|
||||
return;
|
||||
}
|
||||
|
||||
process_t* curr = process_table;
|
||||
while (curr->sched_next != process_table) {
|
||||
curr = curr->sched_next;
|
||||
}
|
||||
|
||||
curr->sched_next = task;
|
||||
task->sched_next = process_table;
|
||||
|
||||
unlock_scheduler();
|
||||
}
|
||||
|
||||
process_t* current_task() {
|
||||
lock_scheduler();
|
||||
process_t* rtn = &process_table[current_process];
|
||||
process_t* rtn = current_process;
|
||||
unlock_scheduler();
|
||||
return rtn;
|
||||
}
|
||||
|
||||
process_t* current_task_unsafe() {
|
||||
return &process_table[current_process];
|
||||
}
|
||||
|
||||
void sleep(uint32_t ms) {
|
||||
if (ms == 0) return;
|
||||
lock_scheduler();
|
||||
process_table[current_process].sleep = ms;
|
||||
process_table[current_process].state = STATE_SLEEPING;
|
||||
current_process->sleep = ms;
|
||||
current_process->state = STATE_SLEEPING;
|
||||
yield();
|
||||
unlock_scheduler();
|
||||
}
|
||||
|
||||
void exit() {
|
||||
lock_scheduler();
|
||||
process_table[current_process].state = STATE_DEAD;
|
||||
current_process->state = STATE_DEAD;
|
||||
yield(); // yield forever
|
||||
unlock_scheduler();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user