wip: better way of handling thread switch (iret in the switch)
This commit is contained in:
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
void scheduler(void);
|
||||
#include <stdint.h>
|
||||
|
||||
void scheduler(uint32_t *esp);
|
||||
|
||||
@ -24,4 +24,4 @@ struct tcb {
|
||||
|
||||
struct tcb *create_thread(struct pcb *process, void (*entry)(void));
|
||||
void delete_thread(struct tcb *thread);
|
||||
void switch_thread(struct tcb *thread_to_switch);
|
||||
void switch_thread(uint32_t *esp);
|
||||
|
||||
@ -40,7 +40,7 @@ static void clock_handler(struct registers *regs)
|
||||
{
|
||||
(void)regs;
|
||||
if (scheduler_counter % 10 == 0)
|
||||
scheduler();
|
||||
scheduler((uint32_t *)regs->esp);
|
||||
scheduler_counter++;
|
||||
sleep_counter--;
|
||||
}
|
||||
|
||||
@ -6,31 +6,6 @@
|
||||
|
||||
#include "string.h"
|
||||
|
||||
// int8_t create_kernel_process(void)
|
||||
// {
|
||||
// struct pcb *new_pcb = vmalloc(sizeof(struct pcb));
|
||||
// if (!new_pcb)
|
||||
// return -1;
|
||||
// new_pcb->pid = 0;
|
||||
// new_pcb->uid = 0;
|
||||
// new_pcb->heap = kernel_pd;
|
||||
// new_pcb->cr3 = (uint32_t *)((uint32_t)kernel_pd - HEAP_END);
|
||||
// new_pcb->next = new_pcb;
|
||||
// new_pcb->prev = new_pcb;
|
||||
// struct tcb *kern_thread = vmalloc(sizeof(struct tcb));
|
||||
// if (!kern_thread) {
|
||||
// vfree(new_pcb);
|
||||
// return -1;
|
||||
// }
|
||||
// kern_thread->esp = ;
|
||||
// kern_thread->next = NULL;
|
||||
// kern_thread->process = new_pcb;
|
||||
// kern_thread->state = RUNNING;
|
||||
// kern_thread->tid = 1;
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
struct pcb *create_process(uint8_t uid)
|
||||
{
|
||||
static uint32_t pid = 1;
|
||||
@ -47,14 +22,16 @@ struct pcb *create_process(uint8_t uid)
|
||||
}
|
||||
memcpy(new_pcb->heap, current_pcb->heap, 4096);
|
||||
|
||||
new_pcb->next = new_pcb;
|
||||
new_pcb->prev = new_pcb;
|
||||
|
||||
if (current_pcb) {
|
||||
new_pcb->next = current_pcb->next;
|
||||
new_pcb->prev = current_pcb;
|
||||
current_pcb->next = new_pcb;
|
||||
if (current_pcb->prev == current_pcb)
|
||||
current_pcb->prev = new_pcb;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
current_pcb = new_pcb;
|
||||
}
|
||||
new_pcb->signals.pending = SIG_IGN;
|
||||
|
||||
@ -11,19 +11,32 @@
|
||||
struct pcb *current_pcb;
|
||||
struct tcb *current_tcb;
|
||||
|
||||
void scheduler(void)
|
||||
static struct tcb *get_thread_to_switch(void)
|
||||
{
|
||||
struct tcb *thread_to_switch;
|
||||
if (!current_tcb) {
|
||||
thread_to_switch = current_pcb->thread_list;
|
||||
} else {
|
||||
if (!current_tcb->next) {
|
||||
current_pcb = current_pcb->next;
|
||||
// TODO switch context
|
||||
thread_to_switch = current_pcb->thread_list;
|
||||
} else {
|
||||
thread_to_switch = current_tcb->next;
|
||||
struct pcb *it_p;
|
||||
struct tcb *it_t;
|
||||
|
||||
it_p = current_pcb;
|
||||
it_t = current_tcb == NULL ? NULL : current_tcb->next;
|
||||
while (it_p) {
|
||||
while (it_t != NULL) {
|
||||
if (it_t != NULL && it_t->state != WAITING)
|
||||
return it_t;
|
||||
it_t = it_t->next;
|
||||
}
|
||||
it_p = it_p->next;
|
||||
it_t = it_p->thread_list;
|
||||
}
|
||||
switch_thread(thread_to_switch);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void scheduler(uint32_t *esp)
|
||||
{
|
||||
struct tcb *thread_to_switch = get_thread_to_switch();
|
||||
if (!thread_to_switch)
|
||||
kpanic("No existing threads \n");
|
||||
if (current_tcb)
|
||||
current_tcb->esp = esp;
|
||||
current_tcb = thread_to_switch;
|
||||
switch_thread(thread_to_switch->esp);
|
||||
}
|
||||
|
||||
@ -1,27 +1,21 @@
|
||||
.intel_syntax noprefix
|
||||
.set CLEAR_ERRNO_INTNO, 0x08
|
||||
|
||||
.section .text
|
||||
.global switch_thread
|
||||
|
||||
switch_thread:
|
||||
mov edx, DWORD PTR [esp]
|
||||
cmp DWORD PTR [current_tcb], 0
|
||||
je .LABEL1
|
||||
mov eax, [current_tcb]
|
||||
|
||||
// save the current stack pointer to the old stack
|
||||
mov [eax+0], esp
|
||||
mov eax, [esp + 4]
|
||||
mov esp, eax
|
||||
|
||||
// stack pointer + the 4 regs pushed
|
||||
// and + 1 to get the argument (next thread)
|
||||
.LABEL1:
|
||||
mov esi, [esp+4]
|
||||
mov [current_tcb], esi
|
||||
pop eax
|
||||
mov ds, eax
|
||||
|
||||
mov eax, [current_tcb]
|
||||
popa
|
||||
|
||||
mov esp, [eax+0] // get esp
|
||||
call pic_send_eoi
|
||||
|
||||
push edx
|
||||
add esp, CLEAR_ERRNO_INTNO
|
||||
|
||||
ret
|
||||
iret
|
||||
|
||||
@ -19,15 +19,27 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
|
||||
vfree(new_tcb);
|
||||
return NULL;
|
||||
}
|
||||
// set esp to "skip" the 4 GPRs and eip later to be used as the context
|
||||
// of the thread
|
||||
uint32_t *stack =
|
||||
(uint32_t *)((uint8_t *)new_tcb->esp0 + STACK_SIZE - 5 * 4);
|
||||
uint32_t *stack = (uint32_t *)((uint8_t *)new_tcb->esp0 + STACK_SIZE);
|
||||
uint32_t *esp = stack;
|
||||
|
||||
// testing out some stuff
|
||||
*(--stack) = 0x202; // EFLAGS
|
||||
*(--stack) = 0x08; // CS = kernel code segment
|
||||
*(--stack) = (uint32_t)entry;
|
||||
// Error code and interrupt number (skipped by add $8, %esp)
|
||||
*(--stack) = 0; // err_code
|
||||
*(--stack) = 0; // int_no
|
||||
|
||||
// General purpose registers (for popa)
|
||||
*(--stack) = 0; // EAX
|
||||
*(--stack) = 0; // ECX
|
||||
*(--stack) = 0; // EDX
|
||||
*(--stack) = 0; // EBX
|
||||
*(--stack) = (uint32_t)esp; // ESP (original - points to exit_process)
|
||||
*(--stack) = 0; // EBP
|
||||
*(--stack) = 0; // ESI
|
||||
*(--stack) = 0; // EDI
|
||||
*(--stack) = 0x10; // kernel DS
|
||||
new_tcb->esp = stack;
|
||||
new_tcb->process = process;
|
||||
new_tcb->next = NULL;
|
||||
|
||||
Reference in New Issue
Block a user