Task switch that can be called from interrupt and directly
Posted: Thu Jul 28, 2016 8:08 am
Hi everyone,
I started a very simple OS (well actually something that can boot) quite a few years ago and somehow I'd like to extend it now At the moment i have the following "chain": boot sector loads boot loader loads 16 bit kernel loads 32 bit kernel where the 32 bit kernel is written in C and the rest in assembler. So far that works well but is still done on a very simple basis (e.g. no paged memory or different segments).
What I'd like to do now is a very basic multi tasking. Therefore I read in the forum and the wiki and decided to base my implementation on a mixture of the following information:
http://wiki.osdev.org/Kernel_Multitasking
http://forum.osdev.org/viewtopic.php?f=1&t=24452
I have created a basic Process structure in C which only contains the SS and ESP values. All other segments, registers and flags are pushed to the stack. Using that technique I have to create and prepare a fake stack when a new process is created and although that's not pretty, it's fine for me at the moment, is quite easy and works fine.
At the moment the task switch is only called from the timer interrupt but in the future I'd like to add a directly triggered task switch e.g. for sleep() or if a lock is not available. The forum post from above contains the following:
Let's imagine the following example: TaskA calls sleep() and its state is suspended (return address being within the sleep method) and TaskB starts to run. At some point in the future a timer interrupt triggers, interrupts TaskB and want's to go back to TaskA. In that case, as TaskA was suspended in sleep(), the signal to the PIC to allow interrupts again won't happen and therefore interrupts will be blocked => scheduler breaks.
I can't figure out how this should work especially as Brendan wrote that it shouldn't be a problem.
Maybe anybody could give me a few hints and point me to the right direction Thanks a lot!
Best regards
Werzi2001
I started a very simple OS (well actually something that can boot) quite a few years ago and somehow I'd like to extend it now At the moment i have the following "chain": boot sector loads boot loader loads 16 bit kernel loads 32 bit kernel where the 32 bit kernel is written in C and the rest in assembler. So far that works well but is still done on a very simple basis (e.g. no paged memory or different segments).
What I'd like to do now is a very basic multi tasking. Therefore I read in the forum and the wiki and decided to base my implementation on a mixture of the following information:
http://wiki.osdev.org/Kernel_Multitasking
http://forum.osdev.org/viewtopic.php?f=1&t=24452
I have created a basic Process structure in C which only contains the SS and ESP values. All other segments, registers and flags are pushed to the stack. Using that technique I have to create and prepare a fake stack when a new process is created and although that's not pretty, it's fine for me at the moment, is quite easy and works fine.
At the moment the task switch is only called from the timer interrupt but in the future I'd like to add a directly triggered task switch e.g. for sleep() or if a lock is not available. The forum post from above contains the following:
That part confuses me a little bit as I don't understand how this (at least in my case) should work. I understand that no matter where the new task was suspended (being in switch_to_task() called by interrupt or direct call) it will just continue at that point but in my case (and as far as I understood it should be that way) the interrupt routine contains the signal to the PIC to allow interrupts again after the routine was finished:Brendan wrote:The code path into and out of the "switch_to_task()" function will remain the same in all cases; and that's all that matters. The "switch_to_task()" function switches to the new task, then the new task returns to whatever that new task was doing before it called "switch_to_task()" (which may be an IRQ handler, "Reschedule()", any other kernel function, an exception handler or any anything else).eryjus wrote:For example: ProcessA is in the ready queue with its own stack and the stack was left in a state where it was preempted through the timer interrupt. ProcessB, the current process, now enters a blocked state (such as sleep()), and therefore needs to give up the processor to the next process on the ready queue. Since the kernel function will call Reschedule without going through the interrupt handler, ProcessA will receive control and will exit in a different manner than it went in, meaning the code path in and the code path out will not match.
Code: Select all
mov al, 20h
out A0h, al
out 20h, al
I can't figure out how this should work especially as Brendan wrote that it shouldn't be a problem.
Maybe anybody could give me a few hints and point me to the right direction Thanks a lot!
Best regards
Werzi2001