posix® threads (pthreads)faculty.washington.edu/jstraub/isilon/isilon1/unit 9.pdf · posix®...

39
Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof, Addison Wesley, 1997

Upload: others

Post on 25-Aug-2020

87 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Posix® Threads (Pthreads)Reference:

Programming with POSIX® Threads by David R. Butenhof, Addison Wesley, 1997

Page 2: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Threads: Introductionmain:

startThread( funk1 )startThread( funk1 )startThread( funk2 )waitexit

main

funk1 funk1 funk2

exit

exit exit

wait

exit

Page 3: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Threads: Advantages

• Intuitive Modeling• True parallelization Wait for 

connection

Server

Launch thread

Client processing...

. . .

Client processing...

. . .

Clientprocessing...

. . .

Client 1

Client 2

Client 3

Page 4: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Threads: SynchronizationRace conditions:

1. Object not ready for processing

4. Wait for signal

Object to 

process

Processing Thread

2. Place object

3. Signal object ready for processing

Assembly Thread

Page 5: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Threads: SynchronizationDeadlocks:

1. Seize object A3. Seize object B

. . .Release object ARelease object B

Thread 1

2. Seize object B4. Seize object A

. . .Release object BRelease object A

Thread 2

Page 6: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Threads: Reentrancy

Thread 1process( “/etc/data/results.txt” )

process( param )1.     token = strtok( param )6.     while ( token != NULL )7.          . . .8.          token = strtok( NULL )

Thread 2process( “/tmp/data.txt” )

process( param )2.     token = strtok( param )3.     while ( token != NULL )4.          . . .5.          token = strtok( NULL )

Page 7: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_createtypedef void *START_PROC_t( void * );typedef START_PROC_t *START_PROC_p_t;int pthread_create(

pthread_t *thread,const pthread_attr_t *attr, START_PROC_p_t start_proc,void *arg

);

threadpointer to thread ID storage

attrpointer to thread attributes object; may be NULL

threadpointer to work function

argargument to pass to work function

returns:0 for success, non‐0 for error

Page 8: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_create Examplestatic START_PROC_t funk1;int main( int argc, char **argv ){

pthread_t tid1;int arg1 = 1;status = pthread_create( &tid1, NULL, funk1, &arg1 );if ( status != 0 )

. . .return 0;

}

Page 9: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_joinint pthread_join(pthread_t thread, void **retval);

Waits for a thread to terminate; returns immediately if thread has already terminated.

threadID  of thread to join

retvalpointer to storage for joined thread’s return value; may be NULL

returns:0 for success, non‐0 for error

Page 10: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_join, Exampleint main( int argc, char **argv ){

pthread_t tid1;int arg1 = 1;status = pthread_create( &tid1, NULL, funk1, &arg1 );if ( status != 0 )

. . .status = pthread_join( tid1, NULL );if ( status != 0 )

. . .return 0;

}

Page 11: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_cancelint pthread_cancel(pthread_t thread);

Gracefully terminates a thread.

thread

The thread to terminate.Returns:

0 if successful, non‐zero otherwise.

Page 12: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_cancel, Exampleint main( int argc, char **argv ){

pthread_t tid1;int arg1 = 1;status = pthread_create( &tid1, NULL, funk1, &arg1 );if ( status != 0 )

. . .sleep( 60 );status = pthread_cancel( tid1 );if ( status != 0 )

. . .return 0;

}

Page 13: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

pth_util.h/************** BEGIN SPECIAL CONDITION: STATUS ********************* To use any of the following macros you must first define variable* 'int status.' This is less than ideal, but we'll go with it for* now.*/

#define PTH_CREATE( p1, p2, p3, p4 ) \((status = pthread_create( (p1), (p2), (p3), (p4) )) == 0 ? (void)0 : \PTH_err( status, "pthread_create", __FILE__, __LINE__ ) \

)

#define PTH_CANCEL( p1 ) \((status = pthread_cancel( (p1) )) == 0 ? (void)0 : \PTH_err( status, "pthread_cancel", __FILE__, __LINE__ ) \

). . .

