multitask switch base software
Posted: Thu Jun 21, 2012 6:52 am
I just want to realize multitask switch base software.
//the main function
//the create thread function
//the schedule algorithm
// timer callback function
//test functions
when I run the kernel, I found it loop on the fun1 function and print some "b" on the screen. Through debug it, I found the timer callback function only run one times, and funtion fn didn't run,at the same time IF flags was enabled.
//the main function
Code: Select all
// the stack size: 4k. move the pointer to the end
uint32_t *stack = kmalloc(0x400) + 0x3F0;
//0x567 is arbitrarily
thread_t *t = create_thread(&fn, (void*)0x567, stack);
init_scheduler(t);
uint32_t *stack1 = kmalloc(0x400) + 0x3F0;
thread_t *t1 = create_thread(&fn1, (void*)0x567, stack1);
init_timer(20);
asm volatile("sti");
for(;;) ;
Code: Select all
thread_t *create_thread(int (*fn)(void*), void *arg, uint32_t *stack)
{
thread_t *thread = (thread_t*)kmalloc(sizeof(thread_t));
memset(thread, 0, sizeof(thread_t));
thread->id = next_tid++;
*--stack = (uint32_t)arg;
*--stack = (uint32_t)&thread_exit;
*--stack = (uint32_t)fn;
thread->esp = (uint32_t)stack;
thread->ebp = 0;
thread->eflags = 0x200;
thread_is_ready(thread);
return thread;
}
Code: Select all
void schedule()
{
if(!ready_queue) return; //deque empty
//iterator through the ready queue to the end
thread_list_t *iterator = ready_queue;
while(iterator->next)
iterator = iterator->next;
//add the old thread to the end of the deque, and remove it from the start
iterator->next = current_thread;
current_thread->next = 0;
thread_list_t *new_thread = ready_queue;
ready_queue = ready_queue->next;
//switch to the new thread.
switch_thread(new_thread);
}
Code: Select all
static void timer_callback(registers_t *regs)
{
tick++;
// if(tick%20)
// return;
monitor_write("Tick: ");
monitor_write_dec(tick);
monitor_write("\n");
schedule();
}
Code: Select all
int fn(void *arg)
{
for(;;)
{
monitor_write("a");
}
return 0;
}
int fn1(void *arg)
{
for(;;)
{
monitor_write("b");
}
return 0;
}
Code: Select all
switch_thread:
mov eax, [current_thread] ;assign the pointer address to eax
mov eax, [eax]
mov [eax+0], esp ; save
mov [eax+4], ebp
mov [eax+8], ebx
mov [eax+12], esi
mov [eax+16], edi
pushf ; update eflags
pop ecx
mov [eax+20], ecx
mov eax, [esp+4] ; argument: pointer address
mov [current_thread], eax ; update pointer
mov eax, [eax] ; the read current_thread object
mov esp, [eax+0] ; load
mov ebp, [eax+4]
mov ebx, [eax+8]
mov esi, [eax+12]
mov edi, [eax+16]
mov eax, [eax+20] ; load eflags
push eax
popf
ret ; esp: the address of function fn. Then jmp there