wip: better way of handling thread switch (iret in the switch)
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
#pragma once
|
#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));
|
struct tcb *create_thread(struct pcb *process, void (*entry)(void));
|
||||||
void delete_thread(struct tcb *thread);
|
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;
|
(void)regs;
|
||||||
if (scheduler_counter % 10 == 0)
|
if (scheduler_counter % 10 == 0)
|
||||||
scheduler();
|
scheduler((uint32_t *)regs->esp);
|
||||||
scheduler_counter++;
|
scheduler_counter++;
|
||||||
sleep_counter--;
|
sleep_counter--;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,31 +6,6 @@
|
|||||||
|
|
||||||
#include "string.h"
|
#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)
|
struct pcb *create_process(uint8_t uid)
|
||||||
{
|
{
|
||||||
static uint32_t pid = 1;
|
static uint32_t pid = 1;
|
||||||
@ -47,14 +22,16 @@ struct pcb *create_process(uint8_t uid)
|
|||||||
}
|
}
|
||||||
memcpy(new_pcb->heap, current_pcb->heap, 4096);
|
memcpy(new_pcb->heap, current_pcb->heap, 4096);
|
||||||
|
|
||||||
|
new_pcb->next = new_pcb;
|
||||||
|
new_pcb->prev = new_pcb;
|
||||||
|
|
||||||
if (current_pcb) {
|
if (current_pcb) {
|
||||||
new_pcb->next = current_pcb->next;
|
new_pcb->next = current_pcb->next;
|
||||||
new_pcb->prev = current_pcb;
|
new_pcb->prev = current_pcb;
|
||||||
current_pcb->next = new_pcb;
|
current_pcb->next = new_pcb;
|
||||||
if (current_pcb->prev == current_pcb)
|
if (current_pcb->prev == current_pcb)
|
||||||
current_pcb->prev = new_pcb;
|
current_pcb->prev = new_pcb;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
current_pcb = new_pcb;
|
current_pcb = new_pcb;
|
||||||
}
|
}
|
||||||
new_pcb->signals.pending = SIG_IGN;
|
new_pcb->signals.pending = SIG_IGN;
|
||||||
|
|||||||
@ -11,19 +11,32 @@
|
|||||||
struct pcb *current_pcb;
|
struct pcb *current_pcb;
|
||||||
struct tcb *current_tcb;
|
struct tcb *current_tcb;
|
||||||
|
|
||||||
void scheduler(void)
|
static struct tcb *get_thread_to_switch(void)
|
||||||
{
|
{
|
||||||
struct tcb *thread_to_switch;
|
struct pcb *it_p;
|
||||||
if (!current_tcb) {
|
struct tcb *it_t;
|
||||||
thread_to_switch = current_pcb->thread_list;
|
|
||||||
} else {
|
it_p = current_pcb;
|
||||||
if (!current_tcb->next) {
|
it_t = current_tcb == NULL ? NULL : current_tcb->next;
|
||||||
current_pcb = current_pcb->next;
|
while (it_p) {
|
||||||
// TODO switch context
|
while (it_t != NULL) {
|
||||||
thread_to_switch = current_pcb->thread_list;
|
if (it_t != NULL && it_t->state != WAITING)
|
||||||
} else {
|
return it_t;
|
||||||
thread_to_switch = current_tcb->next;
|
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
|
.intel_syntax noprefix
|
||||||
|
.set CLEAR_ERRNO_INTNO, 0x08
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
.global switch_thread
|
.global switch_thread
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
// stack pointer + the 4 regs pushed
|
|
||||||
// and + 1 to get the argument (next thread)
|
|
||||||
.LABEL1:
|
|
||||||
mov esi, [esp+4]
|
|
||||||
mov [current_tcb], esi
|
|
||||||
|
|
||||||
mov eax, [current_tcb]
|
|
||||||
|
|
||||||
mov esp, [eax+0] // get esp
|
|
||||||
|
|
||||||
push edx
|
|
||||||
|
|
||||||
ret
|
mov eax, [esp + 4]
|
||||||
|
mov esp, eax
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
mov ds, eax
|
||||||
|
|
||||||
|
popa
|
||||||
|
|
||||||
|
call pic_send_eoi
|
||||||
|
|
||||||
|
add esp, CLEAR_ERRNO_INTNO
|
||||||
|
|
||||||
|
iret
|
||||||
|
|||||||
@ -19,15 +19,27 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
|
|||||||
vfree(new_tcb);
|
vfree(new_tcb);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// set esp to "skip" the 4 GPRs and eip later to be used as the context
|
uint32_t *stack = (uint32_t *)((uint8_t *)new_tcb->esp0 + STACK_SIZE);
|
||||||
// of the thread
|
uint32_t *esp = stack;
|
||||||
uint32_t *stack =
|
|
||||||
(uint32_t *)((uint8_t *)new_tcb->esp0 + STACK_SIZE - 5 * 4);
|
|
||||||
|
|
||||||
// testing out some stuff
|
// testing out some stuff
|
||||||
*(--stack) = 0x202; // EFLAGS
|
*(--stack) = 0x202; // EFLAGS
|
||||||
*(--stack) = 0x08; // CS = kernel code segment
|
*(--stack) = 0x08; // CS = kernel code segment
|
||||||
*(--stack) = (uint32_t)entry;
|
*(--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->esp = stack;
|
||||||
new_tcb->process = process;
|
new_tcb->process = process;
|
||||||
new_tcb->next = NULL;
|
new_tcb->next = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user