thread-safe programming living with linux. thread-safe programming tommy reynolds fedora...

23
Thread-Safe Programming Living With Linux

Upload: meghan-elliott

Post on 29-Jan-2016

216 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Thread-Safe Programming

Living With Linux

Page 2: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Thread-Safe Programming

Tommy ReynoldsFedora Documentation Project

Steering Committeehttp://www.megacoder.com

Page 3: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

What Are Threads?

• Multiple execution paths in a single program.

• Threads share common address space, credentials, and resource limits.

• POSIX threading model assumes threads are not visible to the O/S kernel.

• Linux doesn’t work this way.

Page 4: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Native POSIX Thread Library

• Traditional POSIX threads require an application-side manager thread

1. O/S schedules application based on overall behavior

2. Application’s manager thread chooses appropriate thread to run.

• On Linux, threads are known to kernel• This lets Linux scheduler make an

optimal choice

Page 5: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Mindset Warping

• Plan for multi-threaded behavior from the beginning

• “Multi-threaded” is all or nothing; even one little thread brings ALL the thread synchronization problems to the forefront

• Always think “is it safe for my other application threads to run while I’m executing this statement” is appropriate paranoia

Page 6: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Compiling A Threaded Program

• Compiler dependent, no standard technique

• Often, special defines and libraries are needed

• Preferred GCC method:

$ gcc -pthread -o foo foo.c

Page 7: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Application Considerations

• Threaded application is a different animal from traditional applications

• Any thread could start running at any time

• Resources shared between threads must be carefully guarded.

• Synchronization tools1. Semaphore (aka MUTEX)2. Condition Variables (aka CV)

Page 8: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Your First Thread Is Free...

• In every program, a default thread is created that runs the main() function

• Traditional POSIX implementations also create a manager thread, but Linux doesn't

• All other threads are created by application• Unlike fork / wait model, there is no parent /

child relationship among threads.• Knowing when sibling thread terminates

takes special effort.

Page 9: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Keeping The Balance

• Traditional applications can use fork(2) and wait(2) to manage processes.

• Threads use pthread_create(P) and pthread_join(P) to a similar purpose.

• Threads are expected to return an exit status.

• Threads may be detached if the exit status is of no interest; avoid zombie threads!

Page 10: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Shape Of A Thread

#include <pthread.h>

void *

thread(

void * arg

)

{

myarg_t * myarg = arg;

int results;

...

pthread_exit( &results );

}

Page 11: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Cleaning Up Cleanly

#include <pthread.h>...void unwind( void * arg ){

/* Whatever */}

void * thread( void * arg ){

pthread_cleanup_push( unwind, arg );/* Funky stuff */pthread_cleanup_pop( 1 );pthread_exit( NULL );

}

Page 12: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Signal Handling

• Threads all share signal handlers• Asynchronous signals (SIGHUP, SIGTERM, SIGUSR1) offered to all threads in a process

• Synchronous signals (SIGFPE, SIGBUS, SIGSEGV) delivered to offending thread

• Use pthread_kill(P) to send signal to a specific thread

Page 13: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

What Are Shared Resources?

• Global variables accessed (read or write) by multiple threads

• Shared data areas (read or write); often passed via pointer

• Most standard library routines – many have re-entrant versions

• Even malloc(3) and free(3) are not thread safe

Page 14: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Critical Regions Considered Harmful

• Puts guards around lines of code that access shared resourcesdisable_interrupts()

hw->reg &= ~(1 << 10)

enable_interrupts()

• Wrong focus – protect shared resources, not code

• Think about shared resources, not code

Page 15: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Application Toolkit

• Needed for the same reason you can’t call printf() from a signal handler.

• Use semaphores (MUTEX) and Condition Variables

• Avoid race conditions, where the result depends on who finishes first

• Non-repeatable behavior is very hard to debug

Page 16: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Semaphores(Spelled “MUTEX”)

• POSIX version of Nicholas Wirth’s P/V semaphores (yes / no decisions)

• Defined in <pthread.h>

• Always in either locked or unlocked state

• pthread_mutex_lock() blocks until lock is unlocked and then returns

• pthread_mutex_unlock() unlocks semaphore, awakens any blocked threads

Page 17: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Example Using MUTEX#include <pthread.h>pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;static int k;

void * producer( void * arg ){

pthread_mutex_lock( &m );++k;pthread_mutex_unlock( &m );

}

void * consumer( void * arg ){

pthread_mutex_lock( &m );printf( “k = %d\n”, k );pthread_mutex_unlock( &m );

}

Page 18: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Condition Variables

• Semaphores are for yes or no decisions• Condition Variables permit complicated

decisions to be made atomically• Guards the test (function call!) with a

MUTEX• Grabs the MUTEX; checks the condition; if

not true, release MUTEX then block then re-acquire MUTEX without missing anything

Page 19: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Condition Variable Example#include <pthread.h>pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cv = PTHREAD_COND_INITIALIZER;

void * consumer( void * ){

pthread_mutex_lock( &m );while( check_for_messages() == 0 ) {

pthread_cond_wait( &cv, &m );}consume_messages();pthread_mutex_unlock( &m );

}

void * producer( void * ){

pthread_mutex_lock( &m );accept_another_message();pthread_cond_broadcast( &cv );pthread_mutex_unlock( &m );

}

Page 20: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Using Standard Library With Threads

• Thread-safe standard library version of foo() is usally named foo_r()

• Protect others using a MUTEX

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;

…pthread_mutex_lock( &m );ptr = malloc( 10 );pthread_mutex_unlock( &m );…

Page 21: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Accessing One File From Two Threads

• Use O_EXCL for open(2) system call, although this is advisory only

• Threads within the same process can wrap the access with a MUTEX

• Separate applications often link(2) a known filename, do the access, then unlink(2) the guard file

Page 22: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

In Summary, En Passant

• POSIX-standard thread API permits portable programs with expected behavior

• Requires “three-dimensional” thinking by the application programmer

• Seemingly innocuous practices can be fraught with peril – programmers must be aware of ALL threats

• There is no cook-book solution

Page 23: Thread-Safe Programming Living With Linux. Thread-Safe Programming Tommy Reynolds Fedora Documentation Project Steering Committee

Protect Your Thread Territory

-or-

This Is The End