PThread

buninnateΛογισμικό & κατασκευή λογ/κού

18 Νοε 2013 (πριν από 4 χρόνια και 1 μήνα)

95 εμφανίσεις

1

Threads

2

Processes versus Threads

3

Why Threads?

Processes do not share resources very well

Why?

Process context switching cost is very high

Why?



Thread
: a light
-
weighted process

A sequence of execution

4

Threads: Lightweight Processes

Environment (resource)

execution

5

Real Life Example?


Process


“system programming” course


Different from
“internet engineering”


Thread


homework, Reading, Self
-
assessment quiz


Each is a different “execution”


But all share


Content


Textbook


Personnel (TAs, instructors)


Affect each other


6

Review: threads vs. processes (created with fork)


Property

Processes created with
fork

Threads of a process

Ordinary function calls

variables

get copies of all variables

share global variables

share global variables

IDs

get new process IDs

share the same process ID but have
unique thread ID

share the same process ID
(and thread ID)

Communication

Must explicitly
communicate, e.g.pipes

or use small integer
return value

May communicate with return
value

or shared variables

if done carefully

May communicate with
return value

or shared variables

(don't have to be careful)

Parallelism (one
CPU)

Concurrent

Concurrent

Sequential

Parallelism
(multiple CPUs)

May be executed
simultaneously

Kernel threads may be executed
simultaneously

Sequential

7

Thread components


A thread has its own program counter and stack, but
shares a number of resources with its process and
other threads of the process:


address space: code and global variables


open files


semaphores


signals


timers


process ID


Thread specific resource:


Thread ID


Program counter


Register set


Stack space


Signal mask (later…)

8

Thread vs. Process

Each thread execute separately

Threads in the same process share resources

No protection among threads!!


9

Storage for Threads

10

Thread Model : Context Switch


Extensive sharing makes CPU switching
among peer threads and creation of threads
inexpensive compared to processes


Thread context switch still requires


Register set switch


But no memory management related

work!!!



Why need to switch from one thread (process)
to another?


Some thread (process) may block for I/O


Many threads (processes) share limited #CPUs

11

Thread State


Threads states are


Ready


Blocked


Running


Terminated


Why these states?


Threads share CPU


On single processor machine only one thread can run at a time


Threads can block waiting for a system call to be completed


12

Creating a Thread


When a new thread is created it runs
concurrently with the creating process.



When creating a thread you indicate which
function the thread should execute.

13

Normal function call

14

Threaded function call

15

Benefits of Threads


Responsiveness


Multi
-
threading allows applications to run even if
part of it is blocked


Resource sharing


Sharing of memory, files and other resources of
the process to which the threads belong


Economy


Much more costly and time consuming to create
and manage processes than threads


Utilization of multiprocessor architectures


Each thread can run in parallel on a different
processor

16

Thread Creation vs. Process Creation

Time in seconds for 50000 fork or
thread creations

17

Threaded Function Call Detail


A function that is used as a thread must have
a special format.



It takes a single parameter and returns a
single parameter.



Can point to a structure, so in effect, the
function can use any number of parameters.


http://www.llnl.gov/computing/tutorials/pthreads/


18

An Example

The thread function casts and unpacks the first argument:


void * myWorkerFunction(void *arg) {





int fd1 = ((int *)arg) [0];


int fd2 = ((int *)arg) [1];


}





19

Pthread Operations

POSIX function

description

pthread_create

create a thread

pthread_detach

set thread to release resources

pthread_equal

test two thread IDs for equality

pthread_exit

exit a thread without exiting process

pthread_kill

send a signal to a thread

pthread_join

wait for a thread

pthread_self

find out own thread ID



20

pthread_* return values

Unlike most POSIX functions, they do not set
errno but the value returned when an error
occurs has the value that errno would have.


None of the POSIX thread functions ever return
the error EINTR.

21

Example program

#include <phtread.h>

#include <thread.h>

#include <stdio.h>

void *threadex(void *);


int main() {



pthread_t tid; /* stores the new thread ID */




pthread_create
(&tid, NULL, threadex, NULL); /*create a new thread*/


pthread_join
(tid, NULL); /*main thread waits for other thread to terminate */


return 0; /* main thread exits */


}

void *threadex(void *arg) /*thread routine*/ {


int i;


for (i=0; i<5; i++)


fprintf(stderr, `Hello, world!
\
n'');

return NULL; }

22

Thread Usage: word processor

What if it is single
-
threaded?

23

Thread Usage: Web Server

24

Web Server

Rough outline of code for previous slide

(a) Dispatcher thread

(b) Worker thread

25

Designing Threaded Programs

Thread candidates?

Discrete, independent tasks which can execute concurrently

E.g. if routine1 and routine2 can be interchanged, interleaved
and/or overlapped in real time, they are candidates for threading


26

Tasks Suitable for threading


Block for potentially long waits


Use many CPU cycles


Must respond to asynchronous events


Are of lesser or greater importance than other
tasks


Are able to be performed in parallel with other
tasks


27

Common Multi
-
thread Software Architectures


Manager/worker


a single thread, the
manager

assigns work to other threads,
the
workers
.


Typically, the manager handles all input and parcels out work
to the other tasks


Pipeline:


a task is broken into a series of suboperations, each of which
is handled in series, but concurrently, by a different thread.


An automobile assembly line best describes this model


Peer


similar to the manager/worker model, but after the main
thread creates other threads, it participates in the work

28

A Challenge: Making Single
-
Threaded Code Multithreaded

Conflicts between threads over the use of a global variable

29

A solution: Private Global Variables

30

Thread Packages


Kernel thread packages


Implemented and supported at kernel level


User
-
level thread packages


Implemented at user level

31

User
-
level Thread

32

User Level Threads


User
-
level threads without direct O/S support


Threads are invisible to the kernel


Simpler kernel implementation


Can only use one processor at a time


Implementation dependent


Some threads can block other threads


(or)
Requires a special library of system calls to
prevent blocking

33

User
-
level Threads


Advantages


Fast Context Switching:


User level threads are implemented using
user level thread
libraries
, hence no call to OS and no interrupts to kernel


One key difference with processes:


when a thread is finished running for the moment, it can call
thread_yield.



This instruction


(a) saves the thread information in the thread table itself, and


(b) calls the thread scheduler to pick another thread to run.


The procedure that saves the local thread state and the
scheduler are
local procedures
, hence no trap to kernel, no
context switch, no memory switch, and this makes the
thread
scheduling very fast
.


Customized Scheduling

34

Kernel
-
level Threads


Kernel can schedule threads in addition to
processes.


Multiple threads of a process can run
simultaneously on multiple CPUs.


Synchronization more efficient than for
processes (but less than for user
-
level
threads).


Kernel
-
level threads can make blocking I/O
calls without blocking other threads of same
process

35

Kernel
-
Level Thread

36

Trade
-
offs (review)?


Kernel thread packages


Each thread can make blocking I/O calls


Can run concurrently on multiple processors


Threads in User
-
level


Fast context switch


Customized scheduling


37

Implementing Threads in User Space (old Linux)

A user
-
level threads package

38

Hybrid Implementations (Solaris)


Multiplexing user
-
level threads onto kernel
-

level threads

39

What’s POSIX Got To Do With It?


Each OS had it’s own thread library and style


That made writing multithreaded programs difficult
because:


you had to learn a new API with each new OS


you had to
modify your code

with each port to a
new OS


POSIX (IEEE 1003.1c
-
1995) provided a standard
known as Pthreads


Unix International (UI) threads (Solaris threads) are
available on Solaris (which also supports POSIX
threads)

40

Pthreads
---

POSIX Threads


It is a standard API


Supported by most vendors


General concepts applicable to other
thread APIs (java threads, NT threads,etc).


Low level functions


41

Creating a thread

with pthread


A thread is created with


int pthread_create( pthread_t *restrict thread,


const pthread_attr_t *restrict attr,


void *(*start_routine)(void *),


void *restrict arg);



The creating process (or thread) must provide a location
for storage of the thread id.


The third parameter is just the name of the function for
the thread to run.


The last parameter is a pointer to the arguments.

42

Restrict Keyword


One of the new features in the recently approved C
standard C99


This qualifier can be applied to a data pointer to
indicate that


During the scope of that pointer declaration, all data
accessed through
it will be accessed only through that
pointer but not through any other pointer.


It enables the compiler to perform certain optimizations
based on the premise that a given object cannot be changed
through another pointer


http://www.cellperformance.com/mike_acton/2006/05/demystifyin
g_the_restrict_keyw.html

43

The Thread ID

pthread_t pthread_self(void)



Each thread has an id of type pthread_t.


On most systems this is just an integer (like a
process ID)


But it does not have to be


A thread can get its ID with pthread_self


Compare two threads


int pthread_equal(thread_t t1, pthread_t t2)

44

Exiting and Cancellation


Question:


If a thread calls exit(), what about other threads in
the same process?


A process can terminate when:


it calls exit directly


one of its threads calls exit


it returns from main()


it receives a termination signal


In any of these cases, all threads of the
process terminate.


45

Exiting


When a thread is done, it can return from its first
function (the one used by pthread_create) or it
can call pthread_exit


void pthread_exit(void *value_ptr);


46

Cancel that thread!


One thread can request that another exit
with pthread_cancel


int pthread_cancel(pthread_t thread);



The pthread_cancel returns after making
the request.


A successful return does not mean that
the target thread has terminated or even
that it eventually will terminate as a
result of the request

47

Thread Attributes


Create an attribute object (initialize it with
default properties)


Modify the properties of the attribute object


Create a thread using the attribute object


The object can be changed or reused without
affecting the thread


The attribute object affects the thread only at
the time of thread creation


48

Attribute Initialization and Deletion

Initialize or destroy an attribute with:



int pthread_attr_destroy(pthread_attr_t *attr);

int pthread_attr_init(pthread_attr_t *attr);

49

Example: Create a detached thread

int e, fd;

pthread_attr_t tattr;

pthread_t tid;


if(e =
pthread_attr_init
(&tattr))


fprintf(stderr, "Failed to create attribute object: %s
\
n", strerror(e));


else if(e =
pthread_attr_setdetachstate
(&tattr,


PTHREAD_CREATE_DETACHED))


fprintf(stderr, "Failed to set attribute state to detached: %s
\
n", strerror(e));


else if(e =
pthread_create
(&tid, &tattr, data, &fd))


fprintf(stderr, "Failed to create thread: %s
\
n", strerror(e));

50

The thread stack

You can set a location and size for the thread stack.




int pthread_attr_setstack( pthread_attr_t *attr,





void *stackaddr,


size_t stacksize )


(there’s a getstack function too)


Some systems allow you to set a guard for the stack so that an
overflow into the guard area can generate a SIGSEGV signal.


int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,


size_t *restrict guardsize);

int pthread_attr_setguardsize(pthread_attr_t *attr,


size_t guardsize);

51

Settable properties of thread attributes

property

function

attribute objects

pthread_attr_destroy

pthread_attr_init

detach state

pthread_attr_getdetachstate

pthread_attr_setdetachstate

stack

pthread_attr_getguardsize

pthread_attr_setguardsize

pthread_attr_getstack

pthread_attr_setstack

scheduling

pthread_attr_getinheritsched

pthread_attr_setinheritsched

pthread_attr_getschedparam

pthread_attr_setschedparam

pthread_attr_getschedpolicy

pthread_attr_setschedpolicy

pthread_attr_getscope

pthread_attr_setscope

52

Thread Detach & Join


Call
pthread_join
() or
pthread_detach
() for
every thread that is created joinable


so that the system can reclaim all resources
associated with the thread


Failure to join or to detach threads

memory
and other resource leaks until the process
ends

53

Detaching a Thread

int pthread_detach(pthread_t threadid);


Indicate that system resources for the specified thread
should be reclaimed when the thread ends


If the thread is already ended, resources are reclaimed
immediately


This routine does not cause the thread to end


Threads are detached


after a pthread_detach() call


after a pthread_join() call


if a thread terminates and the
PTHREAD_CREATE_DETACHED attribute was set on
creation

54

How to make a thread detached

void *processfd(void *arg);


int error;

int fd

pthread_t tid;


if (error = pthread_create(&tid, NULL, processfd, &fd)) {


fprintf(stderr, "Failed to create thread: %s
\
n", strerror(error));

}

else if (error = pthread_detach(tid)){


fprintf(stderr, "Failed to detach thread: %s
\
n", strerror(error));

}

55

How a thread can detach itself

void *runnger(void *arg) {





if (!pthread_detach( pthread_self()) )


return NULL;





}

56

“Wating” on a Thread: pthread_join()

int pthread_join(pthread_t thread,
void** retval);


pthread_join() is a
blocking call

on
non
-
detached
threads


It indicates that the caller wishes to
block until the thread being joined
exits


You cannot join on a detached thread,
only non
-
detached threads

57

Pthread_join

int error;

int *exitcodep;

pthread_t tid;


if (error = pthread_join(tid, &exitcodep)){


fprintf(stderr, "Failed to join thread: %s
\
n", strerror(error));

}

else {


fprintf(stderr, "The exit code was %d
\
n", *exitcodep);

}

58

Thread scheduling

int pthread_attr_getscope(const pthread_attr_t *restrict attr,


int *restrict contentionscope);

int pthread_attr_setscope(pthread_attr_t *attr, int
contentionscope);



The contentionscope can be:


PTHREAD_SCOPE_PROCESS


PTHREAD_SCOPE_SYSTEM.


The scope determines whether the thread competes
with other threads of the process or with other
processes in the system.

59

Create a thread that contends with other
processes

pthread_attr_init(&tattr))


pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM))


thread_create(&tid, &tattr, myfunction, &myptr))