Programming with POSIX* Threads - PowerPoint PPT Presentation

1 / 74
About This Presentation
Title:

Programming with POSIX* Threads

Description:

Programming with POSIX* Threads Intel Software College – PowerPoint PPT presentation

Number of Views:96
Avg rating:3.0/5.0
Slides: 75
Provided by: Clay62
Category:

less

Transcript and Presenter's Notes

Title: Programming with POSIX* Threads


1
Programming with POSIX Threads
  • Intel Software College

2
Objectives
  • At the completion of this module you will be able
    to
  • Write code to create and terminate POSIX threads
  • Use Pthreads synchronization objects to
    coordinate thread execution and memory access

3
Agenda
  • Explore POSIX Threading API functions
  • Create and manage threads
  • Synchronization objects
  • Attributes and thread specific data
  • Labs to give hands-on experience

4
Programming with Explicit Threads
  • Identify tasks for threading
  • Identify computational model
  • What work is to be done?
  • What algorithm to use?
  • Identify how data will be accessed
  • What is global? What is local?
  • How is data to be assigned to threads?

5
Coding Considerations
  • Create function to encapsulate computation
  • May be a function that already exists
  • If so, driver function may be needed to
    coordinate multiple threads
  • Pthreads allows single parameter to thread
    function
  • C structure for multiple arguments

6
More Coding Considerations
  • Recast parameter to local variable if needed
  • May be structure of several parameters
  • Add code to determine task of thread
  • May need access to global variable
  • Add code to access data for task
  • Add code to protect global variables
  • Shared data access may need to be restricted
  • Add code to synchronize thread executions

7
Task Allocation Methods
  • Static
  • Initial assignment sets work
  • Computations or data are divided equally
  • based on number of threads and thread ID
  • Dynamic
  • Useful if tasks require unequal or unknown
    execution time
  • Work given to threads as computation proceeds

8
What is Pthreads?
  • POSIX.1c standard
  • C language interface
  • Threads exist within same process
  • All threads are peers
  • No explicit parent-child model
  • Exception main thread holds process information

9
Thread Data Types
  • pthread_t
  • thread handle
  • pthread_attr_t
  • thread attributes
  • detach state
  • stack size
  • stack address
  • specifying NULL gives default attributes

10
Using Pthreads
  • Identify portions of code to thread
  • Encapsulate code into function
  • If code is already a function, a driver function
    may need to be written to coordinate work of
    multiple threads
  • Add pthread_create() call to assign thread(s) to
    execute function

11
pthread_create
  • int pthread_create(tid, attr, function, arg)
  • pthread_t tid
  • handle of created thread
  • const pthread_attr_t attr
  • attributes of thread to be created
  • void (function)(void )
  • function to be mapped to thread
  • void arg
  • single argument to function

12
pthread_create Explained
  • Spawn a thread running the function
  • Thread handle returned via pthread_t structure
  • Specify NULL to use default attributes
  • Single argument sent to function
  • If no arguments to function, specify NULL
  • Check error codes!

EAGAIN - insufficient resources to create
thread EINVAL - invalid attribute
13
Example Thread Creation
  • include ltstdio.hgt
  • include ltpthread.hgt
  • void hello ()
  • printf(Hello Thread\n)
  • main()
  • pthread_t tid
  • pthread_create(tid, NULL, hello, NULL)

What Happens?
14
Example Explained
  • Main thread is process
  • When process goes, all threads go
  • Need some method of waiting for a thread to finish

15
Waiting for POSIX Threads
  • include ltstdio.hgt
  • include ltpthread.hgt
  • int threadDone 0
  • void hello ()
  • printf(Hello Thread\n)
  • threadDone 1
  • main()
  • pthread_t tid
  • pthread_create(tid, NULL, hello, NULL)
  • while (!threadDone)

Not a good idea!
// wasted cycles!
16
Waiting for a Thread
  • int pthread_join(tid, val_ptr)
  • pthread_t tid
  • handle of joinable thread
  • void val_ptr
  • exit value returned by joined thread