/************** END SPECIAL CONDITION: STATUS ********************/

Page 14: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

pth_util.cvoid PTH_err( int status, const char *msg, const char *file, int line ){

const char *status_str = strerror( status );fprintf( stderr,

"Error %d (%s); %s in %s at line %d\n",status,status_str,msg,file,line

);abort();

}

Page 15: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Exercise1. From the class website download pth_utils.h, pth_utils.c and 

thread_exercise1.c.2. Complete the code in thread_exercise1.c. This will create three threads 

that separately add the numbers between 1 and 1,000,000; 1,000,0001 and 2,000,000; and 2,000,001 and 3,000,000,000 then combine the results.

3. Add PTH_EXIT (which invokes pthread_exit) to pth_utils.h.

Page 16: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Threads: MutexesA mutex is an object that is used for thread synchronization.

Thread 1process( “/etc/data/results.txt” )

process( param )1.     sieze mutex_a3.     token = strtok( param )4.     while ( token != NULL )5.          . . .6.          token = strtok( NULL )7.     release mutex_a

Thread 2process( “/tmp/data.txt” )

process( param )2 .    sieze mutex_a (wait)8.     token = strtok( param )9.     while ( token != NULL )10.      . . .11.      token = strtok( NULL )12.   release mutex_a

mutex_a

Page 17: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_mutex_initint pthread_mutex_init(

pthread_mutex_t *mutex,const pthread_mutexattr_t *attr

);mutex

Pointer to storage for a mutex identifier.attr

Pointer to a mutex attributes object; may be NULL.

returns:0 if successful, non‐zero otherwise

Page 18: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: PTHREAD_MUTEX_INITIALIZERThis macro may be used to initialize static mutexes:

static pthread_mutex_t mutex_ =PTHREAD_MUTEX_INITIALIZER;

No error checking is performed.

Page 19: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_mutex_destroyint pthread_mutex_destroy( pthread_mutex_t *mutex );

mutex

Pointer to storage for a mutex identifier.

returns:0 if successful, non‐zero otherwise

• Do not try to destroy an uninitialized mutex.• Do not try to destroy a locked mutex.• Once a mutex has been destroyed it may be reinitialized.

Page 20: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Mutex Locking/Unlockingint pthread_mutex_lock( pthread_mutex_t *mutex );

Sieze a mutex; if the mutex is already locked wait until it is unlocked.

int pthread_mutex_trylock( pthread_mutex_t *mutex );

Sieze a mutex; if the mutex is already locked return immediately with a status of EBUSY.

int pthread_mutex_unlock( pthread_mutex_t *mutex );

Release a mutex; do not try to release an unlocked mutex.

Return:0 if success, non‐zero otherwise.

Page 21: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_mutexattr_tint pthread_mutexattr_init(pthread_mutexattr_t *attr);

Initialize a Pthread mutex attrbutes object.

int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

Destroy a Pthread mutex attrbutes object.

intpthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);

Set the type of a Pthread mutex object.

attr

Pointer to Pthread mutex attributes object storage.type

Type of a Pthread mutex object.

Page 22: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Mutex TypePTHREAD_MUTEX_NORMAL

Recursive acquistion of a mutex will result in a deadlock. Attempting to unlock a mutex owned by another thread will result in undefined behavior.

PTHREAD_MUTEX_ERRORCHECK

Attempted recursive acquistion of a mutex will return a status of EDEADLK. Attempting to unlock a mutex owned by another thread will return a status of EPERM.

PTHREAD_MUTEX_RECURSIVE

Recursive acquistion of a mutex is allowed. Attempting to unlock a mutex owned by another thread will return a status of EPERM.

PTHREAD_MUTEX_DEFAULT

Recursive acquistion of a mutex will result in undefined behavior. Attempting to unlock a mutex owned by another thread will result in undefined behavior.

This functionality may not be available on all systems; check your documentation.

