Multi Threaded Models - Introduction to Operating System - Lecture Notes, Study notes of Operating Systems

Multithreaded Models, User and Kernel level threads, Solaris 2 threads model, POSIX thread, The pthread library, Sample code, Creating a thread, Joining and terminating a thread. Above mentioned are key points of this lecture handout. Virtual University handout for introduction to operating system are in detail and explanatory.

Typology: Study notes

2011/2012

Uploaded on 11/06/2012

ahsen
ahsen 🇵🇰

4.6

(88)

84 documents

1 / 7

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
70
Operating Systems--[CS-604]
Lecture No.13
Operating Systems
Lecture No. 13
Reading Material
UNIX/Linux manual pages pthread_create(), pthread_join(), and
pthread_exit() calls
Chapter 5 of the textbook
Lecture 13 on Virtual TV
Summary
User- and Kernel –level threads
Multi-threading models
Solaris 2 threads model
POSIX threads (the pthread library)
Sample code
User and Kernel Threads
Support for threads may be provided at either user level for user threads or by kernel for
kernel threads.
User threads are supported above kernel and are implemented by a thread library at
the user level. The library provides support for thread creation, scheduling, and
management with no support from the kernel. Since the kernel is unaware of user-level
threads, all thread creation and scheduling are done in the user space without the need for
kernel intervention, and therefore are fast to create and manage. If the kernel is single
threaded, then any user level thread performing a blocking system call will cause the
entire process to block, even if other threads are available to run within the application.
User thread libraries include POSIX Pthreads , Solaris 2 UI-threads, and Mach C-
threads.
Kernel threads are supported directly by the operating system. The kernel performs
the scheduling, creation, and management in kernel space; the kernel level threads are
hence slower to create and manage, compared to user level threads. However since the
kernel is managing threads, if a thread performs a blocking system call, the kernel can
schedule another thread in the application for execution. Windows NT, Windowss 2000,
Solaris, BeOS and Tru64 UNIX support kernel threads.
Multi-threading Models
There are various models for mapping user-level threads to kernel-level threads. We
describe briefly these models, their main characteristics, and examples.
1. Many-to-One: In this model, many user-level threads are supported per kernel
thread, as shown in Figure 13.1. Since only one kernel-level thread supports many
user threads, there is no concurrency. This means that a process blocks when a thread
makes a system call. Examples of these threads are Solaris Green threads POSIX
Pthreads.
pf3
pf4
pf5

Partial preview of the text

Download Multi Threaded Models - Introduction to Operating System - Lecture Notes and more Study notes Operating Systems in PDF only on Docsity!

Operating Systems--[CS-604] Lecture No.

Operating Systems

Lecture No. 13

Reading Material

ƒ UNIX/Linux manual pages pthread_create(), pthread_join(), and pthread_exit() calls ƒ Chapter 5 of the textbook ƒ Lecture 13 on Virtual TV

Summary

ƒ User- and Kernel –level threads ƒ Multi-threading models ƒ Solaris 2 threads model ƒ POSIX threads (the pthread library) ƒ Sample code

User and Kernel Threads

Support for threads may be provided at either user level for user threads or by kernel for kernel threads. User threads are supported above kernel and are implemented by a thread library at the user level. The library provides support for thread creation, scheduling, and management with no support from the kernel. Since the kernel is unaware of user-level threads, all thread creation and scheduling are done in the user space without the need for kernel intervention, and therefore are fast to create and manage. If the kernel is single threaded, then any user level thread performing a blocking system call will cause the entire process to block, even if other threads are available to run within the application. User thread libraries include POSIX Pthreads , Solaris 2 UI-threads, and Mach C- threads. Kernel threads are supported directly by the operating system. The kernel performs the scheduling, creation, and management in kernel space; the kernel level threads are hence slower to create and manage, compared to user level threads. However since the kernel is managing threads, if a thread performs a blocking system call, the kernel can schedule another thread in the application for execution. Windows NT, Windowss 2000, Solaris, BeOS and Tru64 UNIX support kernel threads.

Multi-threading Models

There are various models for mapping user-level threads to kernel-level threads. We describe briefly these models, their main characteristics, and examples.

  1. Many-to-One : In this model, many user-level threads are supported per kernel thread, as shown in Figure 13.1. Since only one kernel-level thread supports many user threads, there is no concurrency. This means that a process blocks when a thread makes a system call. Examples of these threads are Solaris Green threads POSIX Pthreads.

Figure 13.1 Many –to-One Model

  1. One-to-One : In this model, there is a kernel thread for every user thread, as shown in Figure 13.2. Thus, this model provides true concurrency. This means that a process does not block when a thread makes a system call. The main disadvantage of this model is the overhead of creating a kernel thread per user thread. Examples of these threads are WindowsNT, Windows 2000, and OS/2.

