1 /* POSIX condition variables.
2 Copyright (C) 2010-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Paul Eggert, 2010, and Bruno Haible <bruno@clisp.org>, 2019. */
24 #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
25 # include "windows-cond.h"
29 # include <sys/time.h>
33 #if ((defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS) || !HAVE_PTHREAD_H
36 pthread_condattr_init (pthread_condattr_t
*attr
)
43 pthread_condattr_destroy (_GL_UNUSED pthread_condattr_t
*attr
)
50 #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
51 /* Use Windows threads. */
54 pthread_cond_init (pthread_cond_t
*cond
,
55 _GL_UNUSED
const pthread_condattr_t
*attr
)
57 return glwthread_cond_init (cond
);
61 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
63 return glwthread_cond_wait (cond
, mutex
,
64 (int (*) (void *)) pthread_mutex_lock
,
65 (int (*) (void *)) pthread_mutex_unlock
);
69 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
70 const struct timespec
*abstime
)
72 return glwthread_cond_timedwait (cond
, mutex
,
73 (int (*) (void *)) pthread_mutex_lock
,
74 (int (*) (void *)) pthread_mutex_unlock
,
79 pthread_cond_signal (pthread_cond_t
*cond
)
81 return glwthread_cond_signal (cond
);
85 pthread_cond_broadcast (pthread_cond_t
*cond
)
87 return glwthread_cond_broadcast (cond
);
91 pthread_cond_destroy (pthread_cond_t
*cond
)
93 return glwthread_cond_destroy (cond
);
97 /* Provide workarounds for POSIX threads. */
100 /* Provide a dummy implementation for single-threaded applications. */
103 pthread_cond_init (_GL_UNUSED pthread_cond_t
*cond
,
104 _GL_UNUSED
const pthread_condattr_t
*attr
)
106 /* COND is never seriously used. */
111 pthread_cond_wait (_GL_UNUSED pthread_cond_t
*cond
,
112 _GL_UNUSED pthread_mutex_t
*mutex
)
114 /* No other thread can signal this condition variable.
118 struct timespec duration
=
123 nanosleep (&duration
, NULL
);
128 pthread_cond_timedwait (_GL_UNUSED pthread_cond_t
*cond
,
129 _GL_UNUSED pthread_mutex_t
*mutex
,
130 const struct timespec
*abstime
)
132 /* No other thread can signal this condition variable.
133 Wait until ABSTIME is reached. */
136 struct timeval currtime
;
137 unsigned long remaining
;
139 gettimeofday (&currtime
, NULL
);
141 if (currtime
.tv_sec
> abstime
->tv_sec
)
145 unsigned long seconds
= abstime
->tv_sec
- currtime
.tv_sec
;
146 remaining
= seconds
* 1000000000;
147 if (remaining
/ 1000000000 != seconds
) /* overflow? */
148 remaining
= ULONG_MAX
;
152 abstime
->tv_nsec
- currtime
.tv_usec
* 1000;
153 if (nanoseconds
>= 0)
155 remaining
+= nanoseconds
;
156 if (remaining
< nanoseconds
) /* overflow? */
157 remaining
= ULONG_MAX
;
161 if (remaining
>= - nanoseconds
)
162 remaining
-= (- nanoseconds
);
171 /* Sleep up to REMAINING ns. */
172 struct timespec duration
= { .tv_sec
= remaining
/ 1000000000,
173 .tv_nsec
= remaining
% 1000000000 };
174 nanosleep (&duration
, NULL
);
179 pthread_cond_signal (_GL_UNUSED pthread_cond_t
*cond
)
181 /* No threads can currently be blocked on COND. */
186 pthread_cond_broadcast (_GL_UNUSED pthread_cond_t
*cond
)
188 /* No threads can currently be blocked on COND. */
193 pthread_cond_destroy (_GL_UNUSED pthread_cond_t
*cond
)
195 /* COND is never seriously used. */