summaryrefslogtreecommitdiff
path: root/devel/libdispatch/files/patch-src_shims_lock.c
blob: c267242cb840b3372a8b7c920a8671f93e66878c (plain) (blame)
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