Xv6 scheduler context - why?
Posted: Wed Mar 20, 2024 8:31 am
One thing that has intruiged me about Xv6 is its use of a scheduler thread per core.
When Xv6 is to schedule another process, it first switches context to the scheduler context, picks out the next process to execute, then switches context to that next process.
From the text, it says it does this so it doesn't stay in the old process context, which could be a problem if there is no next context to use.
In my kernel, I just have an idle thread context, which is always executable and never knowingly sleeps (it doesn't execute user code, it doesn't use file backed memory so it shouldn't sleep in page faults) so my schedule always has a thread to run next (I schedule threads, not processes).
I'm just wondering what other people use, an idle process/thread or a scheduler context?
And why?
For the idle process/thread, the benefits I see are:
Of course, there is more to a process context than just the state managed by setjmp/longjmp. A user level process will have an address space as well. It may be using floating point registers. Of course, those can be handled with lazy switching in both scenarios, so I don't see that as an issue, as the scheduler context will have neither floating point state nor a user process address space, so we can use lazy switching there as well.
I think I might have just talked myself into a Xv6 style scheduler thread, but curious what other people think or use?
When Xv6 is to schedule another process, it first switches context to the scheduler context, picks out the next process to execute, then switches context to that next process.
From the text, it says it does this so it doesn't stay in the old process context, which could be a problem if there is no next context to use.
In my kernel, I just have an idle thread context, which is always executable and never knowingly sleeps (it doesn't execute user code, it doesn't use file backed memory so it shouldn't sleep in page faults) so my schedule always has a thread to run next (I schedule threads, not processes).
I'm just wondering what other people use, an idle process/thread or a scheduler context?
And why?
For the idle process/thread, the benefits I see are:
- Fewer context switches - Switching to another process/thread is always a single context switch, instead of two.
- An idle process/thread can do stuff that you'd rather do at idle. In my kernel, I run my garbage collector in the idle thread. But you could do things like clean unused pages, buillding up a cache of zeroed pages so they can be quickly allocated as is when needed.
- I like the separation of running the scheduler outside of any single process/thread context. If there truly is no other process/thread to schedule, you're not left in the context of the last process/thread, which could be racking up CPU usage unnecessarily.
- You can ease restrictions on idle level processes/threads, so they may sleep, but can still do the idle work you want them to do when there is nothing else to do.
Of course, there is more to a process context than just the state managed by setjmp/longjmp. A user level process will have an address space as well. It may be using floating point registers. Of course, those can be handled with lazy switching in both scenarios, so I don't see that as an issue, as the scheduler context will have neither floating point state nor a user process address space, so we can use lazy switching there as well.
I think I might have just talked myself into a Xv6 style scheduler thread, but curious what other people think or use?