The problem is in the first couple of functions, but I added the rest to give anyone an idea of the bigger picture, if they want it.
Code: Select all
#include <system.h>
extern u32int read_eip();
u32int next_thread_id = 1;
volatile thread_t *current_thread = 0;
void threads_install()
{
current_thread = (thread_t*)kmalloc(sizeof(thread_t));
current_thread->stack_start = initial_esp;
new_stack(current_thread);
asm volatile("mov %0, %%esp" :: "r"(current_thread->esp));
asm volatile("mov %0, %%ebp" :: "r"(current_thread->ebp));
current_thread->id = next_thread_id++;
current_thread->status = 0;
current_thread->next = current_thread;
current_thread->previous = current_thread;
current_thread->priority = 20;
current_thread->counter = 20;
// loops from here back up to the asm part, infinitely
}
void new_stack(thread_t *thread)
{
u32int current_esp, current_ebp, size, stack, offset, new_stack_start, i;
asm volatile("mov %%esp, %0" : "=r"(current_esp));
asm volatile("mov %%ebp, %0" : "=r"(current_ebp));
size = current_thread->stack_start - current_esp;
stack = (u32int)kmalloc(0x2000); // reserve 8192 bytes for stack
// start of stack is at _end_ of allocation
new_stack_start = stack + 0x2000;
offset = new_stack_start - current_thread->stack_start;
// find the esp and ebp for the new stack
thread->stack_start = new_stack_start;
thread->esp = current_esp + offset;
thread->ebp = current_ebp + offset;
// copy over the old stack to the new one
memcpyd((u32int*)thread->esp, (u32int*)current_esp, size);
u32int *tmp;
for (tmp = thread->esp; tmp <= thread->stack_start; tmp++)
{
if (*tmp < current_thread->stack_start && *tmp > current_esp)
{
*tmp += offset;
}
}
thread->stack_start = new_stack_start;
thread->stack_size = size;
}
u32int fork()
{ // make new thread
thread_t *parent_thread = (thread_t*)current_thread;
thread_t *new_thread = (thread_t*)kmalloc(sizeof(thread_t));
new_thread-> id = next_thread_id++;
new_thread->next = parent_thread->next;
new_thread->next->previous = new_thread;
parent_thread->next = new_thread;
new_thread->previous = parent_thread;
new_thread->priority = parent_thread->priority;
new_thread->counter = new_thread->priority;
new_thread->status = 1; // halted
// entry point
u32int eip = read_eip();
if (current_thread == parent_thread)
{
asm volatile("cli");
new_stack(new_thread);
new_thread->status = 0; // running
asm volatile("sti");
return new_thread->id;
}
else
{
return 0;
}
}
void switch_thread()
{
// reset counter
current_thread->counter = current_thread->priority;
// get stack
u32int esp, ebp, eip;
asm volatile("mov %%esp, %0" : "=r"(esp));
asm volatile("mov %%ebp, %0" : "=r"(ebp));
// get the eip
eip = read_eip();
if (eip == 0x12345) return;
// save stack
current_thread->esp = esp;
current_thread->ebp = ebp;
// advance current_thread
do current_thread = current_thread->next;
while (current_thread->status);
esp = current_thread->esp;
ebp = current_thread->ebp;
__asm__ __volatile__("\
mov %0, %%ecx; \
mov %1, %%esp; \
mov %2, %%ebp; \
mov $0x12345, %%eax; \
jmp *%%ecx" :: "r"(eip), "r"(esp), "r"(ebp) : "%eax", "%ecx");
}
u32int get_pid()
{
return current_thread->id;
}