Figure 13.2 One-to-One Model

  1. Many-to-One : In this model, multiple user-level threads are multiplexed over a smaller or equal number of kernel threads, as shown in Figure 13.2. Thus, true concurrency is not achieved through this model. Examples of these threads are Solais 2 and HP-UX.

User–level

Threads

Kernel–level

Thread

User–level

Threads

Kernel–level

Threads

P1 P

Creating a Thread You can create a threads by using the pthread_create() call. Here is the syntax of this call.

int pthread_create(pthread_t threadp, const pthread_attr_t attr, void (routine)(void *), arg *arg);

where, ‘threadp’ contains thread ID (TID) of the thread created by the call, ‘attr’ is used to modify the thread attributes (stack size, stack address, detached, joinable, priority, etc.), ‘routine’ is the thread function, and ‘arg’ is any argument we want to pass to the thread function. The argument does not have to be a simple native type; it can be a ‘struct’ of whatever we want to pass in. The pthread_create() call fails and returns the corresponding value if any of the following conditions is detected: ƒ EAGAIN The system-imposed limit on the total number of threads in a process has been exceeded or some system resource has been exceeded (for example, too many LWPs were created). ƒ EINVAL The value specified by ‘attr’ is invalid. ƒ ENOMEM Not enough memory was available to create the new thread. You can do error handling by including the <errno.h> file and incorporating proper error handling code in your programs.

Joining a Thread You can have a thread wait for another thread within the same process by using the pthread_join() call. Here is the syntax of this call.

int pthread_join(pthread_t aThread, void **statusp);

where, ‘aThread’ is the thread ID of the thread to wait for and ‘statusp’ gets the return value of pthread_exit() call made in the process for whom wait is being done. A thread can only wait for a joinable thread in the same process address space; a thread cannot wait for a detached thread. Multiple threads can join with a thread but only one returns successfully; others return with an error that no thread could be found with the given TID

Terminating a Thread You can terminate a thread explicitly by either returning from the thread function or by using the pthread_exit() call. Here is the syntax of the pthread_exit() call.

void pthread_exit(void *valuep);

where, ‘valuep’ is a pointer to the value to be returned to the thread which is waiting for this thread to terminate (i.e., the thread which has executed pthread_join() for this thread). A thread also terminates when the main thread in the process terminates. When a thread terminates with the exit() system call, it terminates the whole process because the purpose of the exit() system call is to terminate a process and not a thread.

Sample Code

The following code shows the use of the pthread library calls discussed above. The program creates a thread and waits for it. The child thread displays the following message on the screen and terminates. Hello, world! ... The threaded version.

As soon as the child thread terminates, the parent comes out of wait, displays the following message and terminates.

Exiting the main function.

#include <stdio.h> #include <stdlib.h> #include <pthread.h> /* Prototype for a function to be passed to our thread / void MyThreadFunc(void arg); int main() { pthread_t aThread; / Create a thread and have it run the MyThreadFunction / pthread_create(&aThread, NULL, MyThreadFunc, NULL); / Parent waits for the aThread thread to exit / pthread_join(aThread, NULL); printf ("Exiting the main function.\n"); return 0; } void MyThreadFunc(void* arg) { printf ("Hello, world! ... The threaded version.\n"); return NULL; }

The following session shows compilation and execution of the above program. Does the output make sense to you?

$ gcc hello.c –o hello –lpthread –D_REENTRANT $ hello Hello, world! ... The threaded version. Exiting the main function. $

Note that you need to take the following steps in order to be able to use the pthread library.

  1. Include <pthread.h> in your program
  2. Link the pthread library with your program (by using the –lpthread option in the compiler command)
  3. Pass the _REENTRANT macro from the command line (or define it in your program)

pthread_t threads[NUM_THREADS]; int *taskids[NUM_THREADS]; int rc, t, sum;

sum=0; messages[0] = "English: Hello World!"; messages[1] = "French: Bonjour, le monde!"; messages[2] = "Spanish: Hola al mundo"; messages[3] = "Klingon: Nuq neH!"; messages[4] = "German: Guten Tag, Welt!"; messages[5] = "Russian: Zdravstvytye, mir!"; messages[6] = "Japan: Sekai e konnichiwa!"; messages[7] = "Latin: Orbis, te saluto!";

for(t=0; t<NUM_THREADS; t++) { sum = sum + t; thread_data_array[t].thread_id = t; thread_data_array[t].sum = sum; thread_data_array[t].message = messages[t]; printf("Creating thread %d\n", t); rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &thread_data_array[t]); if (rc) { printf("ERROR; return code from pthread_create() is %d\n", rc); exit(-1); } } pthread_exit(NULL); }

Reference

The above code was taken from the following website. http://www.llnl.gov/computing/tutorials/pthreads/samples/hello_arg2.c