usleep tests: Avoid failure due to known Cygwin 3.5.3 bug.
[gnulib.git] / tests / test-cnd.c
blob61a86a859c76dba7a3261cf6ba5ea27d006b74c6
1 /* Test of condition variables in multithreaded situations.
2 Copyright (C) 2008-2024 Free Software Foundation, Inc.
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.
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.
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/>. */
17 #include <config.h>
19 /* Which tests to perform.
20 Uncomment some of these, to verify that all tests crash if no locking
21 is enabled. */
22 #define DO_TEST_COND 1
23 #define DO_TEST_TIMEDCOND 1
26 /* Whether to help the scheduler through explicit thrd_yield().
27 Uncomment this to see if the operating system has a fair scheduler. */
28 #define EXPLICIT_YIELD 1
30 /* Whether to print debugging messages. */
31 #define ENABLE_DEBUGGING 0
33 #include <threads.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/time.h>
39 #if HAVE_DECL_ALARM
40 # include <signal.h>
41 # include <unistd.h>
42 #endif
44 #include "macros.h"
46 #if ENABLE_DEBUGGING
47 # define dbgprintf printf
48 #else
49 # define dbgprintf if (0) printf
50 #endif
52 #if EXPLICIT_YIELD
53 # define yield() thrd_yield ()
54 #else
55 # define yield()
56 #endif
60 * Condition check
62 static int cond_value = 0;
63 static cnd_t condtest;
64 static mtx_t lockcond;
66 static int
67 cnd_wait_routine (void *arg)
69 ASSERT (mtx_lock (&lockcond) == thrd_success);
70 while (!cond_value)
72 ASSERT (cnd_wait (&condtest, &lockcond) == thrd_success);
74 ASSERT (mtx_unlock (&lockcond) == thrd_success);
76 cond_value = 2;
78 return 0;
81 static void
82 test_cnd_wait ()
84 struct timespec remain;
85 thrd_t thread;
86 int ret;
88 remain.tv_sec = 2;
89 remain.tv_nsec = 0;
91 cond_value = 0;
93 ASSERT (thrd_create (&thread, cnd_wait_routine, NULL) == thrd_success);
96 yield ();
97 ret = thrd_sleep (&remain, &remain);
98 ASSERT (ret >= -1);
100 while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0));
102 /* signal condition */
103 ASSERT (mtx_lock (&lockcond) == thrd_success);
104 cond_value = 1;
105 ASSERT (cnd_signal (&condtest) == thrd_success);
106 ASSERT (mtx_unlock (&lockcond) == thrd_success);
108 ASSERT (thrd_join (thread, NULL) == thrd_success);
110 if (cond_value != 2)
111 abort ();
116 * Timed Condition check
118 static int cond_timeout;
120 static void
121 get_ts (struct timespec *ts)
123 struct timeval now;
125 gettimeofday (&now, NULL);
127 ts->tv_sec = now.tv_sec + 1;
128 ts->tv_nsec = now.tv_usec * 1000;
131 static int
132 cnd_timedwait_routine (void *arg)
134 int ret;
135 struct timespec ts;
137 ASSERT (mtx_lock (&lockcond) == thrd_success);
138 while (!cond_value)
140 get_ts (&ts);
141 ret = cnd_timedwait (&condtest, &lockcond, &ts);
142 if (ret == thrd_timedout)
143 cond_timeout = 1;
145 ASSERT (mtx_unlock (&lockcond) == thrd_success);
147 return 0;
150 static void
151 test_cnd_timedwait (void)
153 struct timespec remain;
154 thrd_t thread;
155 int ret;
157 remain.tv_sec = 2;
158 remain.tv_nsec = 0;
160 cond_value = cond_timeout = 0;
162 ASSERT (thrd_create (&thread, cnd_timedwait_routine, NULL) == thrd_success);
165 yield ();
166 ret = thrd_sleep (&remain, &remain);
167 ASSERT (ret >= -1);
169 while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0));
171 /* signal condition */
172 ASSERT (mtx_lock (&lockcond) == thrd_success);
173 cond_value = 1;
174 ASSERT (cnd_signal (&condtest) == thrd_success);
175 ASSERT (mtx_unlock (&lockcond) == thrd_success);
177 ASSERT (thrd_join (thread, NULL) == thrd_success);
179 if (!cond_timeout)
180 abort ();
184 main ()
186 #if HAVE_DECL_ALARM
187 /* Declare failure if test takes too long, by using default abort
188 caused by SIGALRM. */
189 int alarm_value = 600;
190 signal (SIGALRM, SIG_DFL);
191 alarm (alarm_value);
192 #endif
194 ASSERT (cnd_init (&condtest) == thrd_success);
195 ASSERT (mtx_init (&lockcond, mtx_plain) == thrd_success);
197 #if DO_TEST_COND
198 printf ("Starting test_cnd_wait ..."); fflush (stdout);
199 test_cnd_wait ();
200 printf (" OK\n"); fflush (stdout);
201 #endif
202 #if DO_TEST_TIMEDCOND
203 printf ("Starting test_cnd_timedwait ..."); fflush (stdout);
204 test_cnd_timedwait ();
205 printf (" OK\n"); fflush (stdout);
206 #endif
208 return test_exit_status;