SLIDE 1 Operating Operating Systems I (1D
Threads (Chapter 4)
(1DT044)
Tuesday february 1 Uppsala University 2011 karl.marklund@it.uu.se
SLIDE 2 PCB
state process id/number program counter registers CPU scheduling information (chapter 5) memory management information (chapter 8) accounting information memory limits I/O status information
In brief, the PCB serves as the repository for any information that may vary from process to process.
SLIDE 3
The text book used in the course
Chapter 4: Threads
Chapter objectives:
★ To introduce the notion of a
thread — a fundamental unit of CPU utilization that forms the basis of multithreaded computer systems.
★ To discuss the APIs for the
Pthreads, Win32, and Java thread libraries.
★ To examine issues related to
multithreaded programming.
SLIDE 4
4.1) Single and Multithreaded Processes
SLIDE 5 4.1.1) Multithreaded Server Architecture
Creating a new process is time consuming and resource intensive compared to creating a new thread. An example of how an server can use threads. One thread listens for client
- requests. When a request is made, the server creates a new thread to service the
request and resume listening fro additional requests. Why not fork a new process for each request?
SLIDE 6 4.1.2) Benefits
What’s so great about threads? Responsiveness
Multithreading an interactive application may allow a program to continue running even if part of it is blocking or performing a lengthy operation, thereby increasing responsiveness to the user.
Resource Sharing
Processes may only share resources through techniques such as shared memory or message passing. Threads (by default) share memory and resources which allows an application to have several threads of execution in the same address space.
Economy
Allocating memory and resources for process creation is costly. Because threads share the resources of the process to which they belong, it is (at least in theory) more economical to create and context-switch threads.
Scalability
The benefits of multithreading can be greatly increased in a multiprocessor architecture, where threads may be running in parallel on different processors.
SLIDE 7
4.1.3) Single-Core CPUs
The core is the part of the processor that actually performs the reading and executing of instructions. Processors were originally developed with only one core. A Single-core processor can process only one instruction at a time. To improve efficiency, processors commonly utilize pipelines internally, which allow several instructions to be processed together; however, they are still consumed into the pipeline one at a time
SLIDE 8
4.1.3) Multi-Core CPUs
A multi-core processor is composed of two or more independent cores. One can describe it as an integrated circuit which has two or more individual processors (called cores in this sense).
SLIDE 9 4.1.3) Multicore Programming
Multi-core give us more computing power - do programmers utilize this? Multicore systems putting pressure on programmers... Challenges:
★ Dividing activities ★ Balance ★ Data splitting ★ Data dependency ★ Testing and debugging
intel quad core
SLIDE 10 Dividing activities
Finding areas in an application that can be divided into separate, concurrent tasks and thus can run in parallel on individual cores.
Balance
If tasks can be found to run in parallel, programmers also must ensure the tasks to perform equal work of equal value. Using a separate execution core for a task that don’t contribute much value to the overall process may not be worth the cost.
Data splitting
Just as applications are divided into separate tasks, the data accesses and manipulated by the tasks must be divided to run
Data dependency
The data accessed by the tasks must be examined for dependencies between two or more tasks. In instances where
- ne task depends on data from another, programmers must
ensure that the execution of the tasks is synchronized to accommodate the data dependency. We examine such strategies in Chapter 6.
Testing and debugging
When a program is running in parallel on multiple cores, there are many different execution paths. Testing and debugging such concurrent programs is inherently more difficult than testing and debugging single-threaded applications.
4.1.3) Multicore Programming - challenges
SLIDE 11
4.1.3) Multicore Programming - debugging and execution paths
You have a data race in your program! If the threads interleave in this order, thread 2 will withdraw money from the account although there are not enough money in the account at the time of the withdraw.
SLIDE 12
4.1.3) Multicore Programming - debugging and execution paths
You have a data race in your program!
Depending on the interleaving of the threads, the program will work as expected sometimes and not as expected other times.
If the threads interleave in this order, thread 2 will detect that there are not enough money in the account at the time of the withdraw.
SLIDE 13
4.1.2 & 4.1.3) Concurrent Execution of Threads ”Concurrent” execution of threads on a single core CPU Concurrent execution of threads on a dual core CPU
SLIDE 14 User Mode Kernel Mode
mode bit = 1 mode bit = 0
4.3) Thread Libraries
User Threads
Three primary thread libraries:
★ POSIX Pthreads ★ Win32 threads ★ Java threads
Kernel Threads
Examples:
★Windows XP/2000 ★Solaris ★Linux
Library entirely in user space Kernel-level library supported by the OS
★Tru64 UNIX ★Mac OS X
A Thread library provides programmers with an API for creating and managing threads. Two primary ways of implementing a thread library exists: How are user level threads implemented? How does user level threads relate to kernel threads?
SLIDE 15 Many-to-One One-to-One Many-to-Many Two-level-model
Many user-level threads mapped to a single kernel thread. Thread management is done by the thread library in user space. Each user-level thread maps to one kernel thread. Allows many user level threads to be mapped to many kernel threads. Allows the
create a sufficient number of kernel threads. Similar to many-to- many, except that it allows a user thread to be bound to a kernel thread.
4.2) Multithreading Models
SLIDE 16 Many-to-One One-to-One Many-to-Many Two-level-model
Thread management is done by the thread library in user space but entire process will block if a thread makes a blocking system call. Only one thread can access the kernel at a time, hence threads cannot run in parallel
Provides more concurrency than the many-to-one model by allowing another thread to run when a thread makes a blocking system call. Allows for threads to run in parallel on multiprocessors.
!
Multiplexes many user-level threads to a smaller or equal number of kernel threads. A compromise between maný-to-one and one-to-one.
Similar to many-to- many, except that it allows a user thread to be bound to a kernel thread.
4.2) Multithreading Models
This models makes thread creation ”expensive” and most implementations restrict the number of threads supported by the system.
SLIDE 17 Many-to-One One-to-One Many-to-Many Two-level-model
Examples:
★ Solaris Green
Threads
★ GNU Portable
Threads Examples:
★ Windows NT/
XP/2000
★ Linux ★ Solaris 9 and
later Examples:
★ Solaris prior to
version 9
★ Windows NT/
2000 with the ThreadFiber package Examples:
★ IRIX ★ HP-UX ★ Tru64 UNIX ★ Solaris 8 and
earlier
4.2) Multithreading Models
SLIDE 18 4.3.1) Pthreads
A POSIX standard (IEEE 1003.1c) API for thread creation and synchronization. May be provided either as user-level
API specifies behavior of the thread library, implementation is up to development of the library. Common in UNIX operating systems (Solaris, Linux, Mac OS X).
SLIDE 19
4.3.3) Java Threads
Java threads are managed by the JVM. Typically implemented using the threads model provided by underlying OS. Java threads may be created by:
★ Extending Thread class. ★ Implementing the Runnable
interface.
SLIDE 20
4.4) Threading Issues
Semantics of fork() and exec() system calls Thread cancellation of target thread
★ Asynchronous or deferred
Signal handling Thread pools Thread-specific data Scheduler activations
SLIDE 21
4.4.2) Thread Cancellation
Two general approaches: Often, a web page is loaded using several threads - each image is loaded in a separate thread etc. If a user presses the stop button in the browser, how can we cancel all the threads?
★ Asynchronous cancellation terminates the
target thread immediately.
★ Deferred cancellation allows the target thread
to periodically check if it should be cancelled.
SLIDE 22 4.4.2) Thread Cancellation
The difficulty with cancellation occurs in situations where resources have been allocated to a canceled thread or where a thread is canceled while in the midst of updating data it is sharing with other threads.
★ Asynchronous cancellation terminates the target thread
immediately.
Often the OS will reclaim system resources from a canceled thread but will not reclaim all resources. Therefore, canceling a thread a asynchronous may not free a necessary system-wide resource.
★ Deferred cancellation allows the target thread to periodically
check if it should be cancelled.
The thread can perform the check for cancelation at a point at which it can be canceled safely. Pthreads refers to such poitns as cancellation points.
Hmm... Do we need to be careful when cancel threads?
SLIDE 23 4.4.3) Signal Handling
Signals are used in UNIX systems to notify a process that a particular event has
A signal handler is used to process signals
★ Signal is generated by particular event ★ Signal is delivered to a process ★ Signal is handled
Options:
★ Deliver the signal to the thread to which the signal applies ★ Deliver the signal to every thread in the process ★ Deliver the signal to certain threads in the process ★ Assign a specific thread to receive all signals for the process
SLIDE 24 Create a number of threads in a pool where they await work Advantages:
★ Usually slightly faster to service a request with an existing thread than create a new
thread
★ Allows the number of threads in the application(s) to be bound to the size of the pool
4.4.4) Thread Pools
A thread pool is a group of threads initially created that waits for jobs and executes
- them. The idea is to have the
threads always existing, so that we won't have to pay
- verhead time for creating
them every time. They are appropriate when we know there's a stream of jobs to process, even though there could be some time when there are no jobs.
SLIDE 25
4.4.5) Thread Specific Data
Allows each thread to have its own copy of data Useful when you do not have control over the thread creation process (i.e., when using a thread pool) Most thread libraries - including Win32 and Pthreads provides some sort of support for thread-specific data. Java also provides support for thread-specific data.
SLIDE 26
4.4.6) Scheduler Activations
Both M:M and Two-level models require communication to maintain the appropriate number of kernel threads allocated to the application. Scheduler activations provide upcalls - a communication mechanism from the kernel to the thread library. This communication allows an application to maintain the correct number kernel threads.
SLIDE 27
Semantics of fork() when using threads
Does fork() duplicate only the calling thread or all threads?
Let’s write a small program to find out!
SLIDE 28
pthread_create()
SLIDE 29
pthread_exit()
SLIDE 30
Similar to exit() and wait() for processes, pthread_exit() and pthread_wait() can be used for pthreads to return a value and for collecting this return value later.
pthread_join()
SLIDE 31
★ This is the function we will use as the start_routine for our
threads.
★ This function must be declared void* and take a single argument of
type void*.
Semantics of fork() when using threads
SLIDE 32 Semantics of fork() when using threads
Create threads with the worker function as the start routine. Create a new process. We can use pthread_join() to see if fork() duplicates all threads or not.
SLIDE 33
Does fork() duplicate only the calling thread or all threads?
On my OS X system, fork() duplicates only the pthread invoking fork().
Semantics of fork() when using threads
SLIDE 34
4.3.1) Concurrency using Pthreads
Given a string, write a program using Pthreads to concurrently:
★ calculate the length of the string. ★ calculate the number of spaces in the string. ★ change the string to uppercase. ★ change the string to lowercase.
What does it really mean to do all of the above concurrently?
SLIDE 35
4.3.1) Concurrency using Pthreads
SLIDE 36
The implementation details of these functions are not important for the purpose of this exercise. But, note that to for pthreads to be able to use these functions as start routines for the threads they must all be declared void* and take a single argument of type void*.
4.3.1) Concurrency using Pthreads
SLIDE 37
4.3.1) Concurrency using Pthreads
SLIDE 38
4.3.1) Concurrency using Pthreads
We could simply call pthread_create() four times using the four different string functions:
★ length() ★ num_of_spaces() ★ to_upppercase() ★ to_lowercase()
, for example like this.
SLIDE 39 4.3.1) Concurrency using Pthreads
In computer programming, a callback is a reference to executable code, or a piece of executable code, that is passed as an argument to other code. This allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer.
But, it is more practial (and fun) to collect pointers to all the functions in an array.
SLIDE 40
4.3.1) Concurrency using Pthreads
In this example, each thread simply writes their results directly to the shared variables STRING, LENGTH and NUM_OF_SPACES.
SLIDE 41
4.3.1) Concurrency using Pthreads
Because the threads execute and operate on the same data in parallel, the result of to_uppercase() and to_lowercase() will be unpredictable.