123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- /* 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)
- {
- unsigned long i;
- unsigned long pid;
- /* create a number to search for */
- pid = getpid();
- printf("Searching for the number = %ld...\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 *)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)
- {
- unsigned long num = (unsigned long) arg;
- unsigned long 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);
- }
|