Skip to content

Commit 9da64fc

Browse files
committed
Lock implementation changes for OpenBSD.
OpenBSD has futex, but not futex_pi. Segregate futex functionality from pi-futex functionality with a new preprocessor symbol. As the futex functionality on OpenBSD is not via a syscall interface, this necessitates refinements in error handling.
1 parent d5aeae7 commit 9da64fc

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

src/shims/lock.c

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ _dispatch_thread_switch(dispatch_lock value, dispatch_lock_options_t flags,
5656
#endif
5757
#endif
5858

59+
#if defined(__unix__)
60+
DISPATCH_ALWAYS_INLINE
61+
static inline void
62+
_dispatch_thread_switch(dispatch_lock value, dispatch_lock_options_t flags,
63+
uint32_t timeout)
64+
{
65+
(void)value;
66+
(void)flags;
67+
(void)timeout;
68+
}
69+
#endif
70+
5971
#pragma mark - semaphores
6072

6173
#if USE_MACH_SEM
@@ -394,8 +406,10 @@ _dispatch_unfair_lock_wake(uint32_t *uaddr, uint32_t flags)
394406
#include <sys/time.h>
395407
#ifdef __ANDROID__
396408
#include <sys/syscall.h>
397-
#else
409+
#elif __linux__
398410
#include <syscall.h>
411+
#else
412+
#include <sys/futex.h>
399413
#endif /* __ANDROID__ */
400414

401415
DISPATCH_ALWAYS_INLINE
@@ -404,7 +418,12 @@ _dispatch_futex(uint32_t *uaddr, int op, uint32_t val,
404418
const struct timespec *timeout, uint32_t *uaddr2, uint32_t val3,
405419
int opflags)
406420
{
421+
#if __linux__
407422
return (int)syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
423+
#else
424+
(void)val3;
425+
return futex(uaddr, op | opflags, (int)val, timeout, uaddr2);
426+
#endif
408427
}
409428

410429
// returns 0, ETIMEDOUT, EFAULT, EINTR, EWOULDBLOCK
@@ -414,11 +433,15 @@ _futex_blocking_op(uint32_t *uaddr, int futex_op, uint32_t val,
414433
const struct timespec *timeout, int flags)
415434
{
416435
for (;;) {
417-
int rc = _dispatch_futex(uaddr, futex_op, val, timeout, NULL, 0, flags);
418-
if (!rc) {
436+
int err = _dispatch_futex(uaddr, futex_op, val, timeout, NULL, 0, flags);
437+
if (!err) {
419438
return 0;
420439
}
421-
switch (errno) {
440+
#if __linux__
441+
// syscall sets errno to communicate error code.
442+
err = errno
443+
#endif
444+
switch (err) {
422445
case EINTR:
423446
/*
424447
* 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 opflags)
454477
DISPATCH_INTERNAL_CRASH(errno, "_dlock_wake() failed");
455478
}
456479

480+
#if HAVE_FUTEX_PI
457481
static void
458482
_dispatch_futex_lock_pi(uint32_t *uaddr, struct timespec *timeout, int detect,
459483
int opflags)
@@ -471,6 +495,7 @@ _dispatch_futex_unlock_pi(uint32_t *uaddr, int opflags)
471495
if (rc == 0) return;
472496
DISPATCH_CLIENT_CRASH(errno, "futex_unlock_pi() failed");
473497
}
498+
#endif
474499

475500
#endif
476501
#pragma mark - wait for address
@@ -599,7 +624,7 @@ _dispatch_unfair_lock_lock_slow(dispatch_unfair_lock_t dul,
599624
}
600625
}
601626
}
602-
#elif HAVE_FUTEX
627+
#elif HAVE_FUTEX_PI
603628
void
604629
_dispatch_unfair_lock_lock_slow(dispatch_unfair_lock_t dul,
605630
dispatch_lock_options_t flags)
@@ -636,7 +661,7 @@ _dispatch_unfair_lock_unlock_slow(dispatch_unfair_lock_t dul, dispatch_lock cur)
636661
if (_dispatch_lock_has_waiters(cur)) {
637662
_dispatch_unfair_lock_wake(&dul->dul_lock, 0);
638663
}
639-
#elif HAVE_FUTEX
664+
#elif HAVE_FUTEX_PI
640665
// futex_unlock_pi() handles both OWNER_DIED which we abuse & WAITERS
641666
_dispatch_futex_unlock_pi(&dul->dul_lock, FUTEX_PRIVATE_FLAG);
642667
#else

src/shims/lock.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,25 @@ _dispatch_lock_owner(dispatch_lock lock_value)
100100
return lock_value & DLOCK_OWNER_MASK;
101101
}
102102

103+
#elif defined(__OpenBSD__)
104+
105+
typedef uint32_t dispatch_tid;
106+
typedef uint32_t dispatch_lock;
107+
108+
#define DLOCK_OWNER_NULL ((dispatch_tid)0)
109+
#define DLOCK_OWNER_MASK ((dispatch_lock)0xfffffffc)
110+
#define DLOCK_WAITERS_BIT ((dispatch_lock)0x00000001)
111+
#define DLOCK_FAILED_TRYLOCK_BIT ((dispatch_lock)0x00000002)
112+
113+
#define _dispatch_tid_self() ((dispatch_tid)(_dispatch_get_tsd_base()->tid))
114+
115+
DISPATCH_ALWAYS_INLINE
116+
static inline dispatch_tid
117+
_dispatch_lock_owner(dispatch_lock lock_value)
118+
{
119+
return lock_value & DLOCK_OWNER_MASK;
120+
}
121+
103122
#else
104123
# error define _dispatch_lock encoding scheme for your platform here
105124
#endif
@@ -167,10 +186,15 @@ _dispatch_lock_has_failed_trylock(dispatch_lock lock_value)
167186
#endif
168187

169188
#ifndef HAVE_FUTEX
170-
#ifdef __linux__
189+
#if defined(__linux__)
190+
#define HAVE_FUTEX 1
191+
#define HAVE_FUTEX_PI 1
192+
#elif defined(__OpenBSD__)
171193
#define HAVE_FUTEX 1
194+
#define HAVE_FUTEX_PI 0
172195
#else
173196
#define HAVE_FUTEX 0
197+
#define HAVE_FUTEX_PI 0
174198
#endif
175199
#endif // HAVE_FUTEX
176200

0 commit comments

Comments
 (0)