Four beginner questions on multitasking
Four beginner questions on multitasking
I've got a working "Bona Fide - Bran's Kernel Dev Tut" based kernel, and now I've been reading everything I can find on preemptive multitasking.
But I still have some unanswered questions:
1. Once I've done multitasking, if I want to play with VESA 2.0 switching to (un)real mode for VESA calls would be simplest, right? GRUB probably leaves the important parts of the first megabyte untouched, right?
2. Does software multitasking usually involve any TSSs? or are they only for hardware multitasking?
3. Would it be a bad idea to have only one kernel stack? Why?
4. User stacks in a flat memory model: a fixed size like 16K is reasonable for a small toy OS, right? I don't need something complicated like stacks that dynamically expand downward, do I?
But I still have some unanswered questions:
1. Once I've done multitasking, if I want to play with VESA 2.0 switching to (un)real mode for VESA calls would be simplest, right? GRUB probably leaves the important parts of the first megabyte untouched, right?
2. Does software multitasking usually involve any TSSs? or are they only for hardware multitasking?
3. Would it be a bad idea to have only one kernel stack? Why?
4. User stacks in a flat memory model: a fixed size like 16K is reasonable for a small toy OS, right? I don't need something complicated like stacks that dynamically expand downward, do I?
Re:Four beginner questions on multitasking
As for TSSs: They are not required unless you want to run some tasks at a lower privelage level. During a task state switch from a low to a higher level, the processor will load/save values to the currently active TSS, no matter what.
Each task should have its own kernel stack, because each task could call a kernel function at the same time. If there was only one kernel stack, either each task would have to wait, or it'd corrupt that one stack. In my opinion, not very fun .
As for stack size: For a toy OS, this could work. But it's still very impractical, and I'd recommend not doing it.
Each task should have its own kernel stack, because each task could call a kernel function at the same time. If there was only one kernel stack, either each task would have to wait, or it'd corrupt that one stack. In my opinion, not very fun .
As for stack size: For a toy OS, this could work. But it's still very impractical, and I'd recommend not doing it.
Re:Four beginner questions on multitasking
Hello,
You mention that fixed sized stacks bad. How do you handle multi-threaded processes? Surely each thread has to have a fixed size stack???? I can't imagine how to handle multiple threads each with dynamically expanding stacks (in the same address space).
Does each task / thread really need its own kernel stack? Say there are 1000 threads / processes..... thats a lot of space! Wouldn't it be possible to have one kernel stack per (virtual) CPU?
I would love to hear everyone's opinions.....
You mention that fixed sized stacks bad. How do you handle multi-threaded processes? Surely each thread has to have a fixed size stack???? I can't imagine how to handle multiple threads each with dynamically expanding stacks (in the same address space).
Does each task / thread really need its own kernel stack? Say there are 1000 threads / processes..... thats a lot of space! Wouldn't it be possible to have one kernel stack per (virtual) CPU?
I would love to hear everyone's opinions.....
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Four beginner questions on multitasking
@tom: you 'd need atleast some space for task state saving in the tcb ere switching to the global kernel stack.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:Four beginner questions on multitasking
Hi,
It is possible to use no TSSs (if all of your code runs at CPL=0) and it's also possible to use software task switching and hardware task switching - for e.g. use hardware task switching for some exception handlers (page fault, double fault, etc). I wouldn't bother using hardware task switching for exception handlers unless you allow those exceptions to be handled by non-kernel code.
The main thing to consider would be how long the most expensive "kernel operation" takes, as this would determine the worse case increase in response times.
For example, if there's something in the kernel that does 2 seconds of processing that is being used by a very low priority task, and the user presses a key which causes a very high priority task to become "ready to run", then the very high priority task would have to wait for up to 2 seconds for the kernel stack to become available before the very high priority task could get CPU time.
It's not quite that simple though - there's things that a "single stack" kernel can do to improve response times. For e.g. split lengthy operations into several smaller operations seperated by "interruption points" (where the kernel stops, checks for pending task switches and aborts or postpones the operation if something is pending). Of course anything like this would increase the complexity again.
There's also the "memory usage" - an OS with 1024 tasks where every task has a 4 KB kernel stack will consume 4 MB just for kernel stacks, even though most of those kernel stacks don't need to be used at the same time.
There is also a third option - dynamic kernel stacks. Here you have "N stacks per CPU" rather than "one stack per CPU" or "1 stack per task". This solves the kernel re-entrancy/response time problem and also minimizes the memory usage, but it's probably the most complicated method. Depending on the how the rest of the kernel is designed it might be pointless.
The "normal" approach is to reserve a large amount of space for the stack, and then allocate actual RAM only when it's needed. For example, you could reserved 2 MB of space but only use 4 KB of RAM. It's also relatively easy to allow the user code to specify how much space to reserve for it's stack. For example, you could read a value from the executable's header and then reserve between 512 MB and 4 KB of space (and still only allocate RAM for it if/when it's needed).
Cheers,
Brendan
GRUB does leave everything useful in the first 1 MB untouched (it does use free RAM, but that shouldn't matter) - I've switched back to real mode and used VESA/VBE, keyboard, etc before without problems.StringCheesian wrote:1. Once I've done multitasking, if I want to play with VESA 2.0 switching to (un)real mode for VESA calls would be simplest, right? GRUB probably leaves the important parts of the first megabyte untouched, right?
Usually it involves one TSS to hold SS0 and ESP0 (used by the CPU when switching from CPL = 3 to CPL = 0), and possibly SS1, ESP1, SS2 and ESP2 (if you use CPL=1 and CPL=2), and maybe an I/O permission bitmap and/or interrupt redirection bitmap (if you need I/O port protection or faster virtual 8086 mode).StringCheesian wrote:2. Does software multitasking usually involve any TSSs? or are they only for hardware multitasking?
It is possible to use no TSSs (if all of your code runs at CPL=0) and it's also possible to use software task switching and hardware task switching - for e.g. use hardware task switching for some exception handlers (page fault, double fault, etc). I wouldn't bother using hardware task switching for exception handlers unless you allow those exceptions to be handled by non-kernel code.
That depends. With only one kernel stack, the kernel can't be re-entrant, which can increase response times. For a monolithic kernel this can be very bad, but for a micro-kernel the response times might not be increased by much and the kernel itself might be faster (due to reduced complexity).StringCheesian wrote:3. Would it be a bad idea to have only one kernel stack? Why?
The main thing to consider would be how long the most expensive "kernel operation" takes, as this would determine the worse case increase in response times.
For example, if there's something in the kernel that does 2 seconds of processing that is being used by a very low priority task, and the user presses a key which causes a very high priority task to become "ready to run", then the very high priority task would have to wait for up to 2 seconds for the kernel stack to become available before the very high priority task could get CPU time.
It's not quite that simple though - there's things that a "single stack" kernel can do to improve response times. For e.g. split lengthy operations into several smaller operations seperated by "interruption points" (where the kernel stops, checks for pending task switches and aborts or postpones the operation if something is pending). Of course anything like this would increase the complexity again.
There's also the "memory usage" - an OS with 1024 tasks where every task has a 4 KB kernel stack will consume 4 MB just for kernel stacks, even though most of those kernel stacks don't need to be used at the same time.
There is also a third option - dynamic kernel stacks. Here you have "N stacks per CPU" rather than "one stack per CPU" or "1 stack per task". This solves the kernel re-entrancy/response time problem and also minimizes the memory usage, but it's probably the most complicated method. Depending on the how the rest of the kernel is designed it might be pointless.
The amount of stack space required by any piece of code depends on that piece of code, and can't be determined accurately without first analyzing that code. I've done software that needs less than 256 bytes of stack space, but I've done applications (in C with recursion) that use a lot more stack space.StringCheesian wrote:4. User stacks in a flat memory model: a fixed size like 16K is reasonable for a small toy OS, right? I don't need something complicated like stacks that dynamically expand downward, do I?
The "normal" approach is to reserve a large amount of space for the stack, and then allocate actual RAM only when it's needed. For example, you could reserved 2 MB of space but only use 4 KB of RAM. It's also relatively easy to allow the user code to specify how much space to reserve for it's stack. For example, you could read a value from the executable's header and then reserve between 512 MB and 4 KB of space (and still only allocate RAM for it if/when it's needed).
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Four beginner questions on multitasking
Hello,
How does Linux handle the task kernel stacks problem? Does anyone know?
As stated above if you have 1024 processes a stack per task / thread could chew up a lot of memory.
How does Linux handle the task kernel stacks problem? Does anyone know?
As stated above if you have 1024 processes a stack per task / thread could chew up a lot of memory.
Re:Four beginner questions on multitasking
Heres a demo i made for swiching to and from realmode for vesa, mode switching, may help.
http://www.dex4u.com/images/DemoVesa.zip
But it does not use grub, it users "bootprog".
http://www.dex4u.com/images/DemoVesa.zip
But it does not use grub, it users "bootprog".
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Four beginner questions on multitasking
iirc, linux dedicates one page of kernel stack for every created thread. The exact size depends on the architecture (64-bit systems for instance have 16K while a x86 PC will have only 4K).
Re:Four beginner questions on multitasking
If you're running 1024 tasks on a single system it shouldn't be a small system to start with. Further more, all tasks need a process image (shared or nonshared, it still needs to be there at least for this task) and other kernel-bound resources. That means they'll take up resources no matter what. A single page for a start-up thread will be expanded pretty quickly in most cases, so there's no loss (and nothing to gain) there.
Re:Four beginner questions on multitasking
Cjmovie and Brendan, your posts were extremely imformative - thank you!
Dex4u, thank you. It's very readable and well commented. And it does exactly what I had in mind. I'll study it and try to write my own without copying yours.
Dex4u, thank you. It's very readable and well commented. And it does exactly what I had in mind. I'll study it and try to write my own without copying yours.