summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2021-05-21 16:52:43 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2021-05-21 16:52:43 +0000
commit83b32a91c5bbc0f5765935f9dafe706e66051d95 (patch)
treed29a468871ba77b3f3655763fe3307cd339a788c /lib
parent71e2a8f174fc0fcaf9094cddb94e7eca873d683d (diff)
The implementation of the FUTEX_WAIT option in futex(2) is subtly broken.
Unfortunately libc and libpthread rely on the broken behaviour. Adjust the code in those libraries such that it works with both the old and the proposed new behaviour. The kernel changes that fix the issue will be committed in a week or so to give those who do their own builds a chance to update these libraries before we make the change. ok mpi@, deraadt@
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/thread/synch.h20
-rw-r--r--lib/librthread/synch.h20
2 files changed, 28 insertions, 12 deletions
diff --git a/lib/libc/thread/synch.h b/lib/libc/thread/synch.h
index aaeb965956a..91b5001c515 100644
--- a/lib/libc/thread/synch.h
+++ b/lib/libc/thread/synch.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: synch.h,v 1.5 2020/07/06 13:33:06 pirofti Exp $ */
+/* $OpenBSD: synch.h,v 1.6 2021/05/21 16:52:42 kettenis Exp $ */
/*
* Copyright (c) 2017 Martin Pieuchot
*
@@ -29,12 +29,17 @@ static inline int
_twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *abs)
{
struct timespec rel;
+ int error;
- if (abs == NULL)
- return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
+ if (abs == NULL) {
+ error = futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
+ if (error == -1)
+ error = errno;
+ return error;
+ }
if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid, &rel))
- return (EINVAL);
+ return EINVAL;
rel.tv_sec = abs->tv_sec - rel.tv_sec;
if ((rel.tv_nsec = abs->tv_nsec - rel.tv_nsec) < 0) {
@@ -42,9 +47,12 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
rel.tv_nsec += 1000000000;
}
if (rel.tv_sec < 0)
- return (ETIMEDOUT);
+ return ETIMEDOUT;
- return futex(p, FUTEX_WAIT_PRIVATE, val, &rel, NULL);
+ error = futex(p, FUTEX_WAIT_PRIVATE, val, &rel, NULL);
+ if (error == -1)
+ error = errno;
+ return error;
}
static inline int
diff --git a/lib/librthread/synch.h b/lib/librthread/synch.h
index 381ed1b1749..e5c623e87a0 100644
--- a/lib/librthread/synch.h
+++ b/lib/librthread/synch.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: synch.h,v 1.6 2019/10/24 12:32:18 sthen Exp $ */
+/* $OpenBSD: synch.h,v 1.7 2021/05/21 16:52:42 kettenis Exp $ */
/*
* Copyright (c) 2017 Martin Pieuchot
*
@@ -36,12 +36,17 @@ static inline int
_twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *abs)
{
struct timespec rel;
+ int error;
- if (abs == NULL)
- return futex(p, FUTEX_WAIT, val, NULL, NULL);
+ if (abs == NULL) {
+ error = futex(p, FUTEX_WAIT, val, NULL, NULL);
+ if (error == -1)
+ error = errno;
+ return error;
+ }
if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
- return (EINVAL);
+ return EINVAL;
rel.tv_sec = abs->tv_sec - rel.tv_sec;
if ((rel.tv_nsec = abs->tv_nsec - rel.tv_nsec) < 0) {
@@ -49,9 +54,12 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
rel.tv_nsec += 1000000000;
}
if (rel.tv_sec < 0)
- return (ETIMEDOUT);
+ return ETIMEDOUT;
- return futex(p, FUTEX_WAIT, val, &rel, NULL);
+ error = futex(p, FUTEX_WAIT, val, &rel, NULL);
+ if (error == -1)
+ error = errno;
+ return error;
}
static inline int