Page 1 of 1

Questions about kernel multitasking

Posted: Mon Apr 27, 2020 5:49 pm
by mrjbom
Hi.
I want to implement multitasking in my core. To do this, I took the code from this article.
And I have some questions about the code in this article and so on.
There are 2 lines in the createTask() function that I don't understand

Code: Select all

task->regs.cr3 = (uint32_t) pagedir;
task->regs.esp = (uint32_t) allocPage() + 0x1000;
What does the first line do? What is pagedir?
What does the second line do? As far as I understand, this is a thread stack.
How can I release a dedicated page when I don't need it? When do I call free to release a selected page(allocPage() as far as I understand allocates one page of memory)?
Explain how this code works.

I'm also wondering how I can automatically switch between threads, maybe use timers or something like that.

The article says that this is not quite "correct" multitasking, what should I use for my tasks?
Thanks.

Re: Questions about kernel multitasking

Posted: Mon Apr 27, 2020 9:38 pm
by nullplan
mrjbom wrote:Explain how this code works.
It doesn't. Not as given, anyway. It is merely illustrative. The first of your quoted lines sets the in-memory version of CR3 to the last argument of the function. For a reason I have not figured out yet, many tutorials represent physical addresses as pointers (they aren't, since you cannot dereference them directly). That's why it is given in that form. It actually should just be called CR3 and have type uintptr_t. The reason you have to switch CR3 on task switch is that all user space processes have a different address space in the user space half. Optimization: If you are switching to a kernel task, you don't need to load CR3. Saves a TLB flush.

The second line... yeah, that won't work that way. The way I do it is: I allocate two contiguous pages, put the task struct right at the end of the allocation, and use everything before it as stack. I never deallocate this structure again; if the task finishes, I mark it as Condemned, and it can be resurrected by the task allocator.
mrjbom wrote:I'm also wondering how I can automatically switch between threads, maybe use timers or something like that.
I tried to keep the structure of my task switcher simple, so here is how that works: Whenever something returns to user space (interrupt or syscall), I test the task flags of the current tasks for "signal pending" and "task timeout". If either is set, I reenter the kernel in a function that handles these states. The handler for "signal pending" is not relevant here. For "task timeout", it calls schedule() once and returns. schedule() will remove the "task timeout" flag, then pick the next task to run and switch there. Since the then-current task is still runnable, eventually execution will resume where it left off. Now the only thing left to do is install a timer interrupt handler that sets the "task timeout" flag.
mrjbom wrote:The article says that this is not quite "correct" multitasking, what should I use for my tasks?
Well, lots of details were left out. And those details make the task switcher more complicated. You have to handle debug registers in it, and FPU, and SSE/AVX, etc. Or at the very least set the TS bit in CR0. There are optimizations like I alluded to above: Kernel tasks can use any address space and don't need CR3 reloaded. And the detail of how to pick the next task is entirely left out.

The code in that article is meant as illustration of the principles involved, not as cut-n-paste solution.

Re: Questions about kernel multitasking

Posted: Tue Apr 28, 2020 5:30 am
by mrjbom
nullplan wrote:
mrjbom wrote:Explain how this code works.
It doesn't. Not as given, anyway. It is merely illustrative. The first of...
I didn't understand much, but thank you for your answer.

Re: Questions about kernel multitasking

Posted: Thu Jul 30, 2020 7:30 am
by LukeyTheKid
Reading this:
Optimization: If you are switching to a kernel task, you don't need to load CR3. Saves a TLB flush.
and this:
Kernel tasks can use any address space and don't need CR3 reloaded
I'm guessing this is based on the kernel being mapped into each process, so kernel addresses are always valid no matter what the address space?

Re: Questions about kernel multitasking

Posted: Thu Jul 30, 2020 9:32 am
by nullplan
LukeyTheKid wrote:I'm guessing this is based on the kernel being mapped into each process, so kernel addresses are always valid no matter what the address space?
Yes. This is normal for a higher-half kernel, which is what most people are familiar with. The only other design I know is to forego virtual memory at all (which, for example, OS-9 uses), and only use the mechanism for memory protection (essentially, everything is identity mapped in those systems). For those OSes the same strategy applies. I am not aware of any other design that is still being used.