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
|
--- src/shims/lock.c.orig 2021-09-17 04:54:52 UTC
+++ src/shims/lock.c
@@ -56,6 +56,18 @@ _dispatch_thread_switch(dispatch_lock value, dispatch_
#endif
#endif
+#if defined(__unix__)
+DISPATCH_ALWAYS_INLINE
+static inline void
+_dispatch_thread_switch(dispatch_lock value, dispatch_lock_options_t flags,
+ uint32_t timeout)
+{
+ (void)value;
+ (void)flags;
+ (void)timeout;
+}
+#endif
+
#pragma mark - semaphores
#if USE_MACH_SEM
@@ -394,8 +406,10 @@ _dispatch_unfair_lock_wake(uint32_t *uaddr, uint32_t f
#include <sys/time.h>
#ifdef __ANDROID__
#include <sys/syscall.h>
-#else
+#elif __linux__
#include <syscall.h>
+#else
+#include <sys/futex.h>
#endif /* __ANDROID__ */
DISPATCH_ALWAYS_INLINE
@@ -404,7 +418,12 @@ _dispatch_futex(uint32_t *uaddr, int op, uint32_t val,
const struct timespec *timeout, uint32_t *uaddr2, uint32_t val3,
int opflags)
{
+#if __linux__
return (int)syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
+#else
+ (void)val3;
+ return futex(uaddr, op | opflags, (int)val, timeout, uaddr2);
+#endif
}
// returns 0, ETIMEDOUT, EFAULT, EINTR, EWOULDBLOCK
@@ -414,11 +433,15 @@ _futex_blocking_op(uint32_t *uaddr, int futex_op, uint
const struct timespec *timeout, int flags)
{
for (;;) {
- int rc = _dispatch_futex(uaddr, futex_op, val, timeout, NULL, 0, flags);
- if (!rc) {
+ int err = _dispatch_futex(uaddr, futex_op, val, timeout, NULL, 0, flags);
+ if (!err) {
return 0;
}
- switch (errno) {
+#if __linux__
+ // syscall sets errno to communicate error code.
+ err = errno
+#endif
+ switch (err) {
case EINTR:
/*
* if we have a timeout, we need to return for the caller to
@@ -454,6 +477,7 @@ _dispatch_futex_wake(uint32_t *uaddr, int wake, int op
DISPATCH_INTERNAL_CRASH(errno, "_dlock_wake() failed");
}
+#if HAVE_FUTEX_PI
static void
_dispatch_futex_lock_pi(uint32_t *uaddr, struct timespec *timeout, int detect,
int opflags)
@@ -471,6 +495,7 @@ _dispatch_futex_unlock_pi(uint32_t *uaddr, int opflags
if (rc == 0) return;
DISPATCH_CLIENT_CRASH(errno, "futex_unlock_pi() failed");
}
+#endif
#endif
#pragma mark - wait for address
@@ -509,6 +534,19 @@ _dispatch_wait_on_address(uint32_t volatile *_address,
return _dispatch_futex_wait(address, value, NULL, FUTEX_PRIVATE_FLAG);
#elif defined(_WIN32)
return WaitOnAddress(address, &value, sizeof(value), INFINITE) == TRUE;
+#elif defined(__FreeBSD__)
+ uint64_t usecs = 0;
+ int rc;
+ if (nsecs == DISPATCH_TIME_FOREVER) {
+ return _dispatch_ulock_wait(address, value, 0, flags);
+ }
+ do {
+ usecs = howmany(nsecs, NSEC_PER_USEC);
+ if (usecs > UINT32_MAX) usecs = UINT32_MAX;
+ rc = _dispatch_ulock_wait(address, value, (uint32_t)usecs, flags);
+ } while (usecs == UINT32_MAX && rc == ETIMEDOUT &&
+ (nsecs = _dispatch_timeout(timeout)) != 0);
+ return rc;
#else
#error _dispatch_wait_on_address unimplemented for this platform
#endif
@@ -599,7 +637,7 @@ _dispatch_unfair_lock_lock_slow(dispatch_unfair_lock_t
}
}
}
-#elif HAVE_FUTEX
+#elif HAVE_FUTEX_PI
void
_dispatch_unfair_lock_lock_slow(dispatch_unfair_lock_t dul,
dispatch_lock_options_t flags)
@@ -636,7 +674,7 @@ _dispatch_unfair_lock_unlock_slow(dispatch_unfair_lock
if (_dispatch_lock_has_waiters(cur)) {
_dispatch_unfair_lock_wake(&dul->dul_lock, 0);
}
-#elif HAVE_FUTEX
+#elif HAVE_FUTEX_PI
// futex_unlock_pi() handles both OWNER_DIED which we abuse & WAITERS
_dispatch_futex_unlock_pi(&dul->dul_lock, FUTEX_PRIVATE_FLAG);
#else
|