Back to index

glibc  2.9
ex14.c
Go to the documentation of this file.
00001 /* Test of POSIX barriers.  */
00002 
00003 #include <pthread.h>
00004 #include <stdio.h>
00005 #include <stdlib.h>
00006 #include <string.h>
00007 
00008 #define NTHREADS 20
00009 
00010 #define ROUNDS 20
00011 
00012 static pthread_barrier_t barriers[NTHREADS];
00013 
00014 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
00015 static int counters[NTHREADS];
00016 static int serial[NTHREADS];
00017 
00018 static void *
00019 worker (void *arg)
00020 {
00021   void *result = NULL;
00022   int nr = (long int) arg;
00023   int i;
00024 
00025   for (i = 0; i < ROUNDS; ++i)
00026     {
00027       int j;
00028       int retval;
00029 
00030       if (nr == 0)
00031        {
00032          memset (counters, '\0', sizeof (counters));
00033          memset (serial, '\0', sizeof (serial));
00034        }
00035 
00036       retval = pthread_barrier_wait (&barriers[NTHREADS - 1]);
00037       if (retval != 0 && retval != PTHREAD_BARRIER_SERIAL_THREAD)
00038        {
00039          printf ("thread %d failed to wait for all the others\n", nr);
00040          result = (void *) 1;
00041        }
00042 
00043       for (j = nr; j < NTHREADS; ++j)
00044        {
00045          /* Increment the counter for this round.  */
00046          pthread_mutex_lock (&lock);
00047          ++counters[j];
00048          pthread_mutex_unlock (&lock);
00049 
00050          /* Wait for the rest.  */
00051          retval = pthread_barrier_wait (&barriers[j]);
00052 
00053          /* Test the result.  */
00054          if (nr == 0 && counters[j] != j + 1)
00055            {
00056              printf ("barrier in round %d released but count is %d\n",
00057                     j, counters[j]);
00058              result = (void *) 1;
00059            }
00060 
00061          if (retval != 0)
00062            {
00063              if (retval != PTHREAD_BARRIER_SERIAL_THREAD)
00064               {
00065                 printf ("thread %d in round %d has nonzero return value != PTHREAD_BARRIER_SERIAL_THREAD\n",
00066                        nr, j);
00067                 result = (void *) 1;
00068               }
00069              else
00070               {
00071                 pthread_mutex_lock (&lock);
00072                 ++serial[j];
00073                 pthread_mutex_unlock (&lock);
00074               }
00075            }
00076 
00077          /* Wait for the rest again.  */
00078          retval = pthread_barrier_wait (&barriers[j]);
00079 
00080          /* Now we can check whether exactly one thread was serializing.  */
00081          if (nr == 0 && serial[j] != 1)
00082            {
00083              printf ("not exactly one serial thread in round %d\n", j);
00084              result = (void *) 1;
00085            }
00086        }
00087     }
00088 
00089   return result;
00090 }
00091 
00092 
00093 #define TEST_FUNCTION do_test ()
00094 #define TIMEOUT 60
00095 static int
00096 do_test (void)
00097 {
00098   pthread_t threads[NTHREADS];
00099   int i;
00100   void *res;
00101   int result = 0;
00102 
00103   /* Initialized the barrier variables.  */
00104   for (i = 0; i < NTHREADS; ++i)
00105     if (pthread_barrier_init (&barriers[i], NULL, i + 1) != 0)
00106       {
00107        printf ("Failed to initialize barrier %d\n", i);
00108        exit (1);
00109       }
00110 
00111   /* Start the threads.  */
00112   for (i = 0; i < NTHREADS; ++i)
00113     if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
00114       {
00115        printf ("Failed to start thread %d\n", i);
00116        exit (1);
00117       }
00118 
00119   /* And wait for them.  */
00120   for (i = 0; i < NTHREADS; ++i)
00121     if (pthread_join (threads[i], &res) != 0 || res != NULL)
00122       {
00123        printf ("thread %d returned a failure\n", i);
00124        result = 1;
00125       }
00126 
00127   if (result == 0)
00128     puts ("all OK");
00129 
00130   return result;
00131 }
00132 
00133 #include "../test-skeleton.c"