Code: Select all
u32int next_thread_id = 1;
volatile thread_t *current_thread = 0;
void new_stack(thread_t *thread, u32int current_esp, u32int current_ebp)
{
u32int size, offset, new_stack_start, i;
size = current_thread->stack_start - current_esp;
thread->stack = (u32int)malloc(0x2000); // reserve 8192 bytes for stack
// start of stack is at _end_ of allocation
new_stack_start = thread->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;
}
void threads_install()
{
u32int esp, ebp;
current_thread = (thread_t*)malloc(sizeof(thread_t));
current_thread->stack_start = initial_esp;
asm volatile("mov %%esp, %0" : "=r"(esp));
asm volatile("mov %%ebp, %0" : "=r"(ebp));
new_stack(current_thread, esp, ebp);
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;
}
u32int fork()
{ // make new thread
__asm__ __volatile__("cli");
thread_t *parent_thread = (thread_t*)current_thread;
thread_t *new_thread = (thread_t*)malloc(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; // ready
current_thread->counter = 0;
switch_thread(); // force switch to new thread
__asm__ __volatile__("sti");
if (current_thread == parent_thread)
return new_thread->id;
return 0;
}
void switch_thread()
{
if (current_thread->counter)
{
current_thread->counter--;
return;
}
if (current_thread->next == current_thread) return;
// reset counter
current_thread->counter = current_thread->priority;
// get stack
u32int esp, ebp;
asm volatile("mov %%esp, %0" : "=r"(esp));
asm volatile("mov %%ebp, %0" : "=r"(ebp));
// save stack
current_thread->esp = esp;
current_thread->ebp = ebp;
// advance current_thread
thread_t *working_thread = current_thread;
do
{
working_thread = working_thread->next;
switch (working_thread->status)
{
case 1: // ready
new_stack(working_thread, esp, ebp);
working_thread->status = 0;
break;
case 3: // zombie
working_thread->previous->next = working_thread->next;
working_thread->next->previous = working_thread->previous;
free(working_thread->stack);
free(working_thread);
break;
}
}
while (working_thread->status);
current_thread = working_thread;
// switch stack
esp = current_thread->esp;
ebp = current_thread->ebp;
/// CRASH ///
__asm__ __volatile__("mov %0, %%esp" :: "r"(esp));
__asm__ __volatile__("mov %0, %%ebp" :: "r"(ebp));
}
void exit()
{
current_thread->status = 3; // zombie
current_thread->counter = 0;
switch_thread();
panic("Failed to kill thread\n");
}
u32int get_pid()
{
return current_thread->id;
}