17
pthread_join Explained
  • Calling thread waits for thread with handle tid
    to terminate
  • Only one thread can be joined
  • Thread must be joinable
  • Exit value is returned from joined thread
  • Type returned is (void )
  • Use NULL if no return value expected

ESRCH - thread (pthread_t) not found EINVAL -
thread (pthread_t) not joinable
18
Thread States
  • Pthreads threads have two states
  • joinable and detached
  • Threads are joinable by default
  • Resources are kept until pthread_join
  • Can be reset with attributes or API call
  • Detached threads cannot be joined
  • Resources can be reclaimed at termination
  • Cannot reset to be joinable

19
Example Multiple Threads
  • include ltstdio.hgt
  • include ltpthread.hgt
  • define NUM_THREADS 4
  • void hello ()
  • printf(Hello Thread\n)
  • main()
  • pthread_t tidNUM_THREADS
  • for (int i 0 i lt NUM_THREADS i)
  • pthread_create(tidi, NULL, hello, NULL)
  • for (int i 0 i lt NUM_THREADS i)
  • pthread_join(tidi, NULL)

20
LAB 1 HelloThreads
  • Modify the previous example code to print out
  • Appropriate Hello Thread message
  • Unique thread number
  • Use for-loop variable of pthread_create() loop
  • Example output
  • Hello from Thread 0
  • Hello from Thread 1
  • Hello from Thread 2
  • Hello from Thread 3

21
Whats wrong?
  • What is printed for myNum?

void threadFunc(void pArg) int p
(int)pArg int myNum p printf( Thread
number d\n, myNum) . . . // from main() for
(int i 0 i lt numThreads i)
pthread_create(tidi, NULL, threadFunc, i)
22
Hello Threads Timeline
Time main Thread 0 Thread 1
T0 i 0 --- ----
T1 create(i) --- ---
T2 i (i 1) launch ---
T3 create(i) p pArg ---
T4 i (i 2) myNum p myNum 2 launch
T5 wait print(2) p pArg
T6 wait exit myNum p myNum 2
23
Race Conditions
  • Concurrent access of same variable by multiple
    threads
  • Read/Write conflict
  • Write/Write conflict
  • Most common error in concurrent programs
  • May not be apparent at all times

24
How to Avoid Data Races
  • Scope variables to be local to threads
  • Variables declared within threaded functions
  • Allocate on threads stack
  • TLS (Thread Local Storage)
  • Control shared access with critical regions
  • Mutual exclusion and synchronization
  • Lock, semaphore, condition variable, critical
    section, mutex

25
Solution Local Storage
void threadFunc(void pArg) int myNum
((int)pArg) printf( Thread number d\n,
myNum) . . . // from main() for (int i 0
i lt numThreads i) tNumi i
pthread_create(tidi, NULL, threadFunc,
tNumi)
26
Pthreads Mutex
  • Simple, flexible, and efficient
  • Enables correct programming structures for
    avoiding race conditions
  • New types
  • pthread_mutex_t
  • the mutex variable
  • pthread_mutexattr_t
  • mutex attributes
  • Before use, mutex must be initialized

27
pthread_mutex_init
  • int pthread_mutex_init( mutex, attr )
  • pthread_mutex_t mutex
  • mutex to be initialized
  • const pthread_mutexattr_t attr
  • attributes to be given to mutex

ENOMEM - insufficient memory for mutex EAGAIN -
insufficient resources (other than memory) EPERM
- no privilege to perform operation
28
Alternate Initialization
  • Can also use the static initializer
  • PTHREAD_MUTEX_INITIALIZER
  • Uses default attributes
  • Programmer must always pay attention to mutex
    scope
  • Must be visible to threads

pthread_mutex_t mtx1 PTHREAD_MUTEX_INITIALIZER
29
pthread_mutex_lock
  • int pthread_mutex_lock( mutex )
  • pthread_mutex_t mutex
  • mutex to attempt to lock

30
pthread_mutex_lock Explained
  • Attempts to lock mutex
  • If mutex is locked by another thread, calling
    thread is blocked
  • Mutex is held by calling thread until unlocked
  • Mutex lock/unlock must be paired or deadlock
    occurs

