!134 [sync] PR-132: nptl: Add POSIX-proposed pthread_cond_clockwait
From: @openeuler-sync-bot Reviewed-by: @liqingqing_1229 Signed-off-by: @liqingqing_1229
This commit is contained in:
commit
9770e71816
@ -0,0 +1,390 @@
|
||||
From 99d01ffcc386d1bfb681fb0684fcf6a6a996beb3 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Crowe <mac@mcrowe.com>
|
||||
Date: Fri, 21 Jun 2019 14:53:40 +0000
|
||||
Subject: [PATCH] nptl: Add clockid parameter to futex timed wait calls
|
||||
|
||||
In preparation for adding POSIX clockwait variants of timedwait functions,
|
||||
add a clockid_t parameter to futex_abstimed_wait functions and pass
|
||||
CLOCK_REALTIME from all callers for the time being.
|
||||
|
||||
Replace lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset
|
||||
which takes a clockid_t parameter rather than the magic clockbit.
|
||||
|
||||
* sysdeps/nptl/lowlevellock-futex.h,
|
||||
sysdeps/unix/sysv/linux/lowlevellock-futex.h: Replace
|
||||
lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset that
|
||||
takes a clockid rather than a special clockbit.
|
||||
* sysdeps/nptl/lowlevellock-futex.h: Add
|
||||
lll_futex_supported_clockid so that client functions can check
|
||||
whether their clockid parameter is valid even if they don't
|
||||
ultimately end up calling lll_futex_clock_wait_bitset.
|
||||
* sysdeps/nptl/futex-internal.h,
|
||||
sysdeps/unix/sysv/linux/futex-internal.h
|
||||
(futex_abstimed_wait, futex_abstimed_wait_cancelable): Add
|
||||
clockid_t parameter to indicate which clock the absolute time
|
||||
passed should be measured against. Pass that clockid onto
|
||||
lll_futex_clock_wait_bitset. Add invalid clock as reason for
|
||||
returning -EINVAL.
|
||||
* sysdeps/nptl/futex-internal.h,
|
||||
sysdeps/unix/sysv/linux/futex-internal.h: Introduce
|
||||
futex_abstimed_supported_clockid so that client functions can check
|
||||
whether their clockid parameter is valid even if they don't
|
||||
ultimately end up calling futex_abstimed_wait.
|
||||
* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Remove
|
||||
code to calculate relative timeout for
|
||||
__PTHREAD_COND_CLOCK_MONOTONIC_MASK and just pass CLOCK_MONOTONIC
|
||||
or CLOCK_REALTIME as required to futex_abstimed_wait_cancelable.
|
||||
* nptl/pthread_rwlock_common (__pthread_rwlock_rdlock_full)
|
||||
(__pthread_wrlock_full), nptl/sem_waitcommon (do_futex_wait): Pass
|
||||
additional CLOCK_REALTIME to futex_abstimed_wait_cancelable.
|
||||
* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock):
|
||||
Switch to lll_futex_clock_wait_bitset and pass CLOCK_REALTIME
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
---
|
||||
ChangeLog | 33 ++++++++++++++++++++
|
||||
nptl/pthread_cond_wait.c | 32 ++++---------------
|
||||
nptl/pthread_mutex_timedlock.c | 4 +--
|
||||
nptl/pthread_rwlock_common.c | 8 ++---
|
||||
nptl/sem_waitcommon.c | 6 ++--
|
||||
sysdeps/nptl/futex-internal.h | 9 +++++-
|
||||
sysdeps/nptl/lowlevellock-futex.h | 14 ++++++---
|
||||
sysdeps/unix/sysv/linux/futex-internal.h | 24 ++++++++++----
|
||||
sysdeps/unix/sysv/linux/lowlevellock-futex.h | 32 +++++++++++++++----
|
||||
9 files changed, 110 insertions(+), 52 deletions(-)
|
||||
|
||||
diff --git a/ChangeLog b/ChangeLog
|
||||
index 24a97096..1f8cf24f 100644
|
||||
--- a/ChangeLog
|
||||
+++ b/ChangeLog
|
||||
@@ -1,3 +1,36 @@
|
||||
+2019-07-12 Mike Crowe <mac@mcrowe.com>
|
||||
+
|
||||
+ nptl: Add clockid parameter to futex timed wait calls
|
||||
+ * sysdeps/nptl/lowlevellock-futex.h,
|
||||
+ sysdeps/unix/sysv/linux/lowlevellock-futex.h: Replace
|
||||
+ lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset that
|
||||
+ takes a clockid rather than a special clockbit.
|
||||
+ * sysdeps/nptl/lowlevellock-futex.h: Add
|
||||
+ lll_futex_supported_clockid so that client functions can check
|
||||
+ whether their clockid parameter is valid even if they don't
|
||||
+ ultimately end up calling lll_futex_clock_wait_bitset.
|
||||
+ * sysdeps/nptl/futex-internal.h,
|
||||
+ sysdeps/unix/sysv/linux/futex-internal.h
|
||||
+ (futex_abstimed_wait, futex_abstimed_wait_cancelable): Add
|
||||
+ clockid_t parameter to indicate which clock the absolute time
|
||||
+ passed should be measured against. Pass that clockid onto
|
||||
+ lll_futex_clock_wait_bitset. Add invalid clock as reason for
|
||||
+ returning -EINVAL.
|
||||
+ * sysdeps/nptl/futex-internal.h,
|
||||
+ sysdeps/unix/sysv/linux/futex-internal.h: Introduce
|
||||
+ futex_abstimed_supported_clockid so that client functions can check
|
||||
+ whether their clockid parameter is valid even if they don't
|
||||
+ ultimately end up calling futex_abstimed_wait.
|
||||
+ * nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Remove
|
||||
+ code to calculate relative timeout for
|
||||
+ __PTHREAD_COND_CLOCK_MONOTONIC_MASK and just pass CLOCK_MONOTONIC
|
||||
+ or CLOCK_REALTIME as required to futex_abstimed_wait_cancelable.
|
||||
+ * nptl/pthread_rwlock_common (__pthread_rwlock_rdlock_full)
|
||||
+ (__pthread_wrlock_full), nptl/sem_waitcommon (do_futex_wait): Pass
|
||||
+ additional CLOCK_REALTIME to futex_abstimed_wait_cancelable.
|
||||
+ * nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock):
|
||||
+ Switch to lll_futex_clock_wait_bitset and pass CLOCK_REALTIME
|
||||
+
|
||||
2019-04-23 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
[BZ #18035]
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 3e110541..3294fa3a 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -509,35 +509,15 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
values despite them being valid. */
|
||||
if (__glibc_unlikely (abstime->tv_sec < 0))
|
||||
err = ETIMEDOUT;
|
||||
-
|
||||
- else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
|
||||
- {
|
||||
- /* CLOCK_MONOTONIC is requested. */
|
||||
- struct timespec rt;
|
||||
- if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
|
||||
- __libc_fatal ("clock_gettime does not support "
|
||||
- "CLOCK_MONOTONIC");
|
||||
- /* 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
|
||||
- (cond->__data.__g_signals + g, 0, &rt, private);
|
||||
- }
|
||||
else
|
||||
{
|
||||
- /* Use CLOCK_REALTIME. */
|
||||
+ const clockid_t clockid =
|
||||
+ ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
|
||||
+ CLOCK_MONOTONIC : CLOCK_REALTIME;
|
||||
+
|
||||
err = futex_abstimed_wait_cancelable
|
||||
- (cond->__data.__g_signals + g, 0, abstime, private);
|
||||
+ (cond->__data.__g_signals + g, 0, clockid, abstime,
|
||||
+ private);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
|
||||
index 888c12fe..46fcf8d8 100644
|
||||
--- a/nptl/pthread_mutex_timedlock.c
|
||||
+++ b/nptl/pthread_mutex_timedlock.c
|
||||
@@ -292,8 +292,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
|
||||
lll_futex_timed_wait (&mutex->__data.__lock, oldval,
|
||||
&rt, PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
|
||||
#else
|
||||
- int err = lll_futex_timed_wait_bitset (&mutex->__data.__lock,
|
||||
- oldval, abstime, FUTEX_CLOCK_REALTIME,
|
||||
+ int err = lll_futex_clock_wait_bitset (&mutex->__data.__lock,
|
||||
+ oldval, CLOCK_REALTIME, abstime,
|
||||
PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
|
||||
/* The futex call timed out. */
|
||||
if (err == -ETIMEDOUT)
|
||||
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
|
||||
index 597a8532..1918f7c9 100644
|
||||
--- a/nptl/pthread_rwlock_common.c
|
||||
+++ b/nptl/pthread_rwlock_common.c
|
||||
@@ -319,7 +319,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
{
|
||||
int private = __pthread_rwlock_get_private (rwlock);
|
||||
int err = futex_abstimed_wait (&rwlock->__data.__readers,
|
||||
- r, abstime, private);
|
||||
+ r, CLOCK_REALTIME, abstime, private);
|
||||
/* We ignore EAGAIN and EINTR. On time-outs, we can just
|
||||
return because we don't need to clean up anything. */
|
||||
if (err == ETIMEDOUT)
|
||||
@@ -444,7 +444,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
&wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
continue;
|
||||
int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
|
||||
- 1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
|
||||
+ 1 | PTHREAD_RWLOCK_FUTEX_USED, CLOCK_REALTIME, abstime, private);
|
||||
if (err == ETIMEDOUT)
|
||||
{
|
||||
/* If we timed out, we need to unregister. If no read phase
|
||||
@@ -704,7 +704,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
in this group. */
|
||||
may_share_futex_used_flag = true;
|
||||
int err = futex_abstimed_wait (&rwlock->__data.__writers_futex,
|
||||
- 1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
|
||||
+ 1 | PTHREAD_RWLOCK_FUTEX_USED, CLOCK_REALTIME, abstime, private);
|
||||
if (err == ETIMEDOUT)
|
||||
{
|
||||
if (prefer_writer)
|
||||
@@ -801,7 +801,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
PTHREAD_RWLOCK_FUTEX_USED))
|
||||
continue;
|
||||
int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
|
||||
- PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
|
||||
+ PTHREAD_RWLOCK_FUTEX_USED, CLOCK_REALTIME, abstime, private);
|
||||
if (err == ETIMEDOUT)
|
||||
{
|
||||
if (rwlock->__data.__flags
|
||||
diff --git a/nptl/sem_waitcommon.c b/nptl/sem_waitcommon.c
|
||||
index 30984be2..1811a32c 100644
|
||||
--- a/nptl/sem_waitcommon.c
|
||||
+++ b/nptl/sem_waitcommon.c
|
||||
@@ -109,11 +109,13 @@ do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
|
||||
|
||||
#if __HAVE_64B_ATOMICS
|
||||
err = futex_abstimed_wait_cancelable (
|
||||
- (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0, abstime,
|
||||
+ (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0,
|
||||
+ CLOCK_REALTIME, abstime,
|
||||
sem->private);
|
||||
#else
|
||||
err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK,
|
||||
- abstime, sem->private);
|
||||
+ CLOCK_REALTIME, abstime,
|
||||
+ sem->private);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
diff --git a/sysdeps/nptl/futex-internal.h b/sysdeps/nptl/futex-internal.h
|
||||
index 1a562478..353fdfb9 100644
|
||||
--- a/sysdeps/nptl/futex-internal.h
|
||||
+++ b/sysdeps/nptl/futex-internal.h
|
||||
@@ -49,7 +49,7 @@
|
||||
futex word.
|
||||
|
||||
Both absolute and relative timeouts can be used. An absolute timeout
|
||||
- expires when the given specific point in time on the CLOCK_REALTIME clock
|
||||
+ expires when the given specific point in time on the specified clock
|
||||
passes, or when it already has passed. A relative timeout expires when
|
||||
the given duration of time on the CLOCK_MONOTONIC clock passes. Relative
|
||||
timeouts may be imprecise (see futex_supports_exact_relative_timeouts).
|
||||
@@ -159,16 +159,23 @@ futex_reltimed_wait_cancelable (unsigned int* futex_word,
|
||||
unsigned int expected,
|
||||
const struct timespec* reltime, int private);
|
||||
|
||||
+/* Check whether the specified clockid is supported by
|
||||
+ futex_abstimed_wait and futex_abstimed_wait_cancelable. */
|
||||
+static __always_inline int
|
||||
+futex_abstimed_supported_clockid (clockid_t clockid);
|
||||
+
|
||||
/* Like futex_reltimed_wait, but the provided timeout (ABSTIME) is an
|
||||
absolute point in time; a call will time out after this point in time. */
|
||||
static __always_inline int
|
||||
futex_abstimed_wait (unsigned int* futex_word, unsigned int expected,
|
||||
+ clockid_t clockid,
|
||||
const struct timespec* abstime, int private);
|
||||
|
||||
/* Like futex_reltimed_wait but is a POSIX cancellation point. */
|
||||
static __always_inline int
|
||||
futex_abstimed_wait_cancelable (unsigned int* futex_word,
|
||||
unsigned int expected,
|
||||
+ clockid_t clockid,
|
||||
const struct timespec* abstime, int private);
|
||||
|
||||
/* Atomically wrt other futex operations on the same futex, this unblocks the
|
||||
diff --git a/sysdeps/nptl/lowlevellock-futex.h b/sysdeps/nptl/lowlevellock-futex.h
|
||||
index 27b81b83..68ce7516 100644
|
||||
--- a/sysdeps/nptl/lowlevellock-futex.h
|
||||
+++ b/sysdeps/nptl/lowlevellock-futex.h
|
||||
@@ -43,11 +43,15 @@
|
||||
#define lll_futex_timed_wait(futexp, val, timeout, private) \
|
||||
-ENOSYS
|
||||
|
||||
-/* This macro should be defined only if FUTEX_CLOCK_REALTIME is also defined.
|
||||
- If CLOCKBIT is zero, this is identical to lll_futex_timed_wait.
|
||||
- If CLOCKBIT has FUTEX_CLOCK_REALTIME set, then it's the same but
|
||||
- TIMEOUT is counted by CLOCK_REALTIME rather than CLOCK_MONOTONIC. */
|
||||
-#define lll_futex_timed_wait_bitset(futexp, val, timeout, clockbit, private) \
|
||||
+/* Verify whether the supplied clockid is supported by
|
||||
+ lll_futex_clock_wait_bitset. */
|
||||
+#define lll_futex_supported_clockid(clockid) \
|
||||
+ (0)
|
||||
+
|
||||
+/* Wait until a lll_futex_wake call on FUTEXP, or the absolute TIMEOUT
|
||||
+ measured against CLOCKID elapses. CLOCKID may be CLOCK_REALTIME or
|
||||
+ CLOCK_MONOTONIC. */
|
||||
+#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \
|
||||
-ENOSYS
|
||||
|
||||
/* Wake up up to NR waiters on FUTEXP. */
|
||||
diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
|
||||
index 96a07b05..8023cb85 100644
|
||||
--- a/sysdeps/unix/sysv/linux/futex-internal.h
|
||||
+++ b/sysdeps/unix/sysv/linux/futex-internal.h
|
||||
@@ -160,17 +160,26 @@ futex_reltimed_wait_cancelable (unsigned int *futex_word,
|
||||
}
|
||||
}
|
||||
|
||||
+/* See sysdeps/nptl/futex-internal.h for details. */
|
||||
+static __always_inline int
|
||||
+futex_abstimed_supported_clockid (clockid_t clockid)
|
||||
+{
|
||||
+ return lll_futex_supported_clockid (clockid);
|
||||
+}
|
||||
+
|
||||
/* See sysdeps/nptl/futex-internal.h for details. */
|
||||
static __always_inline int
|
||||
futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
|
||||
+ clockid_t clockid,
|
||||
const struct timespec *abstime, int private)
|
||||
{
|
||||
/* Work around the fact that the kernel rejects negative timeout values
|
||||
despite them being valid. */
|
||||
if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
|
||||
return ETIMEDOUT;
|
||||
- int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
|
||||
- FUTEX_CLOCK_REALTIME, private);
|
||||
+ int err = lll_futex_clock_wait_bitset (futex_word, expected,
|
||||
+ clockid, abstime,
|
||||
+ private);
|
||||
switch (err)
|
||||
{
|
||||
case 0:
|
||||
@@ -180,8 +189,9 @@ futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
|
||||
return -err;
|
||||
|
||||
case -EFAULT: /* Must have been caused by a glibc or application bug. */
|
||||
- case -EINVAL: /* Either due to wrong alignment or due to the timeout not
|
||||
- being normalized. Must have been caused by a glibc or
|
||||
+ case -EINVAL: /* Either due to wrong alignment, unsupported
|
||||
+ clockid or due to the timeout not being
|
||||
+ normalized. Must have been caused by a glibc or
|
||||
application bug. */
|
||||
case -ENOSYS: /* Must have been caused by a glibc bug. */
|
||||
/* No other errors are documented at this time. */
|
||||
@@ -194,6 +204,7 @@ futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
|
||||
static __always_inline int
|
||||
futex_abstimed_wait_cancelable (unsigned int *futex_word,
|
||||
unsigned int expected,
|
||||
+ clockid_t clockid,
|
||||
const struct timespec *abstime, int private)
|
||||
{
|
||||
/* Work around the fact that the kernel rejects negative timeout values
|
||||
@@ -202,8 +213,9 @@ futex_abstimed_wait_cancelable (unsigned int *futex_word,
|
||||
return ETIMEDOUT;
|
||||
int oldtype;
|
||||
oldtype = __pthread_enable_asynccancel ();
|
||||
- int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
|
||||
- FUTEX_CLOCK_REALTIME, private);
|
||||
+ int err = lll_futex_clock_wait_bitset (futex_word, expected,
|
||||
+ clockid, abstime,
|
||||
+ private);
|
||||
__pthread_disable_asynccancel (oldtype);
|
||||
switch (err)
|
||||
{
|
||||
diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
|
||||
index fc834ed1..337faf1e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
|
||||
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
|
||||
@@ -82,12 +82,32 @@
|
||||
__lll_private_flag (FUTEX_WAIT, private), \
|
||||
val, timeout)
|
||||
|
||||
-#define lll_futex_timed_wait_bitset(futexp, val, timeout, clockbit, private) \
|
||||
- lll_futex_syscall (6, futexp, \
|
||||
- __lll_private_flag (FUTEX_WAIT_BITSET | (clockbit), \
|
||||
- private), \
|
||||
- val, timeout, NULL /* Unused. */, \
|
||||
- FUTEX_BITSET_MATCH_ANY)
|
||||
+/* Verify whether the supplied clockid is supported by
|
||||
+ lll_futex_clock_wait_bitset. */
|
||||
+#define lll_futex_supported_clockid(clockid) \
|
||||
+ ((clockid) == CLOCK_REALTIME || (clockid) == CLOCK_MONOTONIC)
|
||||
+
|
||||
+/* The kernel currently only supports CLOCK_MONOTONIC or
|
||||
+ CLOCK_REALTIME timeouts for FUTEX_WAIT_BITSET. We could attempt to
|
||||
+ convert others here but currently do not. */
|
||||
+#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \
|
||||
+ ({ \
|
||||
+ long int __ret; \
|
||||
+ if (lll_futex_supported_clockid (clockid)) \
|
||||
+ { \
|
||||
+ const unsigned int clockbit = \
|
||||
+ (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0; \
|
||||
+ const int op = \
|
||||
+ __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private); \
|
||||
+ \
|
||||
+ __ret = lll_futex_syscall (6, futexp, op, val, \
|
||||
+ timeout, NULL /* Unused. */, \
|
||||
+ FUTEX_BITSET_MATCH_ANY); \
|
||||
+ } \
|
||||
+ else \
|
||||
+ __ret = -EINVAL; \
|
||||
+ __ret; \
|
||||
+ })
|
||||
|
||||
#define lll_futex_wake(futexp, nr, private) \
|
||||
lll_futex_syscall (4, futexp, \
|
||||
--
|
||||
2.23.0
|
||||
|
||||
455
backport-0002-support-Add-timespec.h-xtime.h.patch
Normal file
455
backport-0002-support-Add-timespec.h-xtime.h.patch
Normal file
@ -0,0 +1,455 @@
|
||||
From 519839965197291924895a3988804e325035beee Mon Sep 17 00:00:00 2001
|
||||
From: Mike Crowe <mac@mcrowe.com>
|
||||
Date: Thu, 9 May 2019 14:19:21 -0300
|
||||
Subject: [PATCH] support: Add timespec.h xtime.h Add xclock_gettime
|
||||
|
||||
It adds useful functions for tests that use struct timespec.
|
||||
|
||||
Checked on x86_64-linux-gnu and i686-linux-gnu.
|
||||
|
||||
* support/timespec.h: New file. Provide timespec helper functions
|
||||
along with macros in the style of those in check.h.
|
||||
* support/timespec.c: New file. Implement check functions declared
|
||||
in support/timespec.h.
|
||||
* support/timespec-add.c: New file from gnulib containing
|
||||
timespec_add implementation that handles overflow.
|
||||
* support/timespec-sub.c: New file from gnulib containing
|
||||
timespec_sub implementation that handles overflow.
|
||||
* support/xclock_gettime.c (xclock_gettime): New file. Provide
|
||||
clock_gettime wrapper for use in tests that fails the test rather
|
||||
than returning failure.
|
||||
* support/xtime.h: New file to declare xclock_gettime.
|
||||
* support/Makefile: Add xclock_gettime.c timespec.c timespec-add.c timespec-sub.c.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
---
|
||||
support/Makefile | 4 ++
|
||||
support/timespec-add.c | 71 ++++++++++++++++++++++++++++++++++++
|
||||
support/timespec-sub.c | 71 ++++++++++++++++++++++++++++++++++++
|
||||
support/timespec.c | 59 ++++++++++++++++++++++++++++++
|
||||
support/timespec.h | 79 ++++++++++++++++++++++++++++++++++++++++
|
||||
support/xclock_gettime.c | 31 ++++++++++++++++
|
||||
support/xtime.h | 43 ++++++++++++++++++++++
|
||||
7 files changed, 358 insertions(+)
|
||||
create mode 100644 support/timespec-add.c
|
||||
create mode 100644 support/timespec-sub.c
|
||||
create mode 100644 support/timespec.c
|
||||
create mode 100644 support/timespec.h
|
||||
create mode 100644 support/xclock_gettime.c
|
||||
create mode 100644 support/xtime.h
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 9bc68583..90c10bac 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -65,6 +65,9 @@ libsupport-routines = \
|
||||
support_test_main \
|
||||
support_test_verify_impl \
|
||||
temp_file \
|
||||
+ timespec \
|
||||
+ timespec-add \
|
||||
+ timespec-sub \
|
||||
write_message \
|
||||
xaccept \
|
||||
xaccept4 \
|
||||
@@ -72,6 +75,7 @@ libsupport-routines = \
|
||||
xbind \
|
||||
xcalloc \
|
||||
xchroot \
|
||||
+ xclock_gettime \
|
||||
xclose \
|
||||
xconnect \
|
||||
xdlfcn \
|
||||
diff --git a/support/timespec-add.c b/support/timespec-add.c
|
||||
new file mode 100644
|
||||
index 00000000..f26abce1
|
||||
--- /dev/null
|
||||
+++ b/support/timespec-add.c
|
||||
@@ -0,0 +1,71 @@
|
||||
+/* Add two struct timespec values.
|
||||
+ Copyright (C) 2011-2019 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library and is also part of gnulib.
|
||||
+ Patches to this file should be submitted to both projects.
|
||||
+
|
||||
+ 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/>. */
|
||||
+
|
||||
+/* Return the sum of two timespec values A and B. On overflow, return
|
||||
+ an extremal value. This assumes 0 <= tv_nsec < TIMESPEC_HZ. */
|
||||
+
|
||||
+#include <config.h>
|
||||
+#include "timespec.h"
|
||||
+
|
||||
+#include "intprops.h"
|
||||
+
|
||||
+struct timespec
|
||||
+timespec_add (struct timespec a, struct timespec b)
|
||||
+{
|
||||
+ time_t rs = a.tv_sec;
|
||||
+ time_t bs = b.tv_sec;
|
||||
+ int ns = a.tv_nsec + b.tv_nsec;
|
||||
+ int nsd = ns - TIMESPEC_HZ;
|
||||
+ int rns = ns;
|
||||
+ time_t tmin = TYPE_MINIMUM (time_t);
|
||||
+ time_t tmax = TYPE_MAXIMUM (time_t);
|
||||
+
|
||||
+ if (0 <= nsd)
|
||||
+ {
|
||||
+ rns = nsd;
|
||||
+ if (bs < tmax)
|
||||
+ bs++;
|
||||
+ else if (rs < 0)
|
||||
+ rs++;
|
||||
+ else
|
||||
+ goto high_overflow;
|
||||
+ }
|
||||
+
|
||||
+ /* INT_ADD_WRAPV is not appropriate since time_t might be unsigned.
|
||||
+ In theory time_t might be narrower than int, so plain
|
||||
+ INT_ADD_OVERFLOW does not suffice. */
|
||||
+ if (! INT_ADD_OVERFLOW (rs, bs) && tmin <= rs + bs && rs + bs <= tmax)
|
||||
+ rs += bs;
|
||||
+ else
|
||||
+ {
|
||||
+ if (rs < 0)
|
||||
+ {
|
||||
+ rs = tmin;
|
||||
+ rns = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ high_overflow:
|
||||
+ rs = tmax;
|
||||
+ rns = TIMESPEC_HZ - 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return make_timespec (rs, rns);
|
||||
+}
|
||||
diff --git a/support/timespec-sub.c b/support/timespec-sub.c
|
||||
new file mode 100644
|
||||
index 00000000..7c33a59f
|
||||
--- /dev/null
|
||||
+++ b/support/timespec-sub.c
|
||||
@@ -0,0 +1,71 @@
|
||||
+/* Subtract two struct timespec values.
|
||||
+ Copyright (C) 2011-2019 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library and is also part of gnulib.
|
||||
+ Patches to this file should be submitted to both projects.
|
||||
+
|
||||
+ 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/>. */
|
||||
+
|
||||
+/* Return the difference between two timespec values A and B. On
|
||||
+ overflow, return an extremal value. This assumes 0 <= tv_nsec <
|
||||
+ TIMESPEC_HZ. */
|
||||
+
|
||||
+#include <config.h>
|
||||
+#include "timespec.h"
|
||||
+
|
||||
+#include "intprops.h"
|
||||
+
|
||||
+struct timespec
|
||||
+timespec_sub (struct timespec a, struct timespec b)
|
||||
+{
|
||||
+ time_t rs = a.tv_sec;
|
||||
+ time_t bs = b.tv_sec;
|
||||
+ int ns = a.tv_nsec - b.tv_nsec;
|
||||
+ int rns = ns;
|
||||
+ time_t tmin = TYPE_MINIMUM (time_t);
|
||||
+ time_t tmax = TYPE_MAXIMUM (time_t);
|
||||
+
|
||||
+ if (ns < 0)
|
||||
+ {
|
||||
+ rns = ns + TIMESPEC_HZ;
|
||||
+ if (bs < tmax)
|
||||
+ bs++;
|
||||
+ else if (- TYPE_SIGNED (time_t) < rs)
|
||||
+ rs--;
|
||||
+ else
|
||||
+ goto low_overflow;
|
||||
+ }
|
||||
+
|
||||
+ /* INT_SUBTRACT_WRAPV is not appropriate since time_t might be unsigned.
|
||||
+ In theory time_t might be narrower than int, so plain
|
||||
+ INT_SUBTRACT_OVERFLOW does not suffice. */
|
||||
+ if (! INT_SUBTRACT_OVERFLOW (rs, bs) && tmin <= rs - bs && rs - bs <= tmax)
|
||||
+ rs -= bs;
|
||||
+ else
|
||||
+ {
|
||||
+ if (rs < 0)
|
||||
+ {
|
||||
+ low_overflow:
|
||||
+ rs = tmin;
|
||||
+ rns = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ rs = tmax;
|
||||
+ rns = TIMESPEC_HZ - 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return make_timespec (rs, rns);
|
||||
+}
|
||||
diff --git a/support/timespec.c b/support/timespec.c
|
||||
new file mode 100644
|
||||
index 00000000..0a1a13ff
|
||||
--- /dev/null
|
||||
+++ b/support/timespec.c
|
||||
@@ -0,0 +1,59 @@
|
||||
+/* Support code for timespec checks.
|
||||
+ Copyright (C) 2019 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 <support/timespec.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+void
|
||||
+test_timespec_before_impl (const char *file, int line,
|
||||
+ const struct timespec left,
|
||||
+ const struct timespec right)
|
||||
+{
|
||||
+ if (left.tv_sec > right.tv_sec
|
||||
+ || (left.tv_sec == right.tv_sec
|
||||
+ && left.tv_nsec > right.tv_nsec)) {
|
||||
+ support_record_failure ();
|
||||
+ const struct timespec diff = timespec_sub (left, right);
|
||||
+ printf ("%s:%d: %jd.%09jds not before %jd.%09jds "
|
||||
+ "(difference %jd.%09jds)\n",
|
||||
+ file, line,
|
||||
+ (intmax_t) left.tv_sec, (intmax_t) left.tv_nsec,
|
||||
+ (intmax_t) right.tv_sec, (intmax_t) right.tv_nsec,
|
||||
+ (intmax_t) diff.tv_sec, (intmax_t) diff.tv_nsec);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+test_timespec_equal_or_after_impl (const char *file, int line,
|
||||
+ const struct timespec left,
|
||||
+ const struct timespec right)
|
||||
+{
|
||||
+ if (left.tv_sec < right.tv_sec
|
||||
+ || (left.tv_sec == right.tv_sec
|
||||
+ && left.tv_nsec < right.tv_nsec)) {
|
||||
+ support_record_failure ();
|
||||
+ const struct timespec diff = timespec_sub (right, left);
|
||||
+ printf ("%s:%d: %jd.%09jds not after %jd.%09jds "
|
||||
+ "(difference %jd.%09jds)\n",
|
||||
+ file, line,
|
||||
+ (intmax_t) left.tv_sec, (intmax_t) left.tv_nsec,
|
||||
+ (intmax_t) right.tv_sec, (intmax_t) right.tv_nsec,
|
||||
+ (intmax_t) diff.tv_sec, (intmax_t) diff.tv_nsec);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/support/timespec.h b/support/timespec.h
|
||||
new file mode 100644
|
||||
index 00000000..cf2c0318
|
||||
--- /dev/null
|
||||
+++ b/support/timespec.h
|
||||
@@ -0,0 +1,79 @@
|
||||
+/* Useful functions for tests that use struct timespec.
|
||||
+ Copyright (C) 2019 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/>. */
|
||||
+
|
||||
+#ifndef SUPPORT_TIMESPEC_H
|
||||
+#define SUPPORT_TIMESPEC_H
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <time.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/xtime.h>
|
||||
+
|
||||
+struct timespec timespec_add (struct timespec, struct timespec)
|
||||
+ __attribute__((const));
|
||||
+struct timespec timespec_sub (struct timespec, struct timespec)
|
||||
+ __attribute__((const));
|
||||
+
|
||||
+static inline struct timespec
|
||||
+make_timespec (time_t s, long int ns)
|
||||
+{
|
||||
+ struct timespec r;
|
||||
+ r.tv_sec = s;
|
||||
+ r.tv_nsec = ns;
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+enum { TIMESPEC_HZ = 1000000000 };
|
||||
+
|
||||
+void test_timespec_before_impl (const char *file, int line,
|
||||
+ const struct timespec left,
|
||||
+ const struct timespec right);
|
||||
+
|
||||
+void test_timespec_equal_or_after_impl (const char *file, int line,
|
||||
+ const struct timespec left,
|
||||
+ const struct timespec right);
|
||||
+
|
||||
+/* Check that the timespec on the left represents a time before the
|
||||
+ time on the right. */
|
||||
+#define TEST_TIMESPEC_BEFORE(left, right) \
|
||||
+ test_timespec_before_impl (__FILE__, __LINE__, (left), (right))
|
||||
+
|
||||
+#define TEST_TIMESPEC_BEFORE_NOW(left, clockid) \
|
||||
+ ({ \
|
||||
+ struct timespec now; \
|
||||
+ const int saved_errno = errno; \
|
||||
+ xclock_gettime ((clockid), &now); \
|
||||
+ TEST_TIMESPEC_BEFORE ((left), now); \
|
||||
+ errno = saved_errno; \
|
||||
+ })
|
||||
+
|
||||
+/* Check that the timespec on the left represents a time equal to or
|
||||
+ after the time on the right. */
|
||||
+#define TEST_TIMESPEC_EQUAL_OR_AFTER(left, right) \
|
||||
+ test_timespec_equal_or_after_impl (__FILE__, __LINE__, left, right)
|
||||
+
|
||||
+#define TEST_TIMESPEC_NOW_OR_AFTER(clockid, right) \
|
||||
+ ({ \
|
||||
+ struct timespec now; \
|
||||
+ const int saved_errno = errno; \
|
||||
+ xclock_gettime ((clockid), &now); \
|
||||
+ TEST_TIMESPEC_EQUAL_OR_AFTER (now, (right)); \
|
||||
+ errno = saved_errno; \
|
||||
+ })
|
||||
+
|
||||
+#endif /* SUPPORT_TIMESPEC_H */
|
||||
diff --git a/support/xclock_gettime.c b/support/xclock_gettime.c
|
||||
new file mode 100644
|
||||
index 00000000..5dd3ae9b
|
||||
--- /dev/null
|
||||
+++ b/support/xclock_gettime.c
|
||||
@@ -0,0 +1,31 @@
|
||||
+/* clock_gettime with error checking.
|
||||
+ Copyright (C) 2019 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 <support/check.h>
|
||||
+#include <support/xtime.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+void
|
||||
+xclock_gettime (clockid_t clockid,
|
||||
+ struct timespec *ts)
|
||||
+{
|
||||
+ const int ret = clock_gettime (clockid, ts);
|
||||
+ if (ret < 0)
|
||||
+ FAIL_EXIT1 ("clock_gettime (%d): %m",
|
||||
+ clockid);
|
||||
+}
|
||||
diff --git a/support/xtime.h b/support/xtime.h
|
||||
new file mode 100644
|
||||
index 00000000..9e6df5b9
|
||||
--- /dev/null
|
||||
+++ b/support/xtime.h
|
||||
@@ -0,0 +1,43 @@
|
||||
+/* Support functionality for using time.
|
||||
+ Copyright (C) 2019 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/>. */
|
||||
+
|
||||
+#ifndef SUPPORT_TIME_H
|
||||
+#define SUPPORT_TIME_H
|
||||
+
|
||||
+#include <time.h>
|
||||
+
|
||||
+__BEGIN_DECLS
|
||||
+
|
||||
+/* The following functions call the corresponding libc functions and
|
||||
+ terminate the process on error. */
|
||||
+
|
||||
+void xclock_gettime (clockid_t clock, struct timespec *ts);
|
||||
+
|
||||
+/* This helper can often simplify tests by avoiding an explicit
|
||||
+ variable declaration or allowing that declaration to be const. */
|
||||
+
|
||||
+static inline struct timespec xclock_now (clockid_t clock)
|
||||
+{
|
||||
+ struct timespec ts;
|
||||
+ xclock_gettime (clock, &ts);
|
||||
+ return ts;
|
||||
+}
|
||||
+
|
||||
+__END_DECLS
|
||||
+
|
||||
+#endif /* SUPPORT_TIME_H */
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -0,0 +1,713 @@
|
||||
From afe4de7d283ebd88157126c5494ce1796194c16e Mon Sep 17 00:00:00 2001
|
||||
From: Mike Crowe <mac@mcrowe.com>
|
||||
Date: Fri, 21 Jun 2019 17:36:56 +0000
|
||||
Subject: [PATCH] nptl: Add POSIX-proposed pthread_cond_clockwait
|
||||
|
||||
Add:
|
||||
|
||||
int pthread_cond_clockwait (pthread_cond_t *cond,
|
||||
pthread_mutex_t *mutex,
|
||||
clockid_t clockid,
|
||||
const struct timespec *abstime)
|
||||
|
||||
which behaves just like pthread_cond_timedwait except it always measures
|
||||
abstime against the supplied clockid. Currently supports CLOCK_REALTIME
|
||||
and
|
||||
CLOCK_MONOTONIC and returns EINVAL if any other clock is specified.
|
||||
|
||||
Includes feedback from many others. This function was originally
|
||||
proposed[1] as pthread_cond_timedwaitonclock_np, but The Austin Group
|
||||
preferred the new name.
|
||||
|
||||
* nptl/Makefile: Add tst-cond26 and tst-cond27
|
||||
* nptl/Versions (GLIBC_2.30): Add pthread_cond_clockwait
|
||||
* sysdeps/nptl/pthread.h: Likewise
|
||||
* nptl/pthreadP.h: Likewise
|
||||
* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Add
|
||||
clockid parameter and comment describing why we don't need to check
|
||||
its value. Use that value when calling
|
||||
futex_abstimed_wait_cancelable rather than reading the clock from
|
||||
the flags. (__pthread_cond_wait): Pass unused clockid parameter.
|
||||
(__pthread_cond_timedwait): Read clock from flags and pass it to
|
||||
__pthread_cond_wait_common. (__pthread_cond_clockwait): Add new
|
||||
function with weak alias from pthread_cond_clockwait.
|
||||
* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
|
||||
* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
|
||||
(GLIBC_2.30): Likewise.
|
||||
* nptl/tst-cond11.c (run_test): Support testing
|
||||
pthread_cond_clockwait too by using a special magic
|
||||
CLOCK_USE_ATTR_CLOCK value to determine whether to call
|
||||
pthread_cond_timedwait or pthread_cond_clockwait. (do_test): Pass
|
||||
CLOCK_USE_ATTR_CLOCK for existing tests, and add new tests using
|
||||
all combinations of CLOCK_MONOTONIC and CLOCK_REALTIME.
|
||||
* ntpl/tst-cond26.c: New test for passing unsupported and invalid
|
||||
clocks to pthread_cond_clockwait.
|
||||
* nptl/tst-cond27.c: Add test similar to tst-cond5.c, but using
|
||||
struct timespec and pthread_cond_clockwait.
|
||||
* manual/threads.texi: Document pthread_cond_clockwait.
|
||||
|
||||
[1] https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
---
|
||||
ChangeLog | 29 +++
|
||||
manual/threads.texi | 20 ++
|
||||
nptl/Makefile | 1 +
|
||||
nptl/Versions | 1 +
|
||||
nptl/pthreadP.h | 5 +
|
||||
nptl/pthread_cond_wait.c | 44 ++++-
|
||||
nptl/tst-cond11.c | 183 +++++-------------
|
||||
nptl/tst-cond26.c | 77 ++++++++
|
||||
nptl/tst-cond27.c | 66 +++++++
|
||||
sysdeps/nptl/pthread.h | 15 ++
|
||||
.../sysv/linux/aarch64/libpthread.abilist | 1 +
|
||||
.../sysv/linux/x86_64/64/libpthread.abilist | 1 +
|
||||
12 files changed, 305 insertions(+), 138 deletions(-)
|
||||
create mode 100644 nptl/tst-cond26.c
|
||||
create mode 100644 nptl/tst-cond27.c
|
||||
|
||||
diff --git a/ChangeLog b/ChangeLog
|
||||
index 1f8cf24f..8601e9fe 100644
|
||||
--- a/ChangeLog
|
||||
+++ b/ChangeLog
|
||||
@@ -1,5 +1,34 @@
|
||||
2019-07-12 Mike Crowe <mac@mcrowe.com>
|
||||
|
||||
+ nptl: Add POSIX-proposed pthread_cond_clockwait which behaves just
|
||||
+ like pthread_cond_timedwait except it always measures abstime
|
||||
+ against the supplied clockid.
|
||||
+ * nptl/Makefile: Add tst-cond26 and tst-cond27
|
||||
+ * nptl/Versions (GLIBC_2.30): Add pthread_cond_clockwait
|
||||
+ * sysdeps/nptl/pthread.h: Likewise
|
||||
+ * nptl/pthreadP.h: Likewise
|
||||
+ * nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Add
|
||||
+ clockid parameter and comment describing why we don't need to check
|
||||
+ its value. Use that value when calling
|
||||
+ futex_abstimed_wait_cancelable rather than reading the clock from
|
||||
+ the flags. (__pthread_cond_wait): Pass unused clockid parameter.
|
||||
+ (__pthread_cond_timedwait): Read clock from flags and pass it to
|
||||
+ __pthread_cond_wait_common. (__pthread_cond_clockwait): Add new
|
||||
+ function with weak alias from pthread_cond_clockwait.
|
||||
+ * sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
|
||||
+ * sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
|
||||
+ (GLIBC_2.30): Likewise.
|
||||
+ * nptl/tst-cond11.c (run_test): Support testing
|
||||
+ pthread_cond_clockwait too by using a special magic
|
||||
+ CLOCK_USE_ATTR_CLOCK value to determine whether to call
|
||||
+ pthread_cond_timedwait or pthread_cond_clockwait. (do_test): Pass
|
||||
+ CLOCK_USE_ATTR_CLOCK for existing tests, and add new tests using
|
||||
+ all combinations of CLOCK_MONOTONIC and CLOCK_REALTIME.
|
||||
+ * ntpl/tst-cond26.c: New test for passing unsupported and invalid
|
||||
+ clocks to pthread_cond_clockwait.
|
||||
+ * nptl/tst-cond27.c: Add test similar to tst-cond5.c, but using
|
||||
+ struct timespec and pthread_cond_clockwait.
|
||||
+ * manual/threads.texi: Document pthread_cond_clockwait.
|
||||
nptl: Add clockid parameter to futex timed wait calls
|
||||
* sysdeps/nptl/lowlevellock-futex.h,
|
||||
sysdeps/unix/sysv/linux/lowlevellock-futex.h: Replace
|
||||
diff --git a/manual/threads.texi b/manual/threads.texi
|
||||
index 87fda7d8..f4c5447c 100644
|
||||
--- a/manual/threads.texi
|
||||
+++ b/manual/threads.texi
|
||||
@@ -669,6 +669,26 @@ The system does not have sufficient memory.
|
||||
@end table
|
||||
@end deftypefun
|
||||
|
||||
+@comment pthread.h
|
||||
+@comment POSIX-proposed
|
||||
+@deftypefun int pthread_cond_clockwait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex},
|
||||
+ clockid_t @var{clockid}, const struct timespec *@var{abstime})
|
||||
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
|
||||
+@c If exactly the same function with arguments is called from a signal
|
||||
+@c handler that interrupts between the mutex unlock and sleep then it
|
||||
+@c will unlock the mutex twice resulting in undefined behaviour. Keep
|
||||
+@c in mind that the unlock and sleep are only atomic with respect to other
|
||||
+@c threads (really a happens-after relationship for pthread_cond_broadcast
|
||||
+@c and pthread_cond_signal).
|
||||
+@c In the AC case we would cancel the thread and the mutex would remain
|
||||
+@c locked and we can't recover from that.
|
||||
+Behaves like @code{pthread_cond_timedwait} except the time @var{abstime} is
|
||||
+measured against the clock specified by @var{clockid} rather than the clock
|
||||
+specified or defaulted when @code{pthread_cond_init} was called. Currently,
|
||||
+@var{clockid} must be either @code{CLOCK_MONOTONIC} or
|
||||
+@code{CLOCK_REALTIME}.
|
||||
+@end deftypefun
|
||||
+
|
||||
@c FIXME these are undocumented:
|
||||
@c pthread_atfork
|
||||
@c pthread_attr_destroy
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index fb68f238..6a9cd8fa 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -250,6 +250,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
|
||||
tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
|
||||
tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
|
||||
tst-cond20 tst-cond21 tst-cond22 tst-cond23 tst-cond24 tst-cond25 \
|
||||
+ tst-cond26 tst-cond27 \
|
||||
tst-cond-except \
|
||||
tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
|
||||
tst-robust6 tst-robust7 tst-robust8 tst-robust9 \
|
||||
diff --git a/nptl/Versions b/nptl/Versions
|
||||
index e7f691da..94d6fa92 100644
|
||||
--- a/nptl/Versions
|
||||
+++ b/nptl/Versions
|
||||
@@ -275,6 +275,7 @@ libpthread {
|
||||
mtx_init; mtx_lock; mtx_timedlock; mtx_trylock; mtx_unlock; mtx_destroy;
|
||||
call_once; cnd_broadcast; cnd_destroy; cnd_init; cnd_signal;
|
||||
cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
|
||||
+ pthread_cond_clockwait;
|
||||
}
|
||||
|
||||
GLIBC_PRIVATE {
|
||||
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
|
||||
index 19efe1e3..67de9d8c 100644
|
||||
--- a/nptl/pthreadP.h
|
||||
+++ b/nptl/pthreadP.h
|
||||
@@ -492,6 +492,11 @@ extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
|
||||
extern int __pthread_cond_timedwait (pthread_cond_t *cond,
|
||||
pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime);
|
||||
+extern int __pthread_cond_clockwait (pthread_cond_t *cond,
|
||||
+ pthread_mutex_t *mutex,
|
||||
+ clockid_t clockid,
|
||||
+ const struct timespec *abstime)
|
||||
+ __nonnull ((1, 2, 4));
|
||||
extern int __pthread_condattr_destroy (pthread_condattr_t *attr);
|
||||
extern int __pthread_condattr_init (pthread_condattr_t *attr);
|
||||
extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *));
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 3294fa3a..fec86698 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -378,6 +378,7 @@ __condvar_cleanup_waiting (void *arg)
|
||||
*/
|
||||
static __always_inline int
|
||||
__pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
+ clockid_t clockid,
|
||||
const struct timespec *abstime)
|
||||
{
|
||||
const int maxspin = 0;
|
||||
@@ -386,6 +387,11 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
|
||||
LIBC_PROBE (cond_wait, 2, cond, mutex);
|
||||
|
||||
+ /* clockid will already have been checked by
|
||||
+ __pthread_cond_clockwait or pthread_condattr_setclock, or we
|
||||
+ don't use it if abstime is NULL, so we don't need to check it
|
||||
+ here. */
|
||||
+
|
||||
/* Acquire a position (SEQ) in the waiter sequence (WSEQ). We use an
|
||||
atomic operation because signals and broadcasts may update the group
|
||||
switch without acquiring the mutex. We do not need release MO here
|
||||
@@ -511,10 +517,6 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
err = ETIMEDOUT;
|
||||
else
|
||||
{
|
||||
- const clockid_t clockid =
|
||||
- ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
|
||||
- CLOCK_MONOTONIC : CLOCK_REALTIME;
|
||||
-
|
||||
err = futex_abstimed_wait_cancelable
|
||||
(cond->__data.__g_signals + g, 0, clockid, abstime,
|
||||
private);
|
||||
@@ -632,7 +634,8 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
int
|
||||
__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
- return __pthread_cond_wait_common (cond, mutex, NULL);
|
||||
+ /* clockid is unused when abstime is NULL. */
|
||||
+ return __pthread_cond_wait_common (cond, mutex, 0, NULL);
|
||||
}
|
||||
|
||||
/* See __pthread_cond_wait_common. */
|
||||
@@ -644,10 +647,39 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
it can assume that abstime is not NULL. */
|
||||
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
|
||||
return EINVAL;
|
||||
- return __pthread_cond_wait_common (cond, mutex, abstime);
|
||||
+
|
||||
+ /* Relaxed MO is suffice because clock ID bit is only modified
|
||||
+ in condition creation. */
|
||||
+ unsigned int flags = atomic_load_relaxed (&cond->__data.__wrefs);
|
||||
+ clockid_t clockid = (flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK)
|
||||
+ ? CLOCK_MONOTONIC : CLOCK_REALTIME;
|
||||
+ return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
|
||||
+}
|
||||
+
|
||||
+/* See __pthread_cond_wait_common. */
|
||||
+int
|
||||
+__pthread_cond_clockwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
+ clockid_t clockid,
|
||||
+ const struct timespec *abstime)
|
||||
+{
|
||||
+ /* Check parameter validity. This should also tell the compiler that
|
||||
+ it can assume that abstime is not NULL. */
|
||||
+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
|
||||
+ return EINVAL;
|
||||
+
|
||||
+ if (!futex_abstimed_supported_clockid (clockid))
|
||||
+ return EINVAL;
|
||||
+
|
||||
+ /* If we do not support waiting using CLOCK_MONOTONIC, return an error. */
|
||||
+ if (clockid == CLOCK_MONOTONIC
|
||||
+ && !futex_supports_exact_relative_timeouts ())
|
||||
+ return EINVAL;
|
||||
+
|
||||
+ return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
|
||||
}
|
||||
|
||||
versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
|
||||
GLIBC_2_3_2);
|
||||
versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
|
||||
GLIBC_2_3_2);
|
||||
+weak_alias (__pthread_cond_clockwait, pthread_cond_clockwait);
|
||||
diff --git a/nptl/tst-cond11.c b/nptl/tst-cond11.c
|
||||
index eebc8ac5..16d937c4 100644
|
||||
--- a/nptl/tst-cond11.c
|
||||
+++ b/nptl/tst-cond11.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
|
||||
+/* Copyright (C) 2003-2019 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
|
||||
|
||||
@@ -21,145 +21,64 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/timespec.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <support/xtime.h>
|
||||
|
||||
+/* A bogus clock value that tells run_test to use pthread_cond_timedwait
|
||||
+ rather than pthread_condclockwait. */
|
||||
+#define CLOCK_USE_ATTR_CLOCK (-1)
|
||||
|
||||
#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
|
||||
static int
|
||||
-run_test (clockid_t cl)
|
||||
+run_test (clockid_t attr_clock, clockid_t wait_clock)
|
||||
{
|
||||
pthread_condattr_t condattr;
|
||||
pthread_cond_t cond;
|
||||
pthread_mutexattr_t mutattr;
|
||||
pthread_mutex_t mut;
|
||||
|
||||
- printf ("clock = %d\n", (int) cl);
|
||||
+ printf ("attr_clock = %d\n", (int) attr_clock);
|
||||
|
||||
- if (pthread_condattr_init (&condattr) != 0)
|
||||
- {
|
||||
- puts ("condattr_init failed");
|
||||
- return 1;
|
||||
- }
|
||||
+ TEST_COMPARE (pthread_condattr_init (&condattr), 0);
|
||||
+ TEST_COMPARE (pthread_condattr_setclock (&condattr, attr_clock), 0);
|
||||
|
||||
- if (pthread_condattr_setclock (&condattr, cl) != 0)
|
||||
- {
|
||||
- puts ("condattr_setclock failed");
|
||||
- return 1;
|
||||
- }
|
||||
+ clockid_t attr_clock_read;
|
||||
+ TEST_COMPARE (pthread_condattr_getclock (&condattr, &attr_clock_read), 0);
|
||||
+ TEST_COMPARE (attr_clock, attr_clock_read);
|
||||
|
||||
- clockid_t cl2;
|
||||
- if (pthread_condattr_getclock (&condattr, &cl2) != 0)
|
||||
- {
|
||||
- puts ("condattr_getclock failed");
|
||||
- return 1;
|
||||
- }
|
||||
- if (cl != cl2)
|
||||
- {
|
||||
- printf ("condattr_getclock returned wrong value: %d, expected %d\n",
|
||||
- (int) cl2, (int) cl);
|
||||
- return 1;
|
||||
- }
|
||||
+ TEST_COMPARE (pthread_cond_init (&cond, &condattr), 0);
|
||||
+ TEST_COMPARE (pthread_condattr_destroy (&condattr), 0);
|
||||
|
||||
- if (pthread_cond_init (&cond, &condattr) != 0)
|
||||
- {
|
||||
- puts ("cond_init failed");
|
||||
- return 1;
|
||||
- }
|
||||
+ xpthread_mutexattr_init (&mutattr);
|
||||
+ xpthread_mutexattr_settype (&mutattr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
+ xpthread_mutex_init (&mut, &mutattr);
|
||||
+ xpthread_mutexattr_destroy (&mutattr);
|
||||
|
||||
- if (pthread_condattr_destroy (&condattr) != 0)
|
||||
- {
|
||||
- puts ("condattr_destroy failed");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if (pthread_mutexattr_init (&mutattr) != 0)
|
||||
- {
|
||||
- puts ("mutexattr_init failed");
|
||||
- return 1;
|
||||
- }
|
||||
+ xpthread_mutex_lock (&mut);
|
||||
+ TEST_COMPARE (pthread_mutex_lock (&mut), EDEADLK);
|
||||
|
||||
- if (pthread_mutexattr_settype (&mutattr, PTHREAD_MUTEX_ERRORCHECK) != 0)
|
||||
- {
|
||||
- puts ("mutexattr_settype failed");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if (pthread_mutex_init (&mut, &mutattr) != 0)
|
||||
- {
|
||||
- puts ("mutex_init failed");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if (pthread_mutexattr_destroy (&mutattr) != 0)
|
||||
- {
|
||||
- puts ("mutexattr_destroy failed");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if (pthread_mutex_lock (&mut) != 0)
|
||||
- {
|
||||
- puts ("mutex_lock failed");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if (pthread_mutex_lock (&mut) != EDEADLK)
|
||||
- {
|
||||
- puts ("2nd mutex_lock did not return EDEADLK");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- struct timespec ts;
|
||||
- if (clock_gettime (cl, &ts) != 0)
|
||||
- {
|
||||
- puts ("clock_gettime failed");
|
||||
- return 1;
|
||||
- }
|
||||
+ struct timespec ts_timeout;
|
||||
+ xclock_gettime (wait_clock == CLOCK_USE_ATTR_CLOCK ? attr_clock : wait_clock,
|
||||
+ &ts_timeout);
|
||||
|
||||
/* Wait one second. */
|
||||
- ++ts.tv_sec;
|
||||
-
|
||||
- int e = pthread_cond_timedwait (&cond, &mut, &ts);
|
||||
- if (e == 0)
|
||||
- {
|
||||
- puts ("cond_timedwait succeeded");
|
||||
- return 1;
|
||||
- }
|
||||
- else if (e != ETIMEDOUT)
|
||||
- {
|
||||
- puts ("cond_timedwait did not return ETIMEDOUT");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- struct timespec ts2;
|
||||
- if (clock_gettime (cl, &ts2) != 0)
|
||||
- {
|
||||
- puts ("second clock_gettime failed");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- 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;
|
||||
- }
|
||||
+ ++ts_timeout.tv_sec;
|
||||
|
||||
- if (pthread_mutex_unlock (&mut) != 0)
|
||||
- {
|
||||
- puts ("mutex_unlock failed");
|
||||
- return 1;
|
||||
- }
|
||||
+ if (wait_clock == CLOCK_USE_ATTR_CLOCK) {
|
||||
+ TEST_COMPARE (pthread_cond_timedwait (&cond, &mut, &ts_timeout), ETIMEDOUT);
|
||||
+ TEST_TIMESPEC_BEFORE_NOW (ts_timeout, attr_clock);
|
||||
+ } else {
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut, wait_clock, &ts_timeout),
|
||||
+ ETIMEDOUT);
|
||||
+ TEST_TIMESPEC_BEFORE_NOW (ts_timeout, wait_clock);
|
||||
+ }
|
||||
|
||||
- if (pthread_mutex_destroy (&mut) != 0)
|
||||
- {
|
||||
- puts ("mutex_destroy failed");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if (pthread_cond_destroy (&cond) != 0)
|
||||
- {
|
||||
- puts ("cond_destroy failed");
|
||||
- return 1;
|
||||
- }
|
||||
+ xpthread_mutex_unlock (&mut);
|
||||
+ xpthread_mutex_destroy (&mut);
|
||||
+ TEST_COMPARE (pthread_cond_destroy (&cond), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -171,12 +90,11 @@ do_test (void)
|
||||
{
|
||||
#if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1
|
||||
|
||||
- puts ("_POSIX_CLOCK_SELECTION not supported, test skipped");
|
||||
- return 0;
|
||||
+ FAIL_UNSUPPORTED ("_POSIX_CLOCK_SELECTION not supported, test skipped");
|
||||
|
||||
#else
|
||||
|
||||
- int res = run_test (CLOCK_REALTIME);
|
||||
+ run_test (CLOCK_REALTIME, CLOCK_USE_ATTR_CLOCK);
|
||||
|
||||
# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
|
||||
# if _POSIX_MONOTONIC_CLOCK == 0
|
||||
@@ -184,21 +102,22 @@ do_test (void)
|
||||
if (e < 0)
|
||||
puts ("CLOCK_MONOTONIC not supported");
|
||||
else if (e == 0)
|
||||
- {
|
||||
- puts ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
|
||||
- res = 1;
|
||||
- }
|
||||
+ FAIL_RET ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
|
||||
else
|
||||
+ {
|
||||
# endif
|
||||
- res |= run_test (CLOCK_MONOTONIC);
|
||||
+ run_test (CLOCK_MONOTONIC, CLOCK_USE_ATTR_CLOCK);
|
||||
+ run_test (CLOCK_REALTIME, CLOCK_MONOTONIC);
|
||||
+ run_test (CLOCK_MONOTONIC, CLOCK_MONOTONIC);
|
||||
+ run_test (CLOCK_MONOTONIC, CLOCK_REALTIME);
|
||||
+ }
|
||||
# else
|
||||
puts ("_POSIX_MONOTONIC_CLOCK not defined");
|
||||
# endif
|
||||
|
||||
- return res;
|
||||
+ return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
-#define TIMEOUT 3
|
||||
-#define TEST_FUNCTION do_test ()
|
||||
-#include "../test-skeleton.c"
|
||||
+#include <support/test-driver.c>
|
||||
+
|
||||
diff --git a/nptl/tst-cond26.c b/nptl/tst-cond26.c
|
||||
new file mode 100644
|
||||
index 00000000..bb4d6c9b
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-cond26.c
|
||||
@@ -0,0 +1,77 @@
|
||||
+/* Test unsupported/bad clocks passed to pthread_cond_clockwait.
|
||||
+
|
||||
+ Copyright (C) 2019 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 <pthread.h>
|
||||
+#include <stdio.h>
|
||||
+#include <time.h>
|
||||
+#include <unistd.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/timespec.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
|
||||
+
|
||||
+#define NOT_A_VALID_CLOCK 123456
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ xpthread_mutex_lock (&mut);
|
||||
+
|
||||
+ const struct timespec ts = make_timespec (0, 0);
|
||||
+
|
||||
+ /* These clocks are meaningless to sem_clockwait. */
|
||||
+#if defined(CLOCK_PROCESS_CPUTIME_ID)
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
+ CLOCK_PROCESS_CPUTIME_ID, &ts), EINVAL);
|
||||
+#endif
|
||||
+#if defined(CLOCK_THREAD_CPUTIME_ID)
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
+ CLOCK_THREAD_CPUTIME_ID, &ts), EINVAL);
|
||||
+#endif
|
||||
+
|
||||
+ /* These clocks might be meaningful, but are currently unsupported
|
||||
+ by pthread_cond_clockwait. */
|
||||
+#if defined(CLOCK_REALTIME_COARSE)
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
+ CLOCK_REALTIME_COARSE, &ts), EINVAL);
|
||||
+#endif
|
||||
+#if defined(CLOCK_MONOTONIC_RAW)
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
+ CLOCK_MONOTONIC_RAW, &ts), EINVAL);
|
||||
+#endif
|
||||
+#if defined(CLOCK_MONOTONIC_COARSE)
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
+ CLOCK_MONOTONIC_COARSE, &ts), EINVAL);
|
||||
+#endif
|
||||
+#if defined(CLOCK_BOOTTIME)
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
+ CLOCK_BOOTTIME, &ts), EINVAL);
|
||||
+#endif
|
||||
+
|
||||
+ /* This is a completely invalid clock. */
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
+ NOT_A_VALID_CLOCK, &ts), EINVAL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/nptl/tst-cond27.c b/nptl/tst-cond27.c
|
||||
new file mode 100644
|
||||
index 00000000..ad9658af
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-cond27.c
|
||||
@@ -0,0 +1,66 @@
|
||||
+/* Test pthread_cond_clockwait timeout.
|
||||
+
|
||||
+ Copyright (C) 2019 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 <pthread.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <time.h>
|
||||
+#include <sys/time.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/timespec.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+
|
||||
+static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
||||
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+do_test_clock (clockid_t clockid)
|
||||
+{
|
||||
+ /* Get the mutex. */
|
||||
+ xpthread_mutex_lock (&mut);
|
||||
+
|
||||
+ /* Waiting for the condition will fail. But we want the timeout here. */
|
||||
+ const struct timespec ts_now = xclock_now (clockid);
|
||||
+ const struct timespec ts_timeout =
|
||||
+ timespec_add (ts_now, make_timespec (0, 500000000));
|
||||
+
|
||||
+ /* In theory pthread_cond_clockwait could return zero here due to
|
||||
+ spurious wakeup. However that can't happen without a signal or an
|
||||
+ additional waiter. */
|
||||
+ TEST_COMPARE (pthread_cond_clockwait (&cond, &mut, clockid, &ts_timeout),
|
||||
+ ETIMEDOUT);
|
||||
+
|
||||
+ xpthread_mutex_unlock (&mut);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ do_test_clock (CLOCK_MONOTONIC);
|
||||
+ do_test_clock (CLOCK_REALTIME);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
|
||||
index df049abf..7eb2decf 100644
|
||||
--- a/sysdeps/nptl/pthread.h
|
||||
+++ b/sysdeps/nptl/pthread.h
|
||||
@@ -1003,6 +1003,21 @@ extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
|
||||
const struct timespec *__restrict __abstime)
|
||||
__nonnull ((1, 2, 3));
|
||||
|
||||
+# ifdef __USE_GNU
|
||||
+/* Wait for condition variable COND to be signaled or broadcast until
|
||||
+ ABSTIME measured by the specified clock. MUTEX is assumed to be
|
||||
+ locked before. CLOCK is the clock to use. ABSTIME is an absolute
|
||||
+ time specification against CLOCK's epoch.
|
||||
+
|
||||
+ This function is a cancellation point and therefore not marked with
|
||||
+ __THROW. */
|
||||
+extern int pthread_cond_clockwait (pthread_cond_t *__restrict __cond,
|
||||
+ pthread_mutex_t *__restrict __mutex,
|
||||
+ __clockid_t __clock_id,
|
||||
+ const struct timespec *__restrict __abstime)
|
||||
+ __nonnull ((1, 2, 4));
|
||||
+# endif
|
||||
+
|
||||
/* Functions for handling condition variable attributes. */
|
||||
|
||||
/* Initialize condition variable attribute ATTR. */
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
|
||||
index 9a9e4cee..cd9f09fa 100644
|
||||
--- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
|
||||
@@ -235,6 +235,7 @@ GLIBC_2.28 mtx_lock F
|
||||
GLIBC_2.28 mtx_timedlock F
|
||||
GLIBC_2.28 mtx_trylock F
|
||||
GLIBC_2.28 mtx_unlock F
|
||||
+GLIBC_2.28 pthread_cond_clockwait F
|
||||
GLIBC_2.28 thrd_create F
|
||||
GLIBC_2.28 thrd_detach F
|
||||
GLIBC_2.28 thrd_exit F
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
|
||||
index 931c8277..8add10d7 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
|
||||
@@ -211,6 +211,7 @@ GLIBC_2.28 mtx_lock F
|
||||
GLIBC_2.28 mtx_timedlock F
|
||||
GLIBC_2.28 mtx_trylock F
|
||||
GLIBC_2.28 mtx_unlock F
|
||||
+GLIBC_2.28 pthread_cond_clockwait F
|
||||
GLIBC_2.28 thrd_create F
|
||||
GLIBC_2.28 thrd_detach F
|
||||
GLIBC_2.28 thrd_exit F
|
||||
--
|
||||
2.23.0
|
||||
|
||||
10
glibc.spec
10
glibc.spec
@ -59,7 +59,7 @@
|
||||
##############################################################################
|
||||
Name: glibc
|
||||
Version: 2.28
|
||||
Release: 64
|
||||
Release: 65
|
||||
Summary: The GNU libc libraries
|
||||
License: %{all_license}
|
||||
URL: http://www.gnu.org/software/glibc/
|
||||
@ -119,6 +119,9 @@ Patch35: backport-aarch64-revert-memcpy-optimze-for-kunpeng-to-avoid-p.patch
|
||||
Patch36: backport-elf-Allow-dlopen-of-filter-object-to-work-BZ-16272.patch
|
||||
Patch37: backport-elf-Fix-pldd-BZ-18035.patch
|
||||
Patch38: backport-CVE-2021-3326-gconv-Fix-assertion-failure-in-ISO-2022-JP-3-module-.patch
|
||||
Patch39: backport-0001-nptl-Add-clockid-parameter-to-futex-timed-wait-calls.patch
|
||||
Patch40: backport-0002-support-Add-timespec.h-xtime.h.patch
|
||||
Patch41: backport-0003-nptl-Add-POSIX-proposed-pthread_cond_clockwait.patch
|
||||
|
||||
Provides: ldconfig rtld(GNU_HASH) bundled(gnulib)
|
||||
|
||||
@ -1143,7 +1146,10 @@ fi
|
||||
%doc hesiod/README.hesiod
|
||||
|
||||
%changelog
|
||||
* Thu Mar 16 2021 zhujunhao<zhujunhao8@huawei.com> - 2.28-64
|
||||
* Wed Apr 21 2021 xuhuijie<xuhuijie2@huawei.com> - 2.28-65
|
||||
- Add POSIX-proposed pthread_cond_clockwait
|
||||
|
||||
* Tue Mar 16 2021 zhujunhao<zhujunhao8@huawei.com> - 2.28-64
|
||||
- Replace openeuler by vendor
|
||||
|
||||
* Mon Feb 8 2021 Wang Shuo<wangshuo_1994@foxmail.com> - 2.28-63
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user