Why must user threads be mapped to a kernel thread
- A thread is the basic, atomic unit of CPU utilization in computer systems.
- Mostly we consider a process to be the basic unit for CPU utilization but a process maybe further divided into multiple threads of execution. A process can be divided into different tasks or units that can be executed independently and these units are called threads(not to mention a process as a whole is a thread itself).
- Multi threading i.e., creation of multiple threads by a single process is important because sometimes a single thread might have short long I/O bursts and until that burst is entertained other tasks associated with the process that are independent of the I/O burst have to be put on halt, or maybe sometimes 2 or more tasks need to be performed in parallel and with just one single thread of execution that parallelism can’t be achieved.
- For example, a word processor program waits for input from the user but while waiting for input or while it’s taking input it performs some other tasks as well like spell checking, printing output to the screen etc.
Types of threads :
Threads created in a computer system can be of either of the two types –
- User threads
- Kernel threads
Threads can either be created in the address space of the process itself i.e., inside the process without kernel intervention or with kernel intervention.
1. User Threads –
User threads are the threads created by the user with help from a user library and are visible just to the creating process and it’s run time environment (the kernel has no idea about the creation of these threads). User threads just stay in the address space of the creating process and are run and managed by the creating process without kernel intervention i.e., any problems with the execution of these threads are not kernel’s headache.
2. Kernel threads –
Kernel threads on the other hand are created by the kernel and are visible to it. A user process with the help of a provided library asks kernel to create an executable thread for that process and the kernel in turn creates the thread on behalf of the process, and puts it onto it’s list of the available executable threads present. Here the creation, execution and management of the thread is taken care of by the kernel.
Now moving on from the definitions of threads it’s time to answer the question why do we need to map these user threads to kernel threads when the only thing that differs between them is who controls the execution of these threads, kernel or the creating process? Well to understand this point we need to have a look at the diagram given below.
So first of all just to get it out of the way the topmost level of the diagram shows 3 boxes representing 3 different processes in the memory with the first process having 3 user threads in it’s address space second process has 2 of them and so on. The second level of the diagram from the top shows the kernel with each user level process mapped to one kernel thread in the kernel space(why? we will get to it!!) which is specified using arrows, and at the bottom level we have the CPU.
I am using the many to one model to explain the mapping process here but there are other models available for mapping. For more on mapping models for threads please refer to this article.
Scheduling of threads by CPU scheduler :
- Now consider the internal system structure to be something like the diagram shown above. What happens now is that the CPU scheduler in the kernel schedules threads onto the CPU for execution.
- But the catch here is that the scheduler being part of the kernel knows only about the kernel level threads because as mentioned earlier, the kernel has no idea about the existence of user threads since they are created in the address space of the creating process, hence the kernel has no control over them.
- The CPU scheduler program in the kernel just looks at the list of available threads for execution in the “list” of threads that it has and starts scheduling them.
Mapping of User threads :
- But what happens with the user threads? Again as mentioned earlier each process in memory is a “kernel thread” itself that means that the process is also in the list of threads of the kernel. So that means that the kernel maps the user process to one of the kernel threads to execute it.
- All the user threads that are created by a process are executed over the same kernel level thread appointed to the whole process. Whenever it’s the turn for the specified process to execute on the CPU it’s kernel thread is scheduled onto the CPU and hence the process is executed.
- The user threads, since all of them are controlled by the creating process itself, they are to be mapped onto the appointed kernel thread one by one and therefore executed.
- We can think of this whole process as creating a great new product, maybe an electronic gadget or something. If that product is to be sold it has to be sold under a brand name and that brand or company needs to be registered to the government and further that company has to follow the rules and regulations imposed by the government to sell the desired products via shops in the market. Here I am referring to user threads as the product, kernel as government, process as company and shops as kernel threads.
So in a nutshell user threads need to be mapped to kernel threads because it’s the kernel that schedules the thread for execution onto the CPU and for that it must know about the thread that it is scheduling. For a simple process the kernel only knows about the existence of the process and not the user threads created inside of it so the kernel will only schedule the process’s thread (which is a kernel thread) onto the CPU, all the other user threads inside the process have to be mapped one by one onto the kernel thread appointed to the creating process if they have to be executed.