Operating Operating Systems I (1D (1DT044) Threads (Chapter 4) - - PowerPoint PPT Presentation

operating operating systems i 1d 1dt044
SMART_READER_LITE
LIVE PREVIEW

Operating Operating Systems I (1D (1DT044) Threads (Chapter 4) - - PowerPoint PPT Presentation

Operating Operating Systems I (1D (1DT044) Threads (Chapter 4) Tuesday february 1 Uppsala University 2011 karl.marklund@it.uu.se PCB state In brief, the PCB serves as the repository for any process id/number information that may vary


slide-1
SLIDE 1

Operating Operating Systems I (1D

Threads (Chapter 4)

(1DT044)

Tuesday february 1 Uppsala University 2011 karl.marklund@it.uu.se

slide-2
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
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
SLIDE 4

4.1) Single and Multithreaded Processes

slide-5
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
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
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
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
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
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

  • n separate cores.

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
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
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
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
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
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

  • perating system to

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
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

  • n multiprocessors.

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
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
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

  • r kernel-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
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
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
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
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
SLIDE 23

4.4.3) Signal Handling

Signals are used in UNIX systems to notify a process that a particular event has

  • ccurred

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
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
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
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
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
SLIDE 28

pthread_create()

slide-29
SLIDE 29

pthread_exit()

slide-30
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
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
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
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
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
SLIDE 35

4.3.1) Concurrency using Pthreads

slide-36
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
SLIDE 37

4.3.1) Concurrency using Pthreads

slide-38
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
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
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
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.