maint.mk: Update system header list for #include syntax checks.
[gnulib.git] / tests / test-pthread-cond.c
blob145d4b4666b67f0743847816685c7fa6ec80e5d4
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 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
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
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
31 /* Whether to print debugging messages. */
32 #define ENABLE_DEBUGGING 0
34 #include <pthread.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/time.h>
40 #if EXPLICIT_YIELD
41 # include <sched.h>
42 #endif
44 #if HAVE_DECL_ALARM
45 # include <signal.h>
46 # include <unistd.h>
47 #endif
49 #include "macros.h"
51 #if ENABLE_DEBUGGING
52 # define dbgprintf printf
53 #else
54 # define dbgprintf if (0) printf
55 #endif
57 #if EXPLICIT_YIELD
58 # define yield() sched_yield ()
59 #else
60 # define yield()
61 #endif
65 * Condition check
67 static int cond_value = 0;
68 static pthread_cond_t condtest;
69 static pthread_mutex_t lockcond;
71 static void *
72 pthread_cond_wait_routine (void *arg)
74 ASSERT (pthread_mutex_lock (&lockcond) == 0);
75 while (!cond_value)
77 ASSERT (pthread_cond_wait (&condtest, &lockcond) == 0);
79 ASSERT (pthread_mutex_unlock (&lockcond) == 0);
81 cond_value = 2;
83 return NULL;
86 static void
87 test_pthread_cond_wait ()
89 struct timespec remain;
90 pthread_t thread;
91 int ret;
93 remain.tv_sec = 2;
94 remain.tv_nsec = 0;
96 cond_value = 0;
98 ASSERT (pthread_create (&thread, NULL, pthread_cond_wait_routine, NULL) == 0);
101 yield ();
102 ret = nanosleep (&remain, &remain);
103 ASSERT (ret >= -1);
105 while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0));
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);
113 ASSERT (pthread_join (thread, NULL) == 0);
115 if (cond_value != 2)
116 abort ();
121 * Timed Condition check
123 static int cond_timeout;
125 static void
126 get_ts (struct timespec *ts)
128 struct timeval now;
130 gettimeofday (&now, NULL);
132 ts->tv_sec = now.tv_sec + 1;
133 ts->tv_nsec = now.tv_usec * 1000;
136 static void *
137 pthread_cond_timedwait_routine (void *arg)
139 int ret;
140 struct timespec ts;
142 ASSERT (pthread_mutex_lock (&lockcond) == 0);
143 while (!cond_value)
145 get_ts (&ts);
146 ret = pthread_cond_timedwait (&condtest, &lockcond, &ts);
147 if (ret == ETIMEDOUT)
148 cond_timeout = 1;
150 ASSERT (pthread_mutex_unlock (&lockcond) == 0);
152 return NULL;
155 static void
156 test_pthread_cond_timedwait (void)
158 struct timespec remain;
159 pthread_t thread;
160 int ret;
162 remain.tv_sec = 2;
163 remain.tv_nsec = 0;
165 cond_value = cond_timeout = 0;
167 ASSERT (pthread_create (&thread, NULL, pthread_cond_timedwait_routine, NULL)
168 == 0);
171 yield ();
172 ret = nanosleep (&remain, &remain);
173 ASSERT (ret >= -1);
175 while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0));
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);
183 ASSERT (pthread_join (thread, NULL) == 0);
185 if (!cond_timeout)
186 abort ();
190 main ()
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
200 ASSERT (pthread_cond_init (&condtest, NULL) == 0);
203 pthread_mutexattr_t attr;
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);
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
222 return test_exit_status;
225 #else
227 /* No multithreading available. */
229 #include <stdio.h>
232 main ()
234 fputs ("Skipping test: multithreading not enabled\n", stderr);
235 return 77;
238 #endif