diff options
Diffstat (limited to 'linuxthreads/Examples/ex3.c')
| -rw-r--r-- | linuxthreads/Examples/ex3.c | 152 | 
1 files changed, 152 insertions, 0 deletions
| diff --git a/linuxthreads/Examples/ex3.c b/linuxthreads/Examples/ex3.c new file mode 100644 index 0000000000..b80b323a33 --- /dev/null +++ b/linuxthreads/Examples/ex3.c @@ -0,0 +1,152 @@ +/* Multi-thread searching. +   Illustrates: thread cancellation, cleanup handlers. */ + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <pthread.h> + +/* Defines the number of searching threads */ +#define NUM_THREADS 5 + +/* Function prototypes */ +void *search(void *); +void print_it(void *); + +/* Global variables */ +pthread_t threads[NUM_THREADS]; +pthread_mutex_t lock; +int tries; +volatile int started; + +int main(int argc, char ** argv) +{ +  int i; +  int pid; + +  /* create a number to search for */ +  pid = getpid(); +  printf("Searching for the number = %d...\n", pid); + +  /* Initialize the mutex lock */ +  pthread_mutex_init(&lock, NULL); + +  /* Create the searching threads */ +  for (started=0; started<NUM_THREADS; started++) +    pthread_create(&threads[started], NULL, search, (void *) (long int) pid); + +  /* Wait for (join) all the searching threads */ +  for (i=0; i<NUM_THREADS; i++) +    pthread_join(threads[i], NULL); + +  printf("It took %d tries to find the number.\n", tries); + +  /* Exit the program */ +  return 0; +} + +/* This is the cleanup function that is called +   when the threads are cancelled */ + +void print_it(void *arg) +{ +  int *try = (int *) arg; +  pthread_t tid; + +  /* Get the calling thread's ID */ +  tid = pthread_self(); + +  /* Print where the thread was in its search when it was cancelled */ +  printf("Thread %lx was canceled on its %d try.\n", tid, *try); +} + +/* This is the search routine that is executed in each thread */ + +void *search(void *arg) +{ +  int num = (long int) arg; +  int i, j, ntries; +  pthread_t tid; + +  /* get the calling thread ID */ +  tid = pthread_self(); + +  /* use the thread ID to set the seed for the random number generator */ +  /* Since srand and rand are not thread-safe, serialize with lock */ + +  /* Try to lock the mutex lock -- +     if locked, check to see if the thread has been cancelled +     if not locked then continue */ +  while (pthread_mutex_trylock(&lock) == EBUSY) +    pthread_testcancel(); + +  srand((int)tid); +  i = rand() & 0xFFFFFF; +  pthread_mutex_unlock(&lock); +  ntries = 0; + +  /* Set the cancellation parameters -- +     - Enable thread cancellation +     - Defer the action of the cancellation */ + +  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); +  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + +  while (started < NUM_THREADS) +    sched_yield (); + +  /* Push the cleanup routine (print_it) onto the thread +     cleanup stack.  This routine will be called when the +     thread is cancelled.  Also note that the pthread_cleanup_push +     call must have a matching pthread_cleanup_pop call.  The +     push and pop calls MUST be at the same lexical level +     within the code */ + +  /* Pass address of `ntries' since the current value of `ntries' is not +     the one we want to use in the cleanup function */ + +  pthread_cleanup_push(print_it, (void *)&ntries); + +  /* Loop forever */ +  while (1) { +    i = (i + 1) & 0xFFFFFF; +    ntries++; + +    /* Does the random number match the target number? */ +    if (num == i) { +      /* Try to lock the mutex lock -- +         if locked, check to see if the thread has been cancelled +         if not locked then continue */ +      while (pthread_mutex_trylock(&lock) == EBUSY) +        pthread_testcancel(); + +      /* Set the global variable for the number of tries */ +      tries = ntries; +      printf("Thread %lx found the number!\n", tid); + +      /* Cancel all the other threads */ +      for (j=0; j<NUM_THREADS; j++) +        if (threads[j] != tid) pthread_cancel(threads[j]); + +      /* Break out of the while loop */ +      break; +    } + +    /* Every 100 tries check to see if the thread has been cancelled. */ +    if (ntries % 100 == 0) { +      pthread_testcancel(); +    } +  } + +  /* The only way we can get here is when the thread breaks out +     of the while loop.  In this case the thread that makes it here +     has found the number we are looking for and does not need to run +     the thread cleanup function.  This is why the pthread_cleanup_pop +     function is called with a 0 argument; this will pop the cleanup +     function off the stack without executing it */ + +  pthread_cleanup_pop(0); +  return((void *)0); +} | 
