This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v2] Semaphores: add sem_clockwait GNU extension [BZ #14717]
As defined by POSIX.1-2001 the 'abstime' timeout of sem_timedwait()
shall be based on CLOCK_REALTIME. This has the unpleasant effect that
application timeouts are affected by system clock adjustments.
The added sem_clockwait() function behaves just like sem_timedwait() but
lets the user specify the clock against which the timeout is measured.
The implementation is based on [1] which covers all functions that take an
absolute struct timespec timeout.
[1] http://austingroupbugs.net/view.php?id=1216
Signed-off-by: Jan Klötzke <jan@kloetzke.net>
---
v2: Reimplement as sem_clockwait.
One minor issue exists with this implementation: semaphore.h does not expose
the CLOCK_* constants. It is the users resposibility to include time.h for
their definition. AFAICT POSIX.1-2008 would allow semaphore.h to include
time.h but I'm reluctant to do that unconditionally.
ChangeLog | 50 +++++++++
NEWS | 5 +
htl/Makefile | 2 +-
htl/Versions | 3 +
manual/ipc.texi | 13 +++
nptl/Makefile | 5 +-
nptl/Versions | 4 +
nptl/sem_clockwait.c | 52 +++++++++
nptl/sem_timedwait.c | 2 +-
nptl/sem_wait.c | 2 +-
nptl/sem_waitcommon.c | 41 +++++--
nptl/tst-sem17.c | 119 +++++++++++++++++++++
sysdeps/htl/sem-clockwait.c | 40 +++++++
sysdeps/htl/sem-timedwait.c | 7 +-
sysdeps/htl/sem-wait.c | 5 +-
sysdeps/mach/hurd/i386/libpthread.abilist | 1 +
sysdeps/pthread/semaphore.h | 7 ++
sysdeps/unix/sysv/linux/aarch64/libpthread.abilist | 1 +
sysdeps/unix/sysv/linux/alpha/libpthread.abilist | 1 +
sysdeps/unix/sysv/linux/arm/libpthread.abilist | 1 +
sysdeps/unix/sysv/linux/hppa/libpthread.abilist | 1 +
sysdeps/unix/sysv/linux/i386/libpthread.abilist | 1 +
sysdeps/unix/sysv/linux/ia64/libpthread.abilist | 1 +
.../sysv/linux/m68k/coldfire/libpthread.abilist | 1 +
.../unix/sysv/linux/m68k/m680x0/libpthread.abilist | 1 +
.../unix/sysv/linux/microblaze/libpthread.abilist | 1 +
.../unix/sysv/linux/mips/mips32/libpthread.abilist | 1 +
.../unix/sysv/linux/mips/mips64/libpthread.abilist | 1 +
sysdeps/unix/sysv/linux/nios2/libpthread.abilist | 1 +
.../linux/powerpc/powerpc32/libpthread.abilist | 1 +
.../linux/powerpc/powerpc64/be/libpthread.abilist | 1 +
.../linux/powerpc/powerpc64/le/libpthread.abilist | 1 +
.../unix/sysv/linux/riscv/rv64/libpthread.abilist | 1 +
.../sysv/linux/s390/s390-32/libpthread.abilist | 1 +
.../sysv/linux/s390/s390-64/libpthread.abilist | 1 +
sysdeps/unix/sysv/linux/sh/libpthread.abilist | 1 +
.../sysv/linux/sparc/sparc32/libpthread.abilist | 1 +
.../sysv/linux/sparc/sparc64/libpthread.abilist | 1 +
.../unix/sysv/linux/x86_64/64/libpthread.abilist | 1 +
.../unix/sysv/linux/x86_64/x32/libpthread.abilist | 1 +
40 files changed, 362 insertions(+), 19 deletions(-)
create mode 100644 nptl/sem_clockwait.c
create mode 100644 nptl/tst-sem17.c
create mode 100644 sysdeps/htl/sem-clockwait.c
diff --git a/ChangeLog b/ChangeLog
index e419448fe6..69f2a36674 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,53 @@
+2018-12-14 Jan Klötzke <jan@kloetzke.net>
+
+ [BZ #14717]
+ * NEWS: Mention sem_clockwait.
+ * htl/Makefile (libpthread-routines): Add sem-clockwait.
+ * htl/Versions: Add sem_clockwait.
+ * manual/ipc.texi: Likewise.
+ * nptl/Makefile (libpthread-routines): Add sem_clockwait.
+ (tests): Add tst-sem17.
+ * nptl/Versions: Add sem_clockwait.
+ * nptl/sem_clockwait.c: New file.
+ * nptl/sem_timedwait.c (sem_timedwait): Add __new_sem_wait_slow
+ parameter.
+ * nptl/sem_wait.c: Add __new_sem_wait_slow parameter.
+ * nptl/sem_waitcommon.c (do_futex_wait): Add 'monotonic' parameter.
+ * nptl/tst-sem17.c: New file.
+ * sysdeps/htl/sem-clockwait.c: New file.
+ * sysdeps/htl/sem-timedwait.c (__sem_timedwait_internal): Add
+ 'clock_id' parameter.
+ (__sem_timedwait): Pass CLOCK_REALTIME to __sem_timedwait_internal.
+ * sysdeps/htl/sem-wait.c (__sem_wait): Likewise.
+ * sysdeps/mach/hurd/i386/libpthread.abilist: Add sem_clockwait.
+ * sysdeps/pthread/semaphore.h: Likewise.
+ * sysdeps/unix/sysv/linux/aarch64/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/alpha/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/arm/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/hppa/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/i386/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/ia64/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/microblaze/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/nios2/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist:
+ Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist:
+ Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist:
+ Likewise.
+ * sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/sh/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist: Likewise.
+
2018-12-13 Joseph Myers <joseph@codesourcery.com>
* sysdeps/mach/hurd/i386/init-first.c (_hurd_stack_setup): Do not
diff --git a/NEWS b/NEWS
index ae80818df4..1d8c78cf57 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,11 @@ Major new features:
incosistent mutex state after fork call in multithread environment.
In both popen and system there is no direct access to user-defined mutexes.
+* The sem_clockwait function has been added. It complements sem_timedwait by
+ allowing to select the clock against which the absolute timeout is measured.
+ Using CLOCK_MONOTONIC enables an application to wait without being affected
+ by system clock adjustments.
+
Deprecated and removed features, and other changes affecting compatibility:
* The glibc.tune tunable namespace has been renamed to glibc.cpu and the
diff --git a/htl/Makefile b/htl/Makefile
index 11c21df4d3..cebf3cca0e 100644
--- a/htl/Makefile
+++ b/htl/Makefile
@@ -128,7 +128,7 @@ libpthread-routines := pt-attr pt-attr-destroy pt-attr-getdetachstate \
pt-getschedparam pt-setschedparam pt-setschedprio \
pt-yield \
\
- sem-close sem-destroy sem-getvalue sem-init sem-open \
+ sem-clockwait sem-close sem-destroy sem-getvalue sem-init sem-open \
sem-post sem-timedwait sem-trywait sem-unlink \
sem-wait \
\
diff --git a/htl/Versions b/htl/Versions
index c5a616da10..39aced3245 100644
--- a/htl/Versions
+++ b/htl/Versions
@@ -141,6 +141,9 @@ libpthread {
pthread_hurd_cond_wait_np;
pthread_hurd_cond_timedwait_np;
}
+ GLIBC_2.29 {
+ sem_clockwait;
+ }
GLIBC_PRIVATE {
__shm_directory;
__pthread_threads;
diff --git a/manual/ipc.texi b/manual/ipc.texi
index 081b98fe29..05e2e216bd 100644
--- a/manual/ipc.texi
+++ b/manual/ipc.texi
@@ -100,6 +100,19 @@ by @theglibc{}.
@c Same safety issues as sem_wait.
@end deftypefun
+@deftypefun int sem_clockwait (sem_t *@var{sem}, clockid_t @var{clock_id}, const struct timespec *@var{abstime});
+@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
+@c Same safety issues as sem_wait.
+This function is similar to @code{sem_timedwait}, but allows the calling thread
+to select the clock against which the absolute timeout is measured. Currently
+@code{CLOCK_MONOTONIC} and @code{CLOCK_REALTIME} are supported. Invoking this
+function with @code{CLOCK_REALTIME} has the identical behaviour as
+@code{sem_timedwait}. By using @code{CLOCK_MONOTONIC} the timeout will be
+unaffected by changes to the system real time clock.
+
+This function is a GNU extension.
+@end deftypefun
+
@deftypefun int sem_trywait (sem_t *@var{sem});
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@c All atomic operations are safe in all contexts.
diff --git a/nptl/Makefile b/nptl/Makefile
index b01f2b0626..76f850d780 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -114,7 +114,7 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \
sem_init sem_destroy \
sem_open sem_close sem_unlink \
sem_getvalue \
- sem_wait sem_timedwait sem_post \
+ sem_wait sem_clockwait sem_timedwait sem_post \
cleanup cleanup_defer cleanup_compat \
cleanup_defer_compat unwind \
pt-longjmp pt-cleanup\
@@ -193,6 +193,7 @@ CFLAGS-pthread_once.c += $(uses-callbacks) -fexceptions \
-fasynchronous-unwind-tables
CFLAGS-pthread_cond_wait.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-sem_wait.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-sem_clockwait.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-sem_timedwait.c += -fexceptions -fasynchronous-unwind-tables
# These are the function wrappers we have to duplicate here.
@@ -263,7 +264,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
tst-key1 tst-key2 tst-key3 tst-key4 \
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
tst-sem8 tst-sem9 tst-sem10 tst-sem14 \
- tst-sem15 tst-sem16 \
+ tst-sem15 tst-sem16 tst-sem17 \
tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
tst-align tst-align3 \
tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
diff --git a/nptl/Versions b/nptl/Versions
index e7f691da7a..4d4a79da55 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -277,6 +277,10 @@ libpthread {
cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
}
+ GLIBC_2.29 {
+ sem_clockwait;
+ }
+
GLIBC_PRIVATE {
__pthread_initialize_minimal;
__pthread_clock_gettime; __pthread_clock_settime;
diff --git a/nptl/sem_clockwait.c b/nptl/sem_clockwait.c
new file mode 100644
index 0000000000..f0d9487c82
--- /dev/null
+++ b/nptl/sem_clockwait.c
@@ -0,0 +1,52 @@
+/* sem_clockwait -- wait on a semaphore with timeout against specific clock.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "sem_waitcommon.c"
+
+/* This is in a separate file because because sem_clockwait is only
+ provided if __USE_GNU is defined. */
+int
+sem_clockwait (sem_t *sem, clockid_t clock_id, const struct timespec *abstime)
+{
+ if (__glibc_unlikely (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (__glibc_unlikely (clock_id != CLOCK_MONOTONIC
+ && clock_id != CLOCK_REALTIME))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ /* If we do not support waiting using CLOCK_MONOTONIC, return an error. */
+ if (clock_id == CLOCK_MONOTONIC
+ && !futex_supports_exact_relative_timeouts())
+ return ENOTSUP;
+
+ /* Check sem_wait.c for a more detailed explanation why it is required. */
+ __pthread_testcancel ();
+
+ if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
+ return 0;
+ else
+ return __new_sem_wait_slow((struct new_sem *) sem, abstime,
+ clock_id == CLOCK_MONOTONIC);
+}
diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c
index 8886ea2fb3..dec6882f41 100644
--- a/nptl/sem_timedwait.c
+++ b/nptl/sem_timedwait.c
@@ -36,5 +36,5 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
return 0;
else
- return __new_sem_wait_slow((struct new_sem *) sem, abstime);
+ return __new_sem_wait_slow((struct new_sem *) sem, abstime, 0);
}
diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
index e7d910613f..de29868fdb 100644
--- a/nptl/sem_wait.c
+++ b/nptl/sem_wait.c
@@ -39,7 +39,7 @@ __new_sem_wait (sem_t *sem)
if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
return 0;
else
- return __new_sem_wait_slow((struct new_sem *) sem, NULL);
+ return __new_sem_wait_slow((struct new_sem *) sem, NULL, 0);
}
versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
diff --git a/nptl/sem_waitcommon.c b/nptl/sem_waitcommon.c
index 30984be2d0..7012c3fdf1 100644
--- a/nptl/sem_waitcommon.c
+++ b/nptl/sem_waitcommon.c
@@ -103,19 +103,42 @@ __sem_wait_cleanup (void *arg)
users don't seem to need it. */
static int
__attribute__ ((noinline))
-do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
+do_futex_wait (struct new_sem *sem, const struct timespec *abstime, int monotonic)
{
int err;
+ unsigned int * futex_word;
#if __HAVE_64B_ATOMICS
- err = futex_abstimed_wait_cancelable (
- (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0, abstime,
- sem->private);
+ futex_word = (unsigned int *) &sem->data + SEM_VALUE_OFFSET;
#else
- err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK,
- abstime, sem->private);
+ futex_word = &sem->value;
#endif
+ if (monotonic)
+ {
+ /* CLOCK_MONOTONIC is requested. */
+ struct timespec rt;
+ if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
+ __libc_fatal ("clock_gettime does not support "
+ "CLOCK_MONOTONIC\n");
+ /* Convert the absolute timeout value to a relative
+ timeout. */
+ rt.tv_sec = abstime->tv_sec - rt.tv_sec;
+ rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
+ if (rt.tv_nsec < 0)
+ {
+ rt.tv_nsec += 1000000000;
+ --rt.tv_sec;
+ }
+ /* Did we already time out? */
+ if (__glibc_unlikely (rt.tv_sec < 0))
+ err = ETIMEDOUT;
+ else
+ err = futex_reltimed_wait_cancelable (futex_word, 0, &rt, sem->private);
+ }
+ else
+ err = futex_abstimed_wait_cancelable (futex_word, 0, abstime, sem->private);
+
return err;
}
@@ -160,7 +183,7 @@ __new_sem_wait_fast (struct new_sem *sem, int definitive_result)
/* Slow path that blocks. */
static int
__attribute__ ((noinline))
-__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
+__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime, int monotonic)
{
int err = 0;
@@ -178,7 +201,7 @@ __new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
/* If there is no token available, sleep until there is. */
if ((d & SEM_VALUE_MASK) == 0)
{
- err = do_futex_wait (sem, abstime);
+ err = do_futex_wait (sem, abstime, monotonic);
/* A futex return value of 0 or EAGAIN is due to a real or spurious
wake-up, or due to a change in the number of tokens. We retry in
these cases.
@@ -279,7 +302,7 @@ __new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
if ((v >> SEM_VALUE_SHIFT) == 0)
{
/* See __HAVE_64B_ATOMICS variant. */
- err = do_futex_wait(sem, abstime);
+ err = do_futex_wait(sem, abstime, monotonic);
if (err == ETIMEDOUT || err == EINTR)
{
__set_errno (err);
diff --git a/nptl/tst-sem17.c b/nptl/tst-sem17.c
new file mode 100644
index 0000000000..12561b8911
--- /dev/null
+++ b/nptl/tst-sem17.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define EXPECT_OK(exp) \
+ do { \
+ int ret = (exp); \
+ if (ret < 0) \
+ { \
+ printf ("%s:%d: call failed: %s\n", __FILE__, __LINE__, \
+ strerror(errno)); \
+ return 1; \
+ } \
+ } while (0)
+
+#define SEM_CLOCKWAIT_EXPECT_FAIL(err, clk) \
+ do { \
+ errno = 0; \
+ if (sem_clockwait (&s, (clk), &ts) >= 0) \
+ { \
+ printf ("%s:%d: sem_clockwait did not fail\n", __FILE__, __LINE__); \
+ return 1; \
+ } \
+ if (errno != (err)) \
+ { \
+ printf("%s:%d: sem_clockwait did not fail with %d but %d\n", \
+ __FILE__, __LINE__, (err), errno); \
+ return 1; \
+ } \
+ } while (0)
+
+static int
+do_test (void)
+{
+ sem_t s;
+ int val;
+
+ if (sem_init (&s, 0, 2) != 0)
+ {
+ puts ("sem_init failed");
+ return 1;
+ }
+
+ struct timespec ts = { 0, 0 };
+
+ /* CLOCK_REALTIME accepted */
+ EXPECT_OK(sem_clockwait(&s, CLOCK_REALTIME, &ts));
+
+ /* CLOCK_MONOTONIC accepted */
+ EXPECT_OK(sem_clockwait(&s, CLOCK_MONOTONIC, &ts));
+
+ /* invalid clock fails */
+ SEM_CLOCKWAIT_EXPECT_FAIL(EINVAL, 42);
+
+ /* semaphore value ought to be zero by now */
+ EXPECT_OK(sem_getvalue(&s, &val));
+ if (val != 0)
+ {
+ puts("semphore value not zero");
+ return 1;
+ }
+
+ /* invalid tv_nsec */
+ ts.tv_nsec = 1000000001;
+ SEM_CLOCKWAIT_EXPECT_FAIL(EINVAL, CLOCK_MONOTONIC);
+ ts.tv_nsec = -1;
+ SEM_CLOCKWAIT_EXPECT_FAIL(EINVAL, CLOCK_MONOTONIC);
+
+ /* ancient tv_sec */
+ ts.tv_sec = -2;
+ ts.tv_nsec = 0;
+ SEM_CLOCKWAIT_EXPECT_FAIL(ETIMEDOUT, CLOCK_MONOTONIC);
+
+ /* wait 100ms with CLOCK_MONOTONIC */
+ EXPECT_OK(clock_gettime(CLOCK_MONOTONIC, &ts));
+ ts.tv_nsec += 100000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ++ts.tv_sec;
+ ts.tv_nsec -= 1000000000;
+ }
+
+ SEM_CLOCKWAIT_EXPECT_FAIL(ETIMEDOUT, CLOCK_MONOTONIC);
+
+ struct timespec ts2;
+ EXPECT_OK(clock_gettime(CLOCK_MONOTONIC, &ts2));
+
+ if (ts2.tv_sec < ts.tv_sec
+ || (ts2.tv_sec == ts.tv_sec && ts2.tv_nsec < ts.tv_nsec))
+ {
+ puts ("timeout too short");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/htl/sem-clockwait.c b/sysdeps/htl/sem-clockwait.c
new file mode 100644
index 0000000000..68eae9a5ab
--- /dev/null
+++ b/sysdeps/htl/sem-clockwait.c
@@ -0,0 +1,40 @@
+/* Wait on a semaphore with timeout on certain clock. Generic version.
+ Copyright (C) 2005-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <semaphore.h>
+#include <pt-internal.h>
+
+extern int __sem_timedwait_internal (sem_t *restrict sem,
+ const struct timespec *restrict timeout,
+ clockid_t clock_id);
+
+int
+__sem_clockwait (sem_t *restrict sem, clockid_t clock_id,
+ const struct timespec *restrict timeout)
+{
+ if (__glibc_unlikely (clock_id != CLOCK_MONOTONIC
+ && clock_id != CLOCK_REALTIME))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ return __sem_timedwait_internal (sem, timeout, clock_id);
+}
+
+strong_alias (__sem_clockwait, sem_clockwait);
diff --git a/sysdeps/htl/sem-timedwait.c b/sysdeps/htl/sem-timedwait.c
index 803a5c04f4..a7a057faca 100644
--- a/sysdeps/htl/sem-timedwait.c
+++ b/sysdeps/htl/sem-timedwait.c
@@ -24,7 +24,8 @@
int
__sem_timedwait_internal (sem_t *restrict sem,
- const struct timespec *restrict timeout)
+ const struct timespec *restrict timeout,
+ clockid_t clock_id)
{
error_t err;
int drain;
@@ -53,7 +54,7 @@ __sem_timedwait_internal (sem_t *restrict sem,
/* Block the thread. */
if (timeout != NULL)
- err = __pthread_timedblock (self, timeout, CLOCK_REALTIME);
+ err = __pthread_timedblock (self, timeout, clock_id);
else
{
err = 0;
@@ -92,7 +93,7 @@ __sem_timedwait_internal (sem_t *restrict sem,
int
__sem_timedwait (sem_t *restrict sem, const struct timespec *restrict timeout)
{
- return __sem_timedwait_internal (sem, timeout);
+ return __sem_timedwait_internal (sem, timeout, CLOCK_REALTIME);
}
weak_alias (__sem_timedwait, sem_timedwait);
diff --git a/sysdeps/htl/sem-wait.c b/sysdeps/htl/sem-wait.c
index 9fcd22781b..484c43dc13 100644
--- a/sysdeps/htl/sem-wait.c
+++ b/sysdeps/htl/sem-wait.c
@@ -20,12 +20,13 @@
#include <pt-internal.h>
extern int __sem_timedwait_internal (sem_t *restrict sem,
- const struct timespec *restrict timeout);
+ const struct timespec *restrict timeout,
+ clockid_t clock_id);
int
__sem_wait (sem_t *sem)
{
- return __sem_timedwait_internal (sem, 0);
+ return __sem_timedwait_internal (sem, 0, CLOCK_REALTIME);
}
strong_alias (__sem_wait, sem_wait);
diff --git a/sysdeps/mach/hurd/i386/libpthread.abilist b/sysdeps/mach/hurd/i386/libpthread.abilist
index 4c7d06d073..6085a7ff9c 100644
--- a/sysdeps/mach/hurd/i386/libpthread.abilist
+++ b/sysdeps/mach/hurd/i386/libpthread.abilist
@@ -147,3 +147,4 @@ GLIBC_2.2.6 _IO_ftrylockfile F
GLIBC_2.2.6 _IO_funlockfile F
GLIBC_2.21 pthread_hurd_cond_timedwait_np F
GLIBC_2.21 pthread_hurd_cond_wait_np F
+GLIBC_2.29 sem_clockwait F
diff --git a/sysdeps/pthread/semaphore.h b/sysdeps/pthread/semaphore.h
index ff672ebd24..94417d7d95 100644
--- a/sysdeps/pthread/semaphore.h
+++ b/sysdeps/pthread/semaphore.h
@@ -61,6 +61,13 @@ extern int sem_timedwait (sem_t *__restrict __sem,
const struct timespec *__restrict __abstime);
#endif
+#ifdef __USE_GNU
+/* Similar to `sem_timedwait' but with configurable clock. */
+extern int sem_clockwait (sem_t *__restrict __sem,
+ clockid_t __clock_id,
+ const struct timespec *__restrict __abstime);
+#endif
+
/* Test whether SEM is posted. */
extern int sem_trywait (sem_t *__sem) __THROWNL;
diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
index 9a9e4cee85..1f6e81e572 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
@@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
index b413007ccb..ff915631b6 100644
--- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
index af82a4c632..c15acc206c 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.4 _IO_flockfile F
GLIBC_2.4 _IO_ftrylockfile F
GLIBC_2.4 _IO_funlockfile F
diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
index bcba07f575..c11b16802f 100644
--- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
@@ -219,6 +219,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
index bece86d246..3adc3fd963 100644
--- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
index ccc9449826..57d1fe0206 100644
--- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
@@ -219,6 +219,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
index af82a4c632..c15acc206c 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
@@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.4 _IO_flockfile F
GLIBC_2.4 _IO_ftrylockfile F
GLIBC_2.4 _IO_funlockfile F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
index bece86d246..3adc3fd963 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
index 5067375d23..60d75df085 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
@@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
index 02144967c6..1c26f72767 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
index 02144967c6..1c26f72767 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
index 78cac2ae27..5ded824c40 100644
--- a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
@@ -241,3 +241,4 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
index 09e8447b06..e65bfd94f3 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
index 8300958d47..5ac044fad7 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
@@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3 _IO_flockfile F
GLIBC_2.3 _IO_ftrylockfile F
GLIBC_2.3 _IO_funlockfile F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
index 9a9e4cee85..1f6e81e572 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
@@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
index c370fda73d..077574fea6 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
@@ -235,3 +235,4 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
index d05468f3b2..919ae6dc42 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
@@ -229,6 +229,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
index e8161aa747..4178c015cf 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
@@ -221,6 +221,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
index bcba07f575..c11b16802f 100644
--- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
@@ -219,6 +219,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
index b413007ccb..ff915631b6 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
index ccc9449826..57d1fe0206 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
@@ -219,6 +219,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
index 931c8277a8..b7f0ee5045 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
@@ -219,6 +219,7 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
GLIBC_2.3.2 pthread_cond_broadcast F
GLIBC_2.3.2 pthread_cond_destroy F
GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
index c09c9b015a..356412e100 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
@@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
GLIBC_2.28 tss_delete F
GLIBC_2.28 tss_get F
GLIBC_2.28 tss_set F
+GLIBC_2.29 sem_clockwait F
--
2.11.0