Peter
Peter

Reputation: 95

How user level thread talk with kernel level thread

I know there are three thread mapping model in operating system.

  1. One to One
  2. Many to One
  3. Many to Many

In this question I assume we use One to One model.

Let's say, right now I restart my computer, and there are 10 kernel-level threads already running.

After a while, I decide to run a python program which will launch one process with four threads. Three of the threads have to run a function that do a system call.

Here is a question, what is the correct scenario when I run the python program.

a) When a python program start, the kernel will launch another 4 threads in kernel space immediately (so there are 14 threads in kernel space now). When those 3 threads in user level initiate a system call, kernel will map those user-level threads to 3 of 4 kernel-level threads that kernel created when python program start, which also means we will waste 1 kernel-level thread.

b) When a python program start, the kernel will not launch another 4 threads in kernel space immediately. Instead, kernel will create new kernel-level threads whenever those 3 user-level thread initiate a system call and ready to talk with kernel. In this case kernel will just create 3 threads exactly, which also means we will not waste any kernel-level threads.

c) Very similar to second scenario, but in this case when those 3 user-level threads ready to run system call and talk with kernel, what kernel will do is make 3 of kernel-level threads that already created stop doing their current job, and then ask them to do the job that python program ask kernel do.

Which means the scheduler will pick up 3 random kernel-level threads to stop what they're doing, and then store those tasks information to somewhere. After that, scheduler will ask those 3 kernel-level thread to finish the python program job first. In this case we always have only 10 threads in kernel-level.

Any reply and suggested material to study is appreciated!

Upvotes: 2

Views: 745

Answers (2)

artless-noise-bye-due2AI
artless-noise-bye-due2AI

Reputation: 22469

To answer this question directly. You have mixed kernel threads and threading. They are not completely different concepts, but a little different at the OS level. Also, kernel threads may last indefinitely in many cases.

There are at least three types of data,

  1. thread_info - specific schedulable entity; always exists.
  2. task_struct - files open and other specific (not for kernel thread)
  3. A memory management context (usually, but not always).

For kernel threads, there is no memory management nor user space allocations. Kernel threads do have a separate stack in kernel space. Only kernel code may run in the context of the kernel stack, for example on behalf of user space via a syscall. It can also be borrowed during an interrupt; which may cause a context switch.

The initial 10 kernel threads are just a number to add to the total.

b) When a python program start, the kernel will not launch another 4 threads in kernel space immediately. Instead, kernel will create new kernel-level threads whenever those 3 user-level thread initiate a system call and ready to talk with kernel. In this case kernel will just create 3 threads exactly, which also means we will not waste any kernel-level threads.

This is correct. Your pthread_create() will use the same task_struct, which allows the threads to share file handles and static memory. Only the user stack and kernel stack are different. The threads share the same memory management structure as well. This is the only difference from a completely separate process. The context switch is light for a thread as there is no 'mm switch' which may incur all sorts of flushing. This thread_info structure can allow threads to live on different cores for SMP cases.

The thread_info is the only real structure/memory for a kernel thread. thread_info is contained in an 8K region (2 pages) which also contains the kernel stack. It is the only 'schedulable' entity by the kernel. The stack itself contains information on how to return to user space, if it is not a kernel thread.

For user space, we have additional structures which the thread_info has pointers to. So, it is one-to-one at least as far as thread_info goes. It is many-to-one for the other structure/data sets. Ie, the threads share them. For processes, they are typically one-to-one (not for fork(), but execv() type calls).

Upvotes: 0

Jérôme Richard
Jérôme Richard

Reputation: 50846

Kernel threads are like a specialized task responsible for doing a specific operation (not meant to last long). They are not threads waiting for incoming request from user-land threads. Moreover, a system call does not systematically create a kernel thread (see this post for more information and this one for some context about system calls): a kernel thread is started when a background task is required like for dealing with IO requests for example (this post shows a good practical case though the description is a bit deep). Basic system calls just runs in the same user-thread but with higher privileges. Note the kernel functions use a dedicated kernel stack: each user-level thread has 2 stacks on Linux: one for user-land functions and one for kernel-land functions (for sake of security).

As a result, in practice, I think all answers are wrong in usual cases (ie. assuming the target operation do not require to create a kernel thread). If the target system calls done actually require to create kernel threads, then b) is the correct answer. Indeed, kernel threads are like a one-shot specialized task as previously stated. Creating/Destroying new kernel-threads is not much expensive since it is just basically a relatively lightweight task_struct data structure internally.

Upvotes: 3

Related Questions