1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
Description: use __NR_futex_time64 on 32-bit architectures
Many thanks to Arnd Bergmann for the detailed explanation regarding
timespec, libc, musl, and the futex syscall on 32-bit architectures,
and for the basis of the patch.
Author: tony mancill <tmancill@debian.org>
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1067916
Forwarded: no
--- a/src/kj/mutex.c++
+++ b/src/kj/mutex.c++
@@ -37,15 +37,11 @@
#include <linux/futex.h>
#include <limits.h>
-#ifndef SYS_futex
-// Missing on Android/Bionic.
-#ifdef __NR_futex
-#define SYS_futex __NR_futex
-#elif defined(SYS_futex_time64)
-#define SYS_futex SYS_futex_time64
+// see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1067916
+#if defined(__USE_TIME_BITS64) && (__BITS_PER_LONG == 32)
+#define MY_FUTEX __NR_futex_time64
#else
-#error "Need working SYS_futex"
-#endif
+#define MY_FUTEX __NR_futex
#endif
#ifndef FUTEX_WAIT_PRIVATE
@@ -247,7 +243,7 @@
setCurrentThreadIsWaitingFor(&blockReason);
- auto result = syscall(SYS_futex, &futex, FUTEX_WAIT_PRIVATE, state, specp, nullptr, 0);
+ auto result = syscall(MY_FUTEX, &futex, FUTEX_WAIT_PRIVATE, state, specp, nullptr, 0);
if (result < 0) {
if (errno == ETIMEDOUT) {
setCurrentThreadIsNoLongerWaiting();
@@ -288,7 +284,7 @@
// The mutex is exclusively locked by another thread. Since we incremented the counter
// already, we just have to wait for it to be unlocked.
- auto result = syscall(SYS_futex, &futex, FUTEX_WAIT_PRIVATE, state, specp, nullptr, 0);
+ auto result = syscall(MY_FUTEX, &futex, FUTEX_WAIT_PRIVATE, state, specp, nullptr, 0);
if (result < 0) {
// If we timeout though, we need to signal that we're not waiting anymore.
if (errno == ETIMEDOUT) {
@@ -302,7 +298,7 @@
&futex, &state, 0, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
// Wake all exclusive waiters. We have to wake all of them because one of them will
// grab the lock while the others will re-establish the exclusive-requested bit.
- syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
+ syscall(MY_FUTEX, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
}
}
return false;
@@ -382,7 +378,7 @@
} else {
__atomic_store_n(&waiter->futex, 1, __ATOMIC_RELEASE);
}
- syscall(SYS_futex, &waiter->futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
+ syscall(MY_FUTEX, &waiter->futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
// We transferred ownership of the lock to this waiter, so we're done now.
return;
@@ -414,7 +410,7 @@
// the lock, and we must wake them up. If there are any exclusive waiters, we must wake
// them up even if readers are waiting so that at the very least they may re-establish the
// EXCLUSIVE_REQUESTED bit that we just removed.
- syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
+ syscall(MY_FUTEX, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
#ifdef KJ_CONTENTION_WARNING_THRESHOLD
if (readerCount >= KJ_CONTENTION_WARNING_THRESHOLD) {
@@ -437,7 +433,7 @@
&futex, &state, 0, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
// Wake all exclusive waiters. We have to wake all of them because one of them will
// grab the lock while the others will re-establish the exclusive-requested bit.
- syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
+ syscall(MY_FUTEX, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
}
}
break;
@@ -496,7 +492,7 @@
// FUTEX_WAIT_PRIVATE except that the timeout is specified as an absolute time based on
// CLOCK_MONOTONIC. Otherwise, FUTEX_WAIT_PRIVATE interprets it as a relative time, forcing
// us to recompute the time after every iteration.
- KJ_SYSCALL_HANDLE_ERRORS(syscall(SYS_futex,
+ KJ_SYSCALL_HANDLE_ERRORS(syscall(MY_FUTEX,
&waiter.futex, FUTEX_WAIT_BITSET_PRIVATE, 0, tsp, nullptr, FUTEX_BITSET_MATCH_ANY)) {
case EAGAIN:
// Indicates that the futex was already non-zero by the time the kernel looked at it.
@@ -558,7 +554,7 @@
for (;;) {
KJ_IF_MAYBE(waiter, nextWaiter) {
nextWaiter = waiter->next;
- syscall(SYS_futex, &waiter->futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
+ syscall(MY_FUTEX, &waiter->futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
} else {
// No more waiters.
break;
@@ -583,7 +579,7 @@
if (__atomic_exchange_n(&futex, UNINITIALIZED, __ATOMIC_RELEASE) ==
INITIALIZING_WITH_WAITERS) {
// Someone was waiting for us to finish.
- syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
+ syscall(MY_FUTEX, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
}
});
@@ -592,7 +588,7 @@
if (__atomic_exchange_n(&futex, INITIALIZED, __ATOMIC_RELEASE) ==
INITIALIZING_WITH_WAITERS) {
// Someone was waiting for us to finish.
- syscall(SYS_futex, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
+ syscall(MY_FUTEX, &futex, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr, 0);
}
} else {
BlockedOnReason blockReason = BlockedOnOnceInit{*this, location};
@@ -614,7 +610,7 @@
// Wait for initialization.
setCurrentThreadIsWaitingFor(&blockReason);
- syscall(SYS_futex, &futex, FUTEX_WAIT_PRIVATE, INITIALIZING_WITH_WAITERS,
+ syscall(MY_FUTEX, &futex, FUTEX_WAIT_PRIVATE, INITIALIZING_WITH_WAITERS,
nullptr, nullptr, 0);
state = __atomic_load_n(&futex, __ATOMIC_ACQUIRE);
|