EINVAL - mutex is invalid EDEADLK - calling
thread already owns mutex
31
pthread_mutex_unlock
  • int pthread_mutex_unlock( mutex )
  • pthread_mutex_t mutex
  • mutex to be unlocked

EINVAL - mutex is invalid EPERM - calling thread
does not own mutex
32
Example Use of mutex
  • define NUMTHREADS 4
  • pthread_mutex_t gMutex // why does this have to
    be global?
  • int g_sum 0
  • void threadFunc(void arg)
  • int mySum bigComputation()
  • pthread_mutex_lock( gMutex )
  • g_sum mySum // threads access one at a
    time
  • pthread_mutex_unlock( gMutex )
  • main()
  • pthread_t hThreadNUMTHREADS
  • pthread_mutex_init( gMutex, NULL )
  • for (int i 0 i lt NUMTHREADS i)
  • pthread_create(hThreadi,NULL,threadFunc,NULL
    )

33
Numerical Integration Example
4.0
static long num_steps100000 double step,
pi void main() int i double x step
1.0/(double) num_steps for (i0 ilt
num_steps i) x (i0.5)step pi
4.0/(1.0 xx) pi step
printf(Pi f\n,pi)
2.0
1.0
0.0
X
34
Lab 2 Computing Pi
static long num_steps100000 double step,
pi void main() int i double x step
1.0/(double) num_steps for (i0 ilt
num_steps i) x (i0.5)step pi
4.0/(1.0 xx) pi step
printf(Pi f\n,pi)
  • Parallelize the numerical integration code using
    POSIX Threads
  • How can the loop iterations be divided among the
    threads?
  • What variables can be local?
  • What variables need to be visible to all threads?

35
Condition Variables
  • Semaphores are conditional on the semaphore count
  • Condition variable is associated with an
    arbitrary conditional
  • Same operations wait and signal
  • Provides mutual exclusion

36
Condition Variable and Mutex
  • Mutex is associated with condition variable
  • Protects evaluation of the conditional expression
  • Prevents race condition between signaling thread
    and threads waiting on condition variable

37
Lost and Spurious Signals
  • Signal to condition variable is not saved
  • If no thread waiting, signal is lost
  • Thread can be deadlocked waiting for signal that
    will not be sent
  • Condition variable can (rarely) receive spurious
    signals
  • Slowed execution from predictable signals
  • Need to retest conditional expression

38
Condition Variable Algorithm
  • Avoids problems with lost and spurious signals

acquire mutex while (conditional is true)
wait on condition variable perform critical
region computation update conditional signal
sleeping thread(s) release mutex
Mutex is automatically released when thread waits
39
Condition Variables
  • pthread_cond_init, pthread_cond_destroy
  • initialize/destroy condition variable
  • pthread_cond_wait
  • attempt to hold condition variable
  • pthread_cond_signal
  • signal release of condition variable
  • pthread_cond_broadcast
  • broadcast release of condition variable

40
Condition Variable Types
  • Data types used
  • pthread_cond_t
  • the condition variable
  • pthread_condattr_t
  • condition variable attributes
  • Before use, condition variable (and mutex) must
    be initialized

41
pthread_cond_init
  • int pthread_cond_init( cond, attr )
  • pthread_cond_t cond
  • condition variable to be initialized
  • const pthread_condattr_t attr
  • attributes to be given to condition variable

ENOMEM - insufficient memory for mutex EAGAIN -
insufficient resources (other than memory) EBUSY
- condition variable already intialized EINVAL -
attr is invalid
42
Alternate Initialization
  • Can also use the static initializer
  • PTHREAD_COND_INITIALIZER
  • Uses default attributes
  • Programmer must always pay attention to condition
    (and mutex) scope
  • Must be visible to threads

pthread_cond_t cond1 PTHREAD_COND_INITIALIZER
43
pthread_cond_wait
  • int pthread_cond_wait( cond, mutex )
  • pthread_cond_t cond
  • condition variable to wait on
  • pthread_mutex_t mutex
  • mutex to be unlocked

44
pthread_cond_wait Explained
  • Thread put to sleep waiting for signal on cond
  • Mutex is unlocked
  • Allows other threads to acquire lock
  • When signal arrives, mutex will be reacquired
    before pthread_cond_wait returns

