Hi, I recently (within the past year) began research into kernel development. I have gotten as far as basic FS functionality, and multitasking (of the basics like IDT, GDT, etc... are implied), but it didn't work quite right, and there were numerous bugs. With the knowledge from tutorials, and experimentation from my first attempt, I created a new project from scratch, hoping to fix major design flaws which were due to my ignorance on the subject at the beginning, and the fact that I had about 12 different tutorials mixed together which means about 13 different coding styles all together.

This overhaul has actually been good. I have a better interface into the IDT, and paging mechanisms and actually have a nice system call interface (based also off of the linux way, int 80h).

Now, all of that was so that no one blew me off as some complete noob not knowing anything at all (granted I don't claim to be a master on the subject :P).

My real question:

I understand how the scheduler actually switches tasks in switch_to (switch stacks, grab saved state, etc...), but what I don't understand is how that would work in the middle of an interrupt (say, a timer interrupt). When schedule() is called, it never returns (assuming that a schedule happens) so when you call schedule() inside an interrupt (specifically an IRQ) wouldn't the new stack and return from switch_to outside the IRQ handler and never send a ACK to the PIC(s), therefore no more IRQs until that task switches back again (which assumes the new task will voluntarily call schedule on its own, since no other tasks can run (including any kernel functions) without interrupts).

For anyone who is better at visualizing with code (like me) here is an example:

Code:
task1:
   mov eax,0
.1:
   cmp eax,0
      je .2
   jmp .1
.2:
   call schedule
   inc eax
   jmp .1

task2:
   xchg ecx,ecx
   jmp task2

irq0_handler:
   cmp [quantum_remaining],0
      jne .done
.schedule_me:
   call schedule
.done:
   outb ... ; I forget the exact acknowledge commands...
   iret
I did exclude things like pushing registers on the interrupt handler and things like that, but for my point I think it makes sense. When task1 calls schedule, task2 will begin to run, and use up it's quantum. Once that has happened irq0 will call schedule, and it will continue in task1 where it left off. Here, task1 will never call schedule again, and because the interrupt from task2 never finished (and consequently never sent the IRQ ACK), no more IRQs will be processed.

I must be missing something