I'm just trying to get basic multitasking working but I have some trouble...
First I'm going to post some parts of my sources.
The PIT irq handler code:
Code: Select all
.global irq0_handler
irq0_handler:
cli
pushl $0
pushl $0
pusha
push %ds
andl $0xFFFF, (%esp)
push %es
andl $0xFFFF, (%esp)
push %fs
andl $0xFFFF, (%esp)
mov $KERNEL_DS, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
pushl %esp
call schedule
addl $4, %esp
movl %eax, %esp
pop %fs
pop %es
pop %ds
popa
addl $8, %esp
iret
Code: Select all
register_t schedule( registers_t* regs ) {
thread_t* next;
if ( current == t2 ) {
next = t1;
} else {
next = t2;
}
if ( current != NULL ) {
current->context.esp = ( register_t )regs;
}
kprintf( "next thread: %x\n", next );
outb( 0x20, 0x20 );
return next->context.esp;
}
This is the code I use to initialize the stack of a new thread:
Code: Select all
int arch_create_thread( thread_t* thread, void* entry ) {
registers_t* regs;
register_t* stack;
memset( &thread->context, 0, sizeof( cpu_context_t ) );
stack = ( register_t* )( ( uint8_t* )thread->kernel_stack + PAGE_SIZE );
regs = ( registers_t* )( ( uint8_t* )stack - sizeof( registers_t ) );
memset( regs, 0, sizeof( registers_t ) );
regs->fs = KERNEL_DS;
regs->es = KERNEL_DS;
regs->ds = KERNEL_DS;
regs->cs = KERNEL_CS;
regs->ip = ( unsigned long )entry;
regs->flags = 0x203246;
regs->ss = KERNEL_DS;
regs->sp = ( unsigned long )( stack - 1 );
thread->context.esp = ( register_t )regs;
return 0;
}
Code: Select all
typedef unsigned long register_t;
typedef struct regsisters {
unsigned long fs, es, ds;
unsigned long di, si, bp, ksp, bx, dx, cx, ax;
unsigned long int_number, error_code;
unsigned long ip, cs, flags, sp, ss;
} registers_t;
First time the timer IRQ is fired it calls the scheduler just as I planned and thread #2 will be executed. I see a lot of "2" chars printed by the thread on the screen. At the next timer irq the scheduler is called again and thread #2 is selected. But before getting to the thread again I get a general protection fault. The EIP printed in the gpf handler is 0x101C01. As I see in the disassembly version of the kernel 0x101C01 is not a valid address. The only occurrence of the 0x101C01 address in the disasm. output is before a "call kprintf" in this form: "movl $0x101C01, (%esp)".
Do you have any idea what could cause this kind of problem? Do you see any error in my tasking codes?
Thanks,
k0ksz