EINVAL - cond or mutex is invalid EINVAL -
different mutex for concurrent waits EINVAL -
calling thread does not own mutex
45
pthread_cond_signal
  • int pthread_cond_signal( cond )
  • pthread_cond_t cond
  • condition variable to be signaled

46
pthread_cond_signal Explained
  • Signal condition variable, wake one waiting
    thread
  • If no threads waiting, no action taken
  • Signal is not saved for future threads
  • Signaling thread need not have mutex
  • May be more efficient
  • Problem may occur if thread priorities used

EINVAL - cond is invalid
47
Example Denominator
  • Two threads oversee a global variable
  • Thread 1 calculates the value
  • Thread 2 needs a non-zero value
  • A mutex controls access to the variable
  • Thread 1 signals thread 2 (waiting)

48
Example Denominator
  • include ltpthread.hgt
  • pthread_mutex_t denom_mtx PTHREAD_MUTEX_INITIALI
    ZER
  • pthread_cond_t denom_cond PTHREAD_COND_INITIALIZ
    ER
  • float denominator 0.0 / global /
  • void thread1()
  • pthread_mutex_lock( denom_mtx )
  • denominator f() / calculate
    denominator /
  • pthread_signal( denom_cond ) / signal
    waiting thread /
  • pthread_mutex_unlock( denom_mtx )

49
Example Denominator
  • void thread2()
  • float local_denom
  • pthread_mutex_lock( denom_mtx )
  • / wait for non-zero denominator /
  • while( denominator 0.0 )
  • pthread_cond_wait( denom_cond, denom_mtx
    )
  • local_denom denominator
  • pthread_mutex_unlock( denom_mtx )
  • / Use local copy of denominator for division
    /

50
pthread_cond_broadcast
  • int pthread_cond_broadcast( cond )
  • pthread_cond_t cond
  • condition variable to signal

51
pthread_cond_broadcast Explained
  • Wake all threads waiting on condition variable
  • If no threads waiting, no action taken
  • Broadcast is not saved for future threads
  • Signaling thread need not have mutex

EINVAL - cond is invalid
52
Denominator Many threads
  • Assume multiple threads created on Thread2()
  • What happens if
  • all threads are waiting?
  • no threads are waiting?
  • only some threads are waiting?

void thread1() pthread_mutex_lock(
denom_mtx ) denominator f()
pthread_cond_broadcast( denom_cond ) / wake
all / pthread_mutex_unlock( denom_mtx )
53
Activity 3 Condition variables
  • Replace spin-wait and thread counting variable
    with condition variables to signal thread
    completion of computational piece

54
Semaphores
  • Synchronization object that keeps a count
  • Represent the number of available resources
  • Formalized by Edsgar Dijkstra
  • Two operation on semaphores
  • Wait P(s) Thread waits until s gt 0, then s
    s-1
  • Post V(s) s s 1

55
POSIX Semaphores
  • Not part of the POSIX Threads specification
  • Defined in POSIX.1b
  • Check for system support of semaphores before use
  • Is _POSIX_SEMAPORES defined in ltunistd.hgt?
  • If available, threads within a process can use
    semaphores
  • Use header file ltsemaphore.hgt
  • New type
  • sem_t
  • the semaphore variable

56
sem_init
  • int sem_init( sem, pshared, value )
  • sem_t sem
  • counting semaphore to be initialized
  • int pshared
  • if non-zero, semaphore can be shared across
    processes
  • unsigned int value
  • initial value of semaphore

57
sem_init Explained
  • Initializes the semaphore object
  • If pshared is zero, semaphore can only be used by
    threads within the calling process
  • If non-zero, semaphore can be used between
    processes
  • The value parameter sets the initial semaphore
    count value

EINVAL sem is not valid semaphore EPERM
process lacks approriate privelege ENOSYS
semaphores not supported
58
sem_wait
  • int sem_wait( sem )
  • sem_t sem
  • counting semaphore to decrement or wait

59
sem_wait Explained
  • If semaphore count is greater than zero
  • Decrement count by one (1)
  • Proceed with code following
  • Else, if semaphore count is zero
  • Thread blocks until value is greater than zero

