@@ -1,3 +1,51 @@
+2018-12-13 Jan Klötzke <jan@kloetzke.net>
+
+ [BZ #14717]
+ * htl/Makefile (libpthread-routines): Add sem-timedwait-monotonic.
+ * htl/Versions: Add sem_timedwait_monotonic.
+ * manual/ipc.texi: Likewise.
+ * nptl/Makefile: Likewise.
+ * nptl/Versions: Likewise.
+ * nptl/sem_timedwait.c (sem_timedwait): Add __new_sem_wait_slow
+ parameter.
+ * nptl/sem_timedwait_monotonic.c: New file.
+ * nptl/sem_wait.c: Add __new_sem_wait_slow parameter.
+ * nptl/sem_waitcommon.c (do_futex_wait): Add 'monotonic' parameter.
+ * sysdeps/htl/sem-timedwait-monotonic.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_timedwait_monotonic.
+ * 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/libpthread-le.abilist:
+ Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/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-12 Joseph Myers <joseph@codesourcery.com>
* sysdeps/x86/fpu/bits/mathinline.h (hypot): Remove inline
@@ -129,8 +129,8 @@ libpthread-routines := pt-attr pt-attr-destroy pt-attr-getdetachstate \
pt-yield \
\
sem-close sem-destroy sem-getvalue sem-init sem-open \
- sem-post sem-timedwait sem-trywait sem-unlink \
- sem-wait \
+ sem-post sem-timedwait sem-timedwait-monotonic sem-trywait \
+ sem-unlink sem-wait \
\
shm-directory \
\
@@ -141,6 +141,9 @@ libpthread {
pthread_hurd_cond_wait_np;
pthread_hurd_cond_timedwait_np;
}
+ GLIBC_2.29 {
+ sem_timedwait_monotonic;
+ }
GLIBC_PRIVATE {
__shm_directory;
__pthread_threads;
@@ -100,6 +100,17 @@ by @theglibc{}.
@c Same safety issues as sem_wait.
@end deftypefun
+@deftypefun int sem_timedwait_monotonic (sem_t *@var{sem}, 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 uses
+@code{CLOCK_MONOTONIC} instead of @code{CLOCK_REALTIME} for the absolute
+timeout. This makes the timeout 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.
@@ -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_timedwait sem_timedwait_monotonic sem_post \
cleanup cleanup_defer cleanup_compat \
cleanup_defer_compat unwind \
pt-longjmp pt-cleanup\
@@ -194,6 +194,7 @@ CFLAGS-pthread_once.c += $(uses-callbacks) -fexceptions \
CFLAGS-pthread_cond_wait.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-sem_wait.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-sem_timedwait.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-sem_timedwait_monotonic.c += -fexceptions -fasynchronous-unwind-tables
# These are the function wrappers we have to duplicate here.
CFLAGS-fcntl.c += -fexceptions -fasynchronous-unwind-tables
@@ -277,6 +277,10 @@ libpthread {
cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
}
+ GLIBC_2.29 {
+ sem_timedwait_monotonic;
+ }
+
GLIBC_PRIVATE {
__pthread_initialize_minimal;
__pthread_clock_gettime; __pthread_clock_settime;
@@ -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);
}
new file mode 100644
@@ -0,0 +1,40 @@
+/* sem_timedwait_monotonic -- wait on a semaphore with timeout against CLOCK_MONOTONIC.
+ 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_timedwait_monotonic is only
+ provided if __USE_GNU is defined. */
+int
+sem_timedwait_monotonic (sem_t *sem, const struct timespec *abstime)
+{
+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ /* 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, 1);
+}
+
@@ -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);
@@ -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);
new file mode 100644
@@ -0,0 +1,32 @@
+/* Wait on a semaphore. 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_timedwait_monotonic (sem_t *restrict sem, const struct timespec *restrict timeout)
+{
+ return __sem_timedwait_internal (sem, timeout, CLOCK_MONOTONIC);
+}
+
+strong_alias (__sem_timedwait_monotonic, sem_timedwait_monotonic);
@@ -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);
@@ -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);
@@ -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_timedwait_monotonic F
@@ -61,6 +61,12 @@ extern int sem_timedwait (sem_t *__restrict __sem,
const struct timespec *__restrict __abstime);
#endif
+#ifdef __USE_GNU
+/* Similar to `sem_timedwait' but uses CLOCK_MONOTONIC. */
+extern int sem_timedwait_monotonic (sem_t *__restrict __sem,
+ const struct timespec *__restrict __abstime);
+#endif
+
/* Test whether SEM is posted. */
extern int sem_trywait (sem_t *__sem) __THROWNL;
@@ -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_timedwait_monotonic F
@@ -264,3 +264,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -243,3 +243,4 @@ GLIBC_2.4 vfork F
GLIBC_2.4 wait F
GLIBC_2.4 waitpid F
GLIBC_2.4 write F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -254,3 +254,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -262,3 +262,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -256,3 +256,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -243,3 +243,4 @@ GLIBC_2.4 vfork F
GLIBC_2.4 wait F
GLIBC_2.4 waitpid F
GLIBC_2.4 write F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -262,3 +262,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -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_timedwait_monotonic F
@@ -264,3 +264,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -264,3 +264,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -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_timedwait_monotonic F
@@ -266,3 +266,4 @@ GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
GLIBC_2.6 pthread_attr_setstack F
GLIBC_2.6 pthread_attr_setstacksize F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -257,3 +257,4 @@ GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
GLIBC_2.6 pthread_attr_setstack F
GLIBC_2.6 pthread_attr_setstacksize F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -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_timedwait_monotonic F
@@ -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_timedwait_monotonic F
@@ -264,3 +264,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -256,3 +256,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -254,3 +254,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -264,3 +264,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -256,3 +256,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -254,3 +254,4 @@ GLIBC_2.4 pthread_mutexattr_getrobust_np F
GLIBC_2.4 pthread_mutexattr_setprioceiling F
GLIBC_2.4 pthread_mutexattr_setprotocol F
GLIBC_2.4 pthread_mutexattr_setrobust_np F
+GLIBC_2.29 sem_timedwait_monotonic F
@@ -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_timedwait_monotonic F