root/maint/gnulib/tests/test-pthread-cond.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pthread_cond_wait_routine
  2. test_pthread_cond_wait
  3. get_ts
  4. pthread_cond_timedwait_routine
  5. test_pthread_cond_timedwait
  6. main
  7. main

   1 /* Test of condition variables in multithreaded situations.
   2    Copyright (C) 2008-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 #include <config.h>
  18 
  19 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
  20 
  21 /* Which tests to perform.
  22    Uncomment some of these, to verify that all tests crash if no locking
  23    is enabled.  */
  24 #define DO_TEST_COND 1
  25 #define DO_TEST_TIMEDCOND 1
  26 
  27 /* Whether to help the scheduler through explicit sched_yield().
  28    Uncomment this to see if the operating system has a fair scheduler.  */
  29 #define EXPLICIT_YIELD 1
  30 
  31 /* Whether to print debugging messages.  */
  32 #define ENABLE_DEBUGGING 0
  33 
  34 #include <pthread.h>
  35 #include <stdio.h>
  36 #include <stdlib.h>
  37 #include <string.h>
  38 #include <sys/time.h>
  39 
  40 #if EXPLICIT_YIELD
  41 # include <sched.h>
  42 #endif
  43 
  44 #if HAVE_DECL_ALARM
  45 # include <signal.h>
  46 # include <unistd.h>
  47 #endif
  48 
  49 #include "macros.h"
  50 
  51 #if ENABLE_DEBUGGING
  52 # define dbgprintf printf
  53 #else
  54 # define dbgprintf if (0) printf
  55 #endif
  56 
  57 #if EXPLICIT_YIELD
  58 # define yield() sched_yield ()
  59 #else
  60 # define yield()
  61 #endif
  62 
  63 
  64 /*
  65  * Condition check
  66  */
  67 static int cond_value = 0;
  68 static pthread_cond_t condtest;
  69 static pthread_mutex_t lockcond;
  70 
  71 static void *
  72 pthread_cond_wait_routine (void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74   ASSERT (pthread_mutex_lock (&lockcond) == 0);
  75   while (!cond_value)
  76     {
  77       ASSERT (pthread_cond_wait (&condtest, &lockcond) == 0);
  78     }
  79   ASSERT (pthread_mutex_unlock (&lockcond) == 0);
  80 
  81   cond_value = 2;
  82 
  83   return NULL;
  84 }
  85 
  86 static void
  87 test_pthread_cond_wait ()
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89   struct timespec remain;
  90   pthread_t thread;
  91   int ret;
  92 
  93   remain.tv_sec = 2;
  94   remain.tv_nsec = 0;
  95 
  96   cond_value = 0;
  97 
  98   ASSERT (pthread_create (&thread, NULL, pthread_cond_wait_routine, NULL) == 0);
  99   do
 100     {
 101       yield ();
 102       ret = nanosleep (&remain, &remain);
 103       ASSERT (ret >= -1);
 104     }
 105   while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0));
 106 
 107   /* signal condition */
 108   ASSERT (pthread_mutex_lock (&lockcond) == 0);
 109   cond_value = 1;
 110   ASSERT (pthread_cond_signal (&condtest) == 0);
 111   ASSERT (pthread_mutex_unlock (&lockcond) == 0);
 112 
 113   ASSERT (pthread_join (thread, NULL) == 0);
 114 
 115   if (cond_value != 2)
 116     abort ();
 117 }
 118 
 119 
 120 /*
 121  * Timed Condition check
 122  */
 123 static int cond_timeout;
 124 
 125 static void
 126 get_ts (struct timespec *ts)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128   struct timeval now;
 129 
 130   gettimeofday (&now, NULL);
 131 
 132   ts->tv_sec = now.tv_sec + 1;
 133   ts->tv_nsec = now.tv_usec * 1000;
 134 }
 135 
 136 static void *
 137 pthread_cond_timedwait_routine (void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139   int ret;
 140   struct timespec ts;
 141 
 142   ASSERT (pthread_mutex_lock (&lockcond) == 0);
 143   while (!cond_value)
 144     {
 145       get_ts (&ts);
 146       ret = pthread_cond_timedwait (&condtest, &lockcond, &ts);
 147       if (ret == ETIMEDOUT)
 148         cond_timeout = 1;
 149     }
 150   ASSERT (pthread_mutex_unlock (&lockcond) == 0);
 151 
 152   return NULL;
 153 }
 154 
 155 static void
 156 test_pthread_cond_timedwait (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158   struct timespec remain;
 159   pthread_t thread;
 160   int ret;
 161 
 162   remain.tv_sec = 2;
 163   remain.tv_nsec = 0;
 164 
 165   cond_value = cond_timeout = 0;
 166 
 167   ASSERT (pthread_create (&thread, NULL, pthread_cond_timedwait_routine, NULL)
 168           == 0);
 169   do
 170     {
 171       yield ();
 172       ret = nanosleep (&remain, &remain);
 173       ASSERT (ret >= -1);
 174     }
 175   while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0));
 176 
 177   /* signal condition */
 178   ASSERT (pthread_mutex_lock (&lockcond) == 0);
 179   cond_value = 1;
 180   ASSERT (pthread_cond_signal (&condtest) == 0);
 181   ASSERT (pthread_mutex_unlock (&lockcond) == 0);
 182 
 183   ASSERT (pthread_join (thread, NULL) == 0);
 184 
 185   if (!cond_timeout)
 186     abort ();
 187 }
 188 
 189 int
 190 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192 #if HAVE_DECL_ALARM
 193   /* Declare failure if test takes too long, by using default abort
 194      caused by SIGALRM.  */
 195   int alarm_value = 600;
 196   signal (SIGALRM, SIG_DFL);
 197   alarm (alarm_value);
 198 #endif
 199 
 200   ASSERT (pthread_cond_init (&condtest, NULL) == 0);
 201 
 202   {
 203     pthread_mutexattr_t attr;
 204 
 205     ASSERT (pthread_mutexattr_init (&attr) == 0);
 206     ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL) == 0);
 207     ASSERT (pthread_mutex_init (&lockcond, &attr) == 0);
 208     ASSERT (pthread_mutexattr_destroy (&attr) == 0);
 209   }
 210 
 211 #if DO_TEST_COND
 212   printf ("Starting test_pthread_cond_wait ..."); fflush (stdout);
 213   test_pthread_cond_wait ();
 214   printf (" OK\n"); fflush (stdout);
 215 #endif
 216 #if DO_TEST_TIMEDCOND
 217   printf ("Starting test_pthread_cond_timedwait ..."); fflush (stdout);
 218   test_pthread_cond_timedwait ();
 219   printf (" OK\n"); fflush (stdout);
 220 #endif
 221 
 222   return 0;
 223 }
 224 
 225 #else
 226 
 227 /* No multithreading available.  */
 228 
 229 #include <stdio.h>
 230 
 231 int
 232 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234   fputs ("Skipping test: multithreading not enabled\n", stderr);
 235   return 77;
 236 }
 237 
 238 #endif

/* [previous][next][first][last][top][bottom][index][help] */