Page 23: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Mutex Type, Examplestatic void init_mutex( void ){

pthread_mutexattr_t attrs;int status;

status = pthread_mutexattr_init( &attrs );if ( status != 0 )

err( status, "pthread_mutexattr_init" );status = pthread_mutexattr_settype( &attrs, PTHREAD_MUTEX_ERRORCHECK );if ( status != 0 )

err( status, "pthread_mutexattr_settype" );status = pthread_mutex_init( &mutex_var_, &attrs );if ( status != 0 )

err( status, "pthread_mutex_init" );status = pthread_mutexattr_destroy( &attrs );if ( status != 0 )

err( status, "pthread_mutexattr_destroy" );}

Page 24: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Mutex Type, Example (cont’d)static void cleanup( void ){

int status = pthread_mutex_destroy( &mutex_var_ );if ( status != 0 )

err( status, "pthread_mutex_destroy" );}

Page 25: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Exercise1. Write and test the function int get_random_int( int min, int max ). 

This function uses the function rand() (declared in stdlib.h) to generate and return a random integer between min and max, inclusive. The algorithm for doing this is given by:

– rand() % (max – min + 1) + min

2. Write a program, mutex_exercise, with a counter and two threads:– One thread increments the counter up to a maximum value of 5, reports the counter 

value (via printf()) and sleeps for a random number of seconds no less than 2 and no more than 5.

– The other thread decrements the counter to a minimum value of 0, reports the counter value and sleeps for a random number of seconds no less than 1 and no more than 4.

– Use a mutex to ensure that the two threads do not try to adjust the counter or report its value at the same time.

Page 26: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Threads: Sometimes a Mutex is Not Enough

1. Seize mutex2. Object not ready for processing3. Release mutex8. Wait for signal

Object to 

process

Processing Thread

4. Seize mutex5. Place object6. Signal object ready for processing7. Release mutex

Assembly Threadmutex_a

Page 27: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Condition VariablesCondition variables allow you to release a mutex and initiate a wait as an atomic process.

1. Seize mutex2. Object not ready for processing3. Wait on condition via mutex

Object to 

process

Processing Thread

4. Seize mutex5. Place object6. Signal object ready for processing7. Release mutex

Assembly Threadmutex_a

cond_a

Page 28: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_cond_initint pthread_mutex_init(

pthread_cond_t *cond,const pthread_condattr_t *attr

);cond

Pointer to storage for a condition variable identifier.attr

Pointer to a condition variable attributes object; may be NULL.

returns:0 if successful, non‐zero otherwise

Page 29: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: PTHREAD_COND_INITIALIZERThis macro may be used to initialize static condition variables:

static pthread_cond_t cond_ =PTHREAD_COND_INITIALIZER;

No error checking is performed.

Page 30: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_cond_destroyint pthread_cond_destroy( pthread_cond_t *cond );

cond

Pointer to storage for a condition variable identifier.

Returns:0 if successful, non‐zero otherwise

• Do not try to destroy an uninitialized condition variable.

• Do not try to destroy a blocking condition variable.• Once a condition variable has been destroyed it may be reinitialized.

Page 31: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Using Condition Variablesint pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

Release mutex, block on cond.int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

Release mutex, block on cond for at most abstime.int pthread_cond_signal(pthread_cond_t *cond);

Unblock at least one thread waiting on cond.int pthread_cond_broadcast(pthread_cond_t *cond);

Unblock all threads waiting on cond.

! A condition variable always wakes with its mutex locked.

Return:0 on success, non‐0 otherwise. pthread_cond_timedwait returns ETIMEDOUTin the case of a time‐out.

Page 32: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Condition Variable Example

bake_pie();while ( 1 ){

bool bake_another = false;PTH_MUTEX_LOCK( &mutex_ );if ( num_pies_ < max_pies_ ){

++num_pies_;bake_another = true;PTH_COND_SIGNAL( &driver_cond_ );

}else

PTH_COND_WAIT( &baker_cond_, &mutex_ );PTH_MUTEX_UNLOCK( &mutex_ );if ( bake_another )

bake_pie();}