EINVAL sem is not valid semaphore EDEADLK
deadlock condition was detected ENOSYS
semaphores not supported
60
sem_post
  • int sem_post( sem )
  • sem_t sem
  • counting semaphore to be incremented

61
sem_post Explained
  • Post a wakeup to semaphore
  • If one or more threads are waiting, release one
  • Otherwise, increment semaphore count by one (1)

EINVAL sem is not valid semaphore ENOSYS
semaphores not supported
62
Semaphore Uses
  • Control access to limited size data structures
  • Queues, stacks, deques
  • Use count to enumerate available elements
  • Throttle number of active threads within a
    region
  • Binary semaphore 0,1 can act as mutex

63
Semaphore Cautions
  • No ownership of semaphore
  • Any thread can release a semaphore, not just the
    last thread to wait
  • Use good programming practice to avoid
  • No concept of abandoned semaphore
  • If thread terminates before post, semaphore
    increment may be lost
  • Deadlock

64
Example Semaphore as Mutex
  • Main thread opens input file, waits for thread
    termination
  • Threads will
  • Read line from input file
  • Count all five letter words in line

65
Example Main
sem_t hSem1, hSem2 FILE fd int
fiveLetterCount 0
  • main()
  • pthread_t hThreadNUMTHREADS
  • sem_init (hSem1, 0, 1) // Binary semaphore
  • sem_init (hSem2, 0, 1) // Binary semaphore
  • fd fopen(InFile, r) // Open file for
    read
  • for (int i 0 i lt NUMTHREADS i)
  • pthread_create (hThreadi, NULL,
    CountFives, NULL)
  • for (int i 0 i lt NUMTHREADS i)
  • pthread_join (hThreadi, NULL)
  • fclose(fd)
  • printf(Number of five letter words is d\n,
    fiveLetterCount)

66
Example Semaphores
  • void CountFives(void arg)
  • int bDone 0
  • char inLine132 int lCount 0
  • while (!bDone)
  • sem_wait(hSem1) // access to input
  • bDone (GetNextLine(fd, inLine) EOF)
  • sem_post(hSem1)
  • if (!bDone)
  • if (lCount GetFiveLetterWordCount(inLin
    e))
  • sem_wait(hSem2) // update global
  • fiveLetterCount lCount
  • sem_post(hsem2)

67
Activity 4 Using Semaphores
  • Use binary semaphores to control access to shared
    variables

68
Some Advanced Functions
  • Thread-specific Data
  • Thread Attributes
  • Mutex Attributes
  • Condition Variable Attributes
  • Just a quick overview of functions
  • Not too many details

69
Thread-specific Data
  • Another means for local storage
  • pthread_key_create
  • Create thread-specific key for all threads
  • pthread_setspecific
  • Associate thread-specific value with given key
  • pthread_getspecific
  • Return current data value associated with key
  • pthread_key_delete
  • Delete a data key

70
Thread Attribute Functions
  • pthread_attr_init
  • Initialize attribute object to default settings
  • pthread_attr_destroy
  • Delete attribute object
  • pthread_getsetdetachstate
  • Return or set threads detach state
  • pthread_getsetstackaddr
  • Return or set the stack address of thread
  • pthread_getsetstacksize
  • Return or set the stack size of thread

71
Mutex Attribute Functions
  • pthread_mutexattr_init
  • Intialize mutex attribute object to defaults
  • pthread_mutexattr_destroy
  • Delete mutex attribute object
  • pthread_mutexattr_getsetpshared
  • Return or set whether mutex is shared between
    processes

72
Condition Attribute Functions
  • pthread_condattr_init
  • Initialize condition variable attribute object
  • pthread_condattr_destroy
  • Destroy condition variable attribute object
  • pthread_condattr_getsetpshared
  • Return or set whether condition variable is
    shared between processes

73
Summary
  • Create threads to execute work encapsulated
    within functions
  • Coordinate shared access between threads to avoid
    race conditions
  • Local storage to avoid conflicts
  • Synchronization objects to organize use

74
(No Transcript)
Write a Comment
User Comments (0)
About PowerShow.com