200 likes | 303 Views
Windows Application Development. Chapter 10 - Supplement Introduction to Pthreads for Application Portability. OBJECTIVES. Upon completion of this chapter, you will be able to: Describe the Pthreads API Compare Windows and Pthreads Use the open source Pthreads library
E N D
Windows Application Development Chapter 10 - Supplement Introduction to Pthreads for Application Portability
OBJECTIVES • Upon completion of this chapter, you will be able to: • Describe the Pthreads API • Compare Windows and Pthreads • Use the open source Pthreads library • Build portable threaded applications • Understand threading outside the Windows context
1. Pthreads Overview • POSIX Pthreads features supported by: • An industry standard • Similar to Windows, with differences (Ex: Events) • Nearly every UNIX distribution – HP UX, Solaris, AIX, … • Linux • OpenVMS • Others • PLUS, an open source Windows distribution • Cautiously recommended – Trust but verify http://sources.redhat.com/pthreads-win32/ pthread.h pthreadVSE.lib pthreadVSE.dll
2. Thread Management and Creation • A parent thread creates a child thread using: int pthread_create (pthread_t *thread, const pthread_attr_t *attr void *(*start) (void *), void *arg); • Thread creation notes: • pthread_attr_t is NULL (for our purposes) • Use other values only when explicitly required • Parent and child concepts are for convenience only • Operating system does not maintain any such relationship • The main() program initial thread is special • Behaves differently from other threads
Thread Startup • The child thread is created in the ready state • It can run immediately • Thread startup notes: • Parent and child threads can run in any order • Child thread might complete before (or after) any other • Complete all initialization before calling pthread_create() • Each child thread should have its own data structure • For parameters • For working storage • The parent thread initializes the structure and passes its address in arg
Thread Running and Blocking • The operating system scheduler runs a thread according to thread priorities and scheduling policies • A thread can run at any time • A thread may run until one of the following: • The thread times out and the operating system preempts it • The thread blocks due to a page fault • The thread terminates or is terminated • The thread yields the processor and moves to the ready state int sched_yield (void); • The thread blocks by calling a blocking function int pthread_join (pthread_t thread, void **value_ptr);
Thread Termination • The normal way for a thread to terminate is to return from its start function or to call int pthread_exit (void *value_ptr); • The return value is the thread’s exit code • Exit code can be accessed by pthread_join() • Resources created by a thread must be explicitly released
3. Mutexes • A mutex, of object type pthread_mutex_t, can be initialized by assignment or a function call pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int pthread_mutex_init (pthread_mutex_t *mutex, pthread_mutexattr_t *attr); int pthread_mutex_destroy (pthread_mutex_t *mutex);
Mutex Management Notes • pthread_mutex_t • Do not copy a variable of type pthread_mutex_t • If declared outside the main function, it should have either externor static storage class • Each mutex must be initialized before it is used • Static initialization with PTHREAD_MUTEX_INITIALIZER • Dynamic initialization with pthread_mutex_init() • When no longer required, destroy it to free kernel and user resources
Locking and Unlocking a Mutex • A thread can lock or own a mutex • A thread attempts to gain ownership with a try call int pthread_mutex_trylock ( pthread_mutex_t *mutex); • Returns with 0 if successful • Returns with EBUSY if the mutex is owned by another thread • A thread waits to gain ownership with lock call int pthread_mutex_lock (pthread_mutex_t *mutex); • Blocking call; will only return with mutex ownership • Returns with EINVAL if the parameter is not valid • Unlock a mutex int pthread_mutex_unlock ( pthread_mutex_t *mutex);
Locking and Unlocking Notes • There is no timeout associated with pthread_mutex_lock() • If a thread terminates before it unlocks a mutex, the mutex remains locked • A mutex can have the recursive attribute • If pthread_mutex_trylock() fails, do not access the protected resources and do not unlock the mutex • Do not let a thread unlock a mutex it does not own • Exactly one blocked thread will be given mutex ownership • You cannot predict which one
4. Condition Variables • A condition variable is used to signal that some event or state change has occurred • A mutex protects the whole state data structure • Multiple condition variables related to one mutex • Condition variables represent distinct states • New data available in a buffer • Buffer empty, buffer full, etc. • Signaled to awaken just one thread • Broadcast to awaken all waiting threads • Combines: Signal, wait, wait sequence of the CVM
Condition Variable Management pthread_cond_t cond = PTHREAD_COND_INITIALIZER; int pthread_cond_init ( pthread_cond_t *cond, pthread_condattr_t *condattr); int pthread_cond_destroy ( pthread_cond_t *cond);
Waiting on a Condition Variable • Wait with either a blocking wait or a wait with a timeout • Both must specify a mutex • The calling thread must own the mutex before waiting on the condition variable int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *expiration); Returns ETIMEOUT if the timeout period expires
Condition Variable Waiting Notes • A thread “waits” on a condition variable • All threads waiting on a condition variable at any one time must specify the same mutex • Distinct predicates should have distinct condition variables • Associate the condition variable with a state predicate • The mutex should be the one that protects the state variables that determine the predicate • Two distinct predicates • Invariant predicate • Condition variable predicate (implies invariant) • Condition variables are for signaling, not mutual exclusion
Condition Variable Signal and Broadcast • Wake up a single waiting thread with int pthread_cond_signal ( pthread_cond_t *cond); • Cannot directly control which of several threads will awaken • Wake up all threads with int pthread_cond_broadcast ( pthread_cond_t *cond); • All waiting threads wake up and immediately block on the mutex • Only one thread, at most, gains mutex ownership immediately
CV Waiting and Signaling Threads Thread A Thread B Running Ready Lock (&state.guard) change state variables ivp( ) is true Running Wait (&state.cond, &state.guard) Thread A does notown state.guard Lock (&state.guard) change state variables Waiting on cond cvp( ) is true Blocked on guard Signal (&state.cond) Unlock (&state.guard) Ready Preempt Run Running Ready Thread A owns state.guard Unlock (&state.guard) ivp(): invariant predicate cvp(): condition variable predicate
Safe Condition Variable Usage • Test your predicate immediately before and immediately after the condition variable wait call • A simple while() loop achieves these tests • Develop two thread-safe functions: cvp() implies ivp() • They check the CV predicate and invariant predicate • They check relationships in the state variable structure • Must be called with the appropriate mutex locked • No need for a function for simple predicates
Safe Condition Variable Usage • typedef struct _state_t { • pthread_mutex_t guard; • pthread_cond_t cond; • . . . other condition variables • struct state_var_t state_var; • } state_t state = • { PTHREAD_MUTEX_INTIALIZER, PTHREAD_COND_INITIALIZER }; • . . . • pthread_mutex_lock (&state.guard); • /* Change the variables in the state structure */ • . . . state.state_var.xyz = . . . ; • /* We know that ivp(&state) holds, wait for cvp(&state) */ • /* Do not wait if cvp() already is true, avoid lost wakeup */ • while (!cvp(&state)) • pthread_cond_wait (&state.cond, &state.guard); • . . . • pthread_mutex_unlock (&state.guard);
5. Lab Exercise 10-pthreads • Modify eventPC.c (Session 2) to use Pthreads • eventPCPT.c is a solution