Baker Thread1. Bake a pie.2. Lock...3. If there’s room in the queue:

a) Add the pie to the queue.b) Signal the driver.

4. If there’s no room in the queue:a) wait

5. Unlock...6. If possible, bake another pie.

Page 33: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Condition Variable Example (cont.)

while ( 1 ){

bool deliver = false;PTH_MUTEX_LOCK( &mutex_ );if ( num_pies_ > 0 ){

--num_pies_;deliver = true;PTH_COND_SIGNAL( &baker_cond_ );

}else

PTH_COND_WAIT( &driver_cond_, &mutex_ );PTH_MUTEX_UNLOCK( &mutex_ );if ( deliver )

deliver_pie();}

1. Lock...2. If a pie is in the queue:

a) Remove it from the queue.b) Signal the baker.

3. If no pie is waitinga) Wait

4. Unlock...5. If necessary, deliver the pie

Driver Thread

Page 34: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Exercises1. Add the macro PTH_COND_TIMEDWAIT (which invokes 

pthread_cond_timedwait) to pth_utils.h.2. Modify mutex_exercise so that:

– It contains a condition variabe– When the incrementing thread successfully increments the counter it signals 

the condition variable; if it can’t increment the counter it waits on the condition variable.

– When the decrementing thread successfully decrements the counter it signals the condition variable; if it can’t decrement the counter it waits on the condition variable.

Page 35: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_oncetypedef void ONCE_PROC_t( void );typedef ONCE_PROC_t *ONCE_PROC_p_t;int pthread_once( pthread_once_t *control, ONCE_PROC_p_t init_proc );

For performing global initialization once.

control

Variable to control initialization; MUST be statically allocated, MUST be initialized with PTHREAD_ONCE_INIT.

init_proc

Address of initialization function.Returns:

0 for success, non‐zero otherwise.

Page 36: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: pthread_once, Exampleint main( int argc, char **argv ){

int status;PTH_CREATE( &thr1_, NULL, thr_start, NULL );PTH_CREATE( &thr2_, NULL, thr_start, NULL );PTH_CREATE( &thr3_, NULL, thr_start, NULL );. . .

}static void init( void ){

puts( "init starting" );// perform global initialization hereputs( "init ending" );

}static void *thr_start( void *arg ){

static pthread_once_t init_once = PTHREAD_ONCE_INIT;int status;PTH_ONCE( &init_once, init );. . .

}

Output:init startinginit ending

Page 37: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Mutex AttributesSee: pthread_mutexattr_setpshared;• PTHREAD_PROCESS_SHARED: allow mutexes to control threads in multiple 

processes.• PTHREAD_PROCESS_PRIVATE: mutexes may not be accessed outside the 

initializing process.

See: pthread_mutexattr_setprioceiling;Sets the  maximum priority for the critical section guarded by a mutex.

See: pthread_mutexattr_setprotocol;Controls the priority and scheduling of threads that own the target mutex.

Systems are not required to implement this functionality; check your documentation.

Page 38: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Condition Variable AttributesSee: pthread_condattr_setpshared;• PTHREAD_PROCESS_SHARED: allow a condition variable to control threads in 

multiple processes.• PTHREAD_PROCESS_PRIVATE: condition variables may not be accessed 

outside the initializing process.

Systems are not required to implement this functionality; check your documentation.

Page 39: Posix® Threads (Pthreads)faculty.washington.edu/jstraub/isilon/isilon1/Unit 9.pdf · Posix® Threads (Pthreads) Reference: Programming with POSIX® Threads by David R. Butenhof,

Pthreads: Thread AttributesSee:• pthread_attr_setdetachstate• pthread_attr_setguardsize• pthread_attr_setinheritsched• pthread_attr_setschedparam• pthread_attr_setschedpolicy• pthread_attr_setscope• pthread_attr_setstackaddr• pthread_attr_setstacksize

Systems are not required to implement all of this functionality; check your documentation.