Gut,
dann poste ich mal etwas code:
Funktion zum wechseln des Prozesses:
u32int_t multitasking_schedule(u32int_t context)
{
printf("Schedule begin... ");
// Save current task in local variable
task_t *current = multitasking_management_unit.current_task, *next = NULL;
if(!multitasking_initialised)
return(context);
printf("%i - ", (current!=NULL)?current->id:0);
// is current task set, then we need to save page directory
if(current != NULL)
current->cr3 = (u32int_t*)multitasking_get_cr3();
// do we need to change page directory?
if(!vmm_kernel_directory_loaded())
vmm_load_kernel_directory();
// get the next task
next = multitasking_get_next_task(current);
if(next == NULL)
{
// Switch to tasks page directory
vmm_switch_page_directory(next->cr3);
return(context);
}
// switch to next when next state is blocked
while(next->state != MULTITASKING_READY_FOR_EXECUTION)
{
printf("\tcurrent task is blocked!\n");
next = multitasking_get_next_task(next);
}
// context needs to be saved when Multitasking is going around
// not directly after initialising it
if(current != NULL)
{
printf("0x%x - 0x%x - ", ((struct regs*)context)->esp, context);
current->kernel_stack = ((struct regs*)context)->esp;
//current->kernel_stack = context;
}
// Reset current_task to next
multitasking_management_unit.current_task = next;
printf("%i ", next->id);
// Switch to tasks page directory
vmm_switch_page_directory(next->cr3);
printf("...Schedule end\n");
// and at last return the new stack
return(next->kernel_stack);
}
IRQ-Handler (hier wird die Funktion zum wechseln des Prozesses aufgerufen):
u32int_t irq_handler(u32int_t context)
{
struct regs *r = (struct regs *)context;
u32int_t new_esp;
/* This is a blank function pointer */
void (*handler)(struct regs *r);
/* Find out if we have a custom handler to run this
* IRQ, and finally run it */
handler = irq_routines[r->int_no - 32];
if(handler)
handler(r);
/* Try to schedule to next task */
new_esp = multitasking_schedule(context);
/* If the IDT entry that was invoked was greater than 40
* (meaning IRQ8 - 15), then we need to send EOI to
* the slave controller */
if(r->int_no >= 40)
outportb(0xA0, 0x20);
/* In either case, we need to send an EOI to the master
* internet controller too */
outportb(0x20, 0x20);
/* at last return new/old esp */
return(new_esp);
}
Als letztes noch den ASM-Part, der den Interrupthandler aufruft:
; 32: irq0
irq0:
cli
push byte 0 ; Note that these don't push an error_code onto the stack:
; We need to push a dummy error code
push byte 32
jmp irq_common_stub
...
irq_common_stub:
; store registers
pusha
push ds
push es
push fs
push gs
; Load the Kernel Data Segment descriptor!
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; Call C-Handler
push esp
call irq_handler
add esp, 4
; change stack
mov esp, eax
; restore registers
pop gs
pop fs
pop es
pop ds
popa
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS and ESP
Das Ausführen der Prozesse, sofern diese noch nicht ausgeführt wurden, funktioniert einwandfrei. Doch sobald vom letzten zum ersten geschaltet wird, tritt ein Fehler auf. Also muss ja folglich die Adresse in ESP falsch sein, oder ich mache etwas falsch...
Bei Bedarf packe ich den kompletten code mal als zip und lade ihn hoch...
Gruß Christian