User threads, kernel threads and everything in between

Discussions on more advanced topics such as monolithic vs micro-kernels, transactional memory models, and paging vs segmentation should go here. Use this forum to expand and improve the wiki!
Post Reply
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

User threads, kernel threads and everything in between

Post by sunnysideup »

I've been doing a bit of OsDev, and as I'm moving to process management and so on, I got to thinking about user threads and kernel threads that I've read about in OS books.

So the question is this: Is the number of KERNEL threads equal to the number of kernel stacks that I have? That is, there is a complete correspondence between the two. To me, it makes sense because, after all, the kernel is only called when there is an interrupt (trap, exception, hw, etc.). So having multiple kernel stacks = having multiple kernel threads?

And user-level threads are something managed by a user-space thread library?

So I'm guessing that an OS is one-to-one when each user-level thread has its own kernel stack (and thus a kernel thread).
If the kernel had only one stack, that is, it had a global kernel stack, then the user-space thread library can expose only one user thread to "join" the kernel stack, and this would be a many to one model.

Is this right? If so, what is a many to many model?
nexos
Member
Member
Posts: 1078
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: User threads, kernel threads and everything in between

Post by nexos »

User threads do have a kernel and user stack. The kernel stack is in the Task State Segment. When an exception, IRQ, or ISR occur, you will go into kernel mode, and esp and the segment registers will be loaded from the TSS. You could have one kernel stack for the system, but it would soon overflow as more tasks ran.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: User threads, kernel threads and everything in between

Post by sunnysideup »

Here I am not concerned with any specific underlying hardware (TSS, etc.). I want to understand the concept of many to many, many to one, and one to one threading models.
User avatar
AndrewAPrice
Member
Member
Posts: 2299
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: User threads, kernel threads and everything in between

Post by AndrewAPrice »

sunnysideup wrote:And user-level threads are something managed by a user-space thread library?
The kernel knows about user-thread threads, unless you have some esoteric microkernel that has a thread manager runing in userspace (essentially a thread is a bunch of registers (one being a stack pointer), so a userspace thread manager could tell the kernel "switch to these bunch of registers.") This would be a little extreme, and performance would suffer a little (3 context switches instead of 1 when your timer fires), so many microkernels do keep threading and scheduling in the kernel.

With that being said, a user-space thread library could just be a wrapper over your system calls to create a thread, wake a thread, etc.
sunnysideup wrote:So I'm guessing that an OS is one-to-one when each user-level thread has its own kernel stack (and thus a kernel thread).
I only have one kernel stack that I switch to for entering syscalls and interrupts.

Being a microkernel, I have no "kernel threads" only interrupt and syscall handlers. When I support multiple CPU cores, I will have one stack per core.
Last edited by AndrewAPrice on Tue May 19, 2020 2:21 pm, edited 1 time in total.
My OS is Perception.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: User threads, kernel threads and everything in between

Post by sunnysideup »

Take a look at this article: https://www.tutorialspoint.com/operatin ... eading.htm

It describes multi threading models, which is also described in almost all standard OS books (dinosaur book, AST, etc. ) And the article says this while describing user threads: "In this case, the thread management kernel is not aware of the existence of threads. The thread library contains code for creating and destroying threads, for passing message and data between threads, for scheduling thread execution and for saving and restoring thread contexts. The application starts with a single thread."

This clearly says that the kernel doesn't know about threads. Perhaps this model isn't used nowadays, but still... This is a forum for OS theory after all.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: User threads, kernel threads and everything in between

Post by sunnysideup »

In your microkernel system, how do you do syscalls (traps - not necessarily the syscall instruction)? I'm not sure how it'd work on a microkernel, especially blocking syscalls.
User avatar
AndrewAPrice
Member
Member
Posts: 2299
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: User threads, kernel threads and everything in between

Post by AndrewAPrice »

sunnysideup wrote:In your microkernel system, how do you do syscalls (traps - not necessarily the syscall instruction)? I'm not sure how it'd work on a microkernel, especially blocking syscalls.
My microkernel runs in long-mode, so what I say might not apply for real and protected mode:

In the TSS, you can select what stack to use for syscalls and interrupts (and you can even specify multiple stacks if you want to handle nested interrupts, such as catching if your interrupt handler code segfaults.)

For me, I have one kernel stack, which I share between syscalls and interrupts.

There is a bit in the FLAGS register (bit 9) that tells the CPU if interrupts are enabled. When you use syscall/sysret, the kernel masks FLAGS with SFMASK. So if you set bit 9 in SFMASK, interrupts will be disabled upon entering a syscall, and re-enabled upon sysret.

Being a micro-kernel, my kernel is limited to scheduling, memory management, and messaging. I don't have any need for kernel threads, so the only way kernel code gets triggered is via an interrupt or syscall, and since interrupts won't trigger syscalls, and syscalls disable interrupts, kernel code won't interrupt kernel code and I only need one kernel stack.

When I implement multi-core support in the future, my plan is to have one TSS and kernel stack per processor, and use spin-locks around my data structures.
My OS is Perception.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: User threads, kernel threads and everything in between

Post by sunnysideup »

So how do you deal with blocking syscalls? For example, a syscall that waits for some hardware interrupt like a key press. Or you don't have blocking syscalls at all?
User avatar
AndrewAPrice
Member
Member
Posts: 2299
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: User threads, kernel threads and everything in between

Post by AndrewAPrice »

I do have blocking syscalls but you can implement them by putting the caller to sleep (unscheduling the user thread) and returning from the syscall into the next scheduled thread.

You context switch by returning from the syscall loading in a different set of registers than what the syscall was called with.
My OS is Perception.
Post Reply