Back to index

glibc  2.9
tst-barrier3.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 /* Test of POSIX barriers.  */
00021 
00022 #include <pthread.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 
00027 #define NTHREADS 20
00028 
00029 #define ROUNDS 20
00030 
00031 static pthread_barrier_t barriers[NTHREADS];
00032 
00033 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
00034 static int counters[NTHREADS];
00035 static int serial[NTHREADS];
00036 
00037 static void *
00038 worker (void *arg)
00039 {
00040   void *result = NULL;
00041   int nr = (long int) arg;
00042   int i;
00043 
00044   for (i = 0; i < ROUNDS; ++i)
00045     {
00046       int j;
00047       int retval;
00048 
00049       if (nr == 0)
00050        {
00051          memset (counters, '\0', sizeof (counters));
00052          memset (serial, '\0', sizeof (serial));
00053        }
00054 
00055       retval = pthread_barrier_wait (&barriers[NTHREADS - 1]);
00056       if (retval != 0 && retval != PTHREAD_BARRIER_SERIAL_THREAD)
00057        {
00058          printf ("thread %d failed to wait for all the others\n", nr);
00059          result = (void *) 1;
00060        }
00061 
00062       for (j = nr; j < NTHREADS; ++j)
00063        {
00064          /* Increment the counter for this round.  */
00065          pthread_mutex_lock (&lock);
00066          ++counters[j];
00067          pthread_mutex_unlock (&lock);
00068 
00069          /* Wait for the rest.  */
00070          retval = pthread_barrier_wait (&barriers[j]);
00071 
00072          /* Test the result.  */
00073          if (nr == 0 && counters[j] != j + 1)
00074            {
00075              printf ("barrier in round %d released but count is %d\n",
00076                     j, counters[j]);
00077              result = (void *) 1;
00078            }
00079 
00080          if (retval != 0)
00081            {
00082              if (retval != PTHREAD_BARRIER_SERIAL_THREAD)
00083               {
00084                 printf ("thread %d in round %d has nonzero return value != PTHREAD_BARRIER_SERIAL_THREAD\n",
00085                        nr, j);
00086                 result = (void *) 1;
00087               }
00088              else
00089               {
00090                 pthread_mutex_lock (&lock);
00091                 ++serial[j];
00092                 pthread_mutex_unlock (&lock);
00093               }
00094            }
00095 
00096          /* Wait for the rest again.  */
00097          retval = pthread_barrier_wait (&barriers[j]);
00098 
00099          /* Now we can check whether exactly one thread was serializing.  */
00100          if (nr == 0 && serial[j] != 1)
00101            {
00102              printf ("not exactly one serial thread in round %d\n", j);
00103              result = (void *) 1;
00104            }
00105        }
00106     }
00107 
00108   return result;
00109 }
00110 
00111 
00112 #define TEST_FUNCTION do_test ()
00113 #define TIMEOUT 60
00114 static int
00115 do_test (void)
00116 {
00117   pthread_t threads[NTHREADS];
00118   int i;
00119   void *res;
00120   int result = 0;
00121 
00122   /* Initialized the barrier variables.  */
00123   for (i = 0; i < NTHREADS; ++i)
00124     if (pthread_barrier_init (&barriers[i], NULL, i + 1) != 0)
00125       {
00126        printf ("Failed to initialize barrier %d\n", i);
00127        exit (1);
00128       }
00129 
00130   /* Start the threads.  */
00131   for (i = 0; i < NTHREADS; ++i)
00132     if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
00133       {
00134        printf ("Failed to start thread %d\n", i);
00135        exit (1);
00136       }
00137 
00138   /* And wait for them.  */
00139   for (i = 0; i < NTHREADS; ++i)
00140     if (pthread_join (threads[i], &res) != 0 || res != NULL)
00141       {
00142        printf ("thread %d returned a failure\n", i);
00143        result = 1;
00144       }
00145     else
00146       printf ("joined threads %d\n", i);
00147 
00148   if (result == 0)
00149     puts ("all OK");
00150 
00151   return result;
00152 }
00153 
00154 #include "../test-skeleton.c"