Linux Programming –Threads CS 230. 2 Threads Review Threads in the same address space –share...
-
Upload
cornelius-stokes -
Category
Documents
-
view
219 -
download
1
Transcript of Linux Programming –Threads CS 230. 2 Threads Review Threads in the same address space –share...
Linux Programming –Threads
CS 230
2
Threads Review
• Threads in the same address space
– share everything in the address space
– lighter than process
– no protection between threads
• Why is it lighter than process?
– no overhead for address space management
» no page table(no TLB misses)
» cache misses
• Two kinds of threads
– kernel threads (Pthreads, Solaris Threads, …)
– user level threads
3
Address Space with Threads
thread thread thread
files
Virtual AddressSpace
heap
stack
code
registers registers registers
stack stack stack
4
Introduction to Pthreads
• POSIX
– IEEE API standard for Unix family OS’es
– includes threads standard : pthreads
• tutorials
– http://www.mit.edu/people/proven/IAP_2000/index.html
– http://mas.cs.umass.edu/~wagner/threads_html/
• compile
– gcc -flags source_file.c -lpthread (-lposix4)
5
Thread Creation
• a_thread: thread handle
• a_thread_attribute:
– only stack size can be specified with the current version
– use NULL to accept the default values
• thread_function: code to execute
• some_argument: arguments to that code
pthread_t a_thread; pthread_attr_t a_thread_attribute; void thread_function(void *argument); char *some_argument; pthread_create( &a_thread, a_thread_attribute, (void *)&thread_function, (void *) &some_argument);
6
pthread_create() Example
void print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); }
main() { pthread_t thread1, thread2; char *message1 = "Hello"; char *message2 = "World"; pthread_create( &thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); /* two threads are racing */ exit(0); /* this may cause problem: no or partial output */ }
7
Synchronization
• pthread_join(that_thread, &status)
– wait until that_thread completes
– read “man” for the meaning of *status (the return value of the terminating thread)
• mutex (mutual exclusion) - dynamic creationpthread_mutex_t *mutexp;
mutexp = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutexp, NULL)
pthread_mutex_lock(mutexp);
• mutex - static creationpthread_mutex_t xxx = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&xxx);
• pthread_mutex_destroy(&mutex)
• can be used for inter-process communications
8
Synchronization (cont’d)
• int pthread_mutex_trylock(&mutex);
– do not block the calling thread
– useful for polling
» checking IO status
» avoid deadlock, priority inversion
• review of mutex
– most popular primitives
– easy to use
» easy to understand what it is
– prone to errors
» programmers forget to unlock
» what if another thread forgets to use lock
» very difficult to understand programs that contain it
9
Semaphore
• why semaphore
– mutex may result in busy-waiting
– mutex is only for “mutual exclusion” - no sharing
– no guarantee of fairness
• semaphore
– a shared variable with two attributes
» integer value: number of threads that can share this semaphore• allows n threads to share
» thread list: list of threads waiting for this semaphore• guarantees FIFO order
• operations
– cc [ flag ... ] file ... -lposix4 [ library ... ] /* lib for real time extension */
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value );
– pshared: if non-zero, it is shared between processes
» i.e., zero means that it will be used between threads
10
Semaphore(cont’d)
• int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem);
if the integer value > 0, decrement it and proceeds
else block (or fail for trywait)
• int sem_post(sem_t *sem);
– if there is a thread waiting,
» wake up a thread according to its schedparam• ptread_attr_setschedparm();
– else increment the integer value
• int sem_destroy(sem_t *sem);
– other combination
» sem_open(), sem_close()
11
Producer/Consumer using mutex
void producer_function(void) { while(1) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 0 ) { buffer = make_new_item(); buffer_has_item = 1; } pthread_mutex_unlock( &mutex ); pthread_delay_np( &delay ); } }
void consumer_function(void)
{
while(1)
{
pthread_mutex_lock( &mutex );
if ( buffer_has_item == 1)
{
consume_item( buffer );
buffer_has_item = 0;
}
pthread_mutex_unlock( &mutex );
pthread_delay_np( &delay );
}
}
12
Producer/Consumer using semaphore
void producer_function(void) { while(1) { semaphore_down( &writers_turn ); buffer = make_new_item(); semaphore_up( &readers_turn ); } }
void consumer_function(void) { while(1) { semaphore_down( &readers_turn ); consume_item( buffer ); semaphore_up( &writers_turn ); } }
13
Programming Models
• Master/Slave
– socket program example
– thread is created on the fly
• work queue model
– the work queue contains a bag of works
– a set of worker threads are created a priori
– each thread does the following until done
» competes to fetch a work from the queue
» compute on the work
» generate another work, if any
» insert the new work into the queue
• threads created a priori
– if they are too many, there would be idle threads - a waste
– if they are too few, not enough concurrency to carry the work
– solution
» prepare some threads a priori and create(and kill) more threads as necessary
14
Thread Canceling
• why does a thread need to be cancelled
– a transaction: all or nothing
• pthread_cancel(pid)
– a cancelled thread needs to be joined (zombie!)
– detached threads do not need to be joined
• thread types about cancellation
pthread_setcanceltype(type, NULL);
– PTHREAD_CANCEL_ASYNCHRONOUS: cancel ASAP
– PTHREAD_CANCEL_DEFERRED: deferred until cancel point
– cancel points
» pthread_testcancel()
» pthread_join(), pthread_cond_wait(), sem_wait()
• uncancelable thread
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)
– use it inside a critical section
15
Thread-Specific Data
• threads belong to the same process(address space)
– share all the data
– weak protection for the shared data
• Linux provides a space for data private to a thread
– each item should be created associated with a key
static pthread_key_t test_key;pthread_key_create (&test_key, clean_up);pthread_setspecific (test_key, data_to_store); /*
write */data_to_read = pthread_getspecific (test_key); /*
read */» when a thread exits, clean_up is called
• clean up can be installed without thread-specific data
– prevents memory leak
– clean up function is called when a thread exits
16
clean up example
void* allocate_buffer (size_t size){ return malloc (size);}
void deallocate_buffer (void* buffer){ free (buffer);}
void do_some_work (){ void* temp_buffer = allocate_buffer (1024); pthread_cleanup_push (deallocate_buffer, temp_buffer); /* Do some work here that might call pthread_exit or might be cancelled... */ /* Unregister the cleanup handler. Because we pass a nonzero value, this actually performs the cleanup by calling deallocate_buffer. */ pthread_cleanup_pop (1);}