Linux Kernel Support for Threads (Light Weight Processes)

Yes, Linux supports threads. Thread is also a context of execution like the processes. We can do programming with threads. The further discussion on this topic is with respect to the Linux 2.6 kernel. As of now, there is support for muliple threads in the Linux kernel and in the user space, we make utilize of the Threads library like POSIX threads. The way POSIX threads is implemented in Linux is different from other Operating Systems (Because they are no specific system calls for dealing with threads)

So the question arises if Linux does not have any system calls corresponding to threads creation, how are the POSIX threads created. And if POSIX thread implementation is done in the user space alone, there are many issues that has to be dealt with. Let’s think that POSIX thread is implemented completely in the user space, so the scheduling of threads is to be done by the POSIX threads library itself.

Threads must be light weight in the sense that all the threads in the same process share the same address space. Implementing POSIX threads in the user space can solve this issue. Because threads are nothing but an abstraction to the programmer. He/she enjoys some of the benefits of threads. But if one of the threads is blocked on a particular system call like read, the whole process will be blocked because the very idea of the threads is transparent to the kernel. So all the benefits of threads can not be utilized.

So how is this issue solved in Linux? It is done by implementing the so called ‘Light weight processes’. A fork() system call creates a new process. If the child process does not have any execve() like system calls, both the child and the parent process share the same address space for the text(program code). And the data address space is marked as ‘Copy on write’ that is in the beginning both the child and the parent process share the same data adrress space, but any attempt of changing the data by the child will result in creating a new data address space for the child.

Since now we got an idea about how the fork() system call works, we can now think about implementing threads. As we know that threads in the same process share the same address space for text and data, so we need not set any ‘Copy on write’. The issues of data synchroniztion which comes up when two threads access the same data varible has to be worked upon by the programmer.

There is a system call called clone called clone() or clone2() which helps in creating a child process but unlike fork(), we have more control on deciding the behaviour of the child process whether we want to have the new child share the same filesystem information, file descriptor table, signal handler table or the memory space of the parent. In fact the threads library makes use of the clone() system call to create new threads.

So by this time, we got an idea that threads in Linux are nothing but processes or better to be called ‘Light weight processes'(because of the sharing of data).

There is an advantage of this way of implementation. To the kernel everything is seen as processes and the scheduler has nothing to think about separate scheduling techniques for threads and processes. This makes the implementation as simple as possible and also solves the above blocking problem of the threads implementation in user space.

Let’s check a small snippet of code

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
  void * function1(void *arg)
   pthread_t tid=pthread_self();
   printf("In thread %u and process %u\n",tid,getpid());

void * function2(void *arg)
   pthread_t tid=pthread_self();
   printf("In thread %u and process %u\n",tid,getpid());

int main()
   void *status;
   pthread_t tid1,tid2;
   pthread_attr_t attr;



   printf("In main thread %u and process %u\n",pthread_self(),getpid());

To compile this program

$gcc thread.c -lpthread

On Executing, the output is

In thread 3086625680 and process 5480
In thread 3076135824 and process 5480
In main thread 3086628544 and process 5480

How can this be possible? By our above discussion, we found that threads are nothing but light weight processes. But getpid() (which returns the Process ID) gives same PID for all the processes. This is because the POSIX standard says that the threads must return the same PID (based on the assumption that they all are running in the same process). To deal with this issue, Linux introduced a tgid(Thread group Leader ID) field. The tgid is same as the PID of the first light weight process in the threads group(Group of threads created by a process including itself). System calls like getpid() has been so designed that they return the tgid of the process instead of the PID, thus threads in the same thread group get the same value from getpid().


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s