about summary refs log tree commit diff
path: root/linuxthreads/Examples/ex3.c
diff options
context:
space:
mode:
Diffstat (limited to 'linuxthreads/Examples/ex3.c')
-rw-r--r--linuxthreads/Examples/ex3.c152
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);
+}