1 / 29

POSIX Threads

POSIX Threads. Nezer J. Zaidenberg. References. Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist in first edition) Many manuals exist on the web Yolinux.com : POSIX thread (pthread) libraries (very basic and I found some mistakes there!)

gen
Download Presentation

POSIX Threads

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. POSIX Threads Nezer J. Zaidenberg

  2. References • Advanced programming for the UNIX environment (2nd edition chapter 11+12 This material does not exist in first edition) • Many manuals exist on the web • Yolinux.com : POSIX thread (pthread) libraries (very basic and I found some mistakes there!) • http://www.ibm.com/developerworks/library/l-posix1.html (and chapters 2/3) • Programming with POSIX(R) Threads by David Botenhof (more advanced then this course)

  3. Simple thread program code

  4. #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *print_message_function( void *ptr ); main() { pthread_t thread1, thread2; char *message1 = "Thread 1"; char *message2 = "Thread 2"; pthread_create( &thread1, NULL, print_message_function, (void*) message1); pthread_create( &thread2, NULL, print_message_function, (void*) message2); pthread_join( thread1, NULL); pthread_join( thread2, NULL); exit(0); } void *print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s \n", message); }

  5. Two important notes • To compile : • C : gcc -lpthread thread.c • C++ : g++ -lpthread thread.cxx • Other platforms and compilers may require -pthread flag instead • Never code like this • You should check pthread create return value

  6. Why do we need thread library • In Linux malloc(3) is normally not thread safe to speed things up (no locking and unlocking) • That means that when we use threads – we must use different malloc(3) • This is also true in Windows while in OSX malloc is always thread safe.

  7. Pthread_create(3) SYNOPSIS #include <pthread.h> int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg); Arguments thread - returns the thread id. (unsigned long int defined in bits/pthreadtypes.h) attr - Set to NULL if default thread attributes are used. (else define members of the struct pthread_attr_t defined in bits/pthreadtypes.h) void * (*start_routine) - pointer to the function to be threaded. Function has a single argument: pointer to void. *arg - pointer to argument of function. To pass multiple arguments, send a pointer to a structure.

  8. Pthread exit(3) – exit(2) for threads SYNOPSIS #include <pthread.h> void pthread_exit(void *retval); Arguments: * retval - Return value of thread.

  9. Pthread join(3) – wait(2) for threads SYNOPSIS #include <pthread.h> int pthread_join(pthread_t thread, void **value_ptr); Arguments Value_ptr = the value returned by thread This function is BLOCKING!!!

  10. Passing arguments to/from threads • Can be done using the void pointer (cast the void * into a struct and point into any number of arguments) • Return values can be returned in the same way • Shared memory is also used for this (but is less recommended because of problems with syncing)

  11. Example (1/3) #define _MULTI_THREADED #include <pthread.h> #include <stdio.h> #include "check.h” typedef struct { int value; char string[128]; } thread_parm_t; void *threadfunc(void *parm) { thread_parm_t *p = (thread_parm_t *)parm; printf("%s, parm = %d\n", p->string, p->value); free(p); return NULL; }

  12. Example 2/3 int main(int argc, char **argv) { pthread_t thread; int rc=0; thread_parm_t *parm=NULL; printf("Create a thread attributes object\n"); parm = malloc(sizeof(thread_parm_t)); parm->value = 5; strcpy(parm->string, "Inside first thread"); rc = pthread_create(&thread, NULL, threadfunc, (void *)parm); parm = malloc(sizeof(thread_parm_t)); parm->value = 77; strcpy(parm->string, "Inside second thread");

  13. Example 3/3 rc = pthread_create(&thread, NULL, threadfunc, (void *)parm); sleep(5); printf("Main completed\n"); return 0; }

  14. Problems with example • Check return code (existed in the original example) • Don’t use sleep() to wait for thread! – use pthread_join(3). • Avoid heap memory allocation. (It was used in the original example and I wanted to show shared memory and cases where one thread malloc(3)s and another free(3).)

  15. Thread attributes • detached state (joinable? Default: PTHREAD_CREATE_JOINABLE. Other option: PTHREAD_CREATE_DETACHED) • scheduling policy (real-time? PTHREAD_INHERIT_SCHED,PTHREAD_EXPLICIT_SCHED,SCHED_OTHER) • scheduling parameter • inheritsched attribute (Default: PTHREAD_EXPLICIT_SCHED Inherit from parent thread: PTHREAD_INHERIT_SCHED) • scope (Kernel threads: PTHREAD_SCOPE_SYSTEM User threads: PTHREAD_SCOPE_PROCESS Pick one or the other not both.) • guard size • stack address (See unistd.h and bits/posix_opt.h _POSIX_THREAD_ATTR_STACKADDR) • stack size (default minimum PTHREAD_STACK_SIZE set in pthread.h),

  16. In the scope of this course we will always use NULL for thread attributes

  17. Sync using mutex (1/2) #include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; int counter = 0; void *functionC() { pthread_mutex_lock( &mutex1 ); counter++; printf("Counter value: %d\n",counter); pthread_mutex_unlock( &mutex1 ); }

  18. Syncing 2/2 int main() { int rc1, rc2; pthread_t thread1, thread2; if( (rc1=pthread_create( &thread1, NULL, &functionC, NULL)) ) { printf("Thread creation failed: %d\n", rc1); } if( (rc2=pthread_create( &thread2, NULL, &functionC, NULL)) ) { printf("Thread creation failed: %d\n", rc2); } // ++counter pthread_join( thread1, NULL); pthread_join( thread2, NULL); exit(0); }

  19. Pthread_mutex_lock SYNOPSIS #include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); Lock function is blocking Try lock function is not blocking (it would lock if it can) Unlock release

  20. Using cond (1/7) #include <pthread.h> #include <stdio.h> #include <stdlib.h> #define NUM_THREADS 3 #define TCOUNT 10 #define COUNT_LIMIT 12 int count = 0; int thread_ids[3] = {0,1,2}; pthread_mutex_t count_mutex; pthread_cond_t count_threshold_cv;

  21. Using cond 2/7 int main(int argc, char *argv[]) { int i, rc; pthread_t threads[3]; /* Initialize mutex and condition variable objects */ pthread_mutex_init(&count_mutex, NULL); pthread_cond_init (&count_threshold_cv, NULL); pthread_create(&threads[0], NULL, inc_count, (void *)&thread_ids[0]); pthread_create(&threads[1], NULL, inc_count, (void *)&thread_ids[1]); pthread_create(&threads[2], NULL, watch_count, (void *)&thread_ids[2]);

  22. Cond 3/7 /* Wait for all threads to complete */ for (i = 0; i < NUM_THREADS; i++) { pthread_join(threads[i], NULL); } printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS); /* Clean up and exit */ pthread_mutex_destroy(&count_mutex); pthread_cond_destroy(&count_threshold_cv); pthread_exit (NULL); }

  23. Using cond 4/7 void *inc_count(void *idp) { int j,i; double result=0.0; int *my_id = idp; for (i=0; i < TCOUNT; i++) { pthread_mutex_lock(&count_mutex); count++; /* Check the value of count and signal waiting thread when condition is reached. Note that this occurs while mutex is locked. */

  24. Cond 5/7 if (count == COUNT_LIMIT) { pthread_cond_signal(&count_threshold_cv); printf("inc_count(): thread %d, count = %d Threshold reached.\n", *my_id, count); } printf("inc_count(): thread %d, count = %d, unlocking mutex\n”, *my_id, count); pthread_mutex_unlock(&count_mutex); /* Do some work so threads can alternate on mutex lock */ for (j=0; j < 10000; j++) result = result + (double)random(); } pthread_exit(NULL); }

  25. Using cond 6/7 void *watch_count(void *idp) { int *my_id = idp; printf("Starting watch_count(): thread %d\n", *my_id); /* Lock mutex and wait for signal. Note that the pthread_cond_wait routine will automatically and atomically unlock mutex while it waits. Also, note that if COUNT_LIMIT is reached before this routine is run by the waiting thread, the loop will be skipped to prevent pthread_cond_wait from never returning. */

  26. Using Cond 7/7 pthread_mutex_lock(&count_mutex); if (count < COUNT_LIMIT) { pthread_cond_wait(&count_threshold_cv, &count_mutex); printf("watch_count(): thread %d Condition signal received.\n", *my_id); } pthread_mutex_unlock(&count_mutex); pthread_exit(NULL); }

  27. Things to note • Cond modify a mutex. • Cond operations are protected by mutex.

  28. Good and bad things • Check return code • In your practice code add some work so threads will alternate

  29. Mutex and cond summary

More Related