3
3
target_os = "android" ,
4
4
all( target_os = "emscripten" , target_feature = "atomics" ) ,
5
5
target_os = "openbsd" ,
6
+ target_os = "netbsd" ,
6
7
) ) ]
7
8
8
9
use crate :: sync:: atomic:: AtomicU32 ;
9
10
use crate :: time:: Duration ;
10
11
12
+ #[ cfg( target_os = "netbsd" ) ]
13
+ pub const SYS___futex : i32 = 166 ;
14
+
11
15
/// Wait for a futex_wake operation to wake us.
12
16
///
13
17
/// Returns directly if the futex doesn't hold the expected value.
14
18
///
15
19
/// Returns false on timeout, and true in all other cases.
16
- #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
20
+ #[ cfg( any( target_os = "linux" , target_os = "android" , target_os = "netbsd" ) ) ]
17
21
pub fn futex_wait ( futex : & AtomicU32 , expected : u32 , timeout : Option < Duration > ) -> bool {
18
22
use super :: time:: Timespec ;
19
23
use crate :: ptr:: null;
@@ -34,15 +38,32 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
34
38
// Use FUTEX_WAIT_BITSET rather than FUTEX_WAIT to be able to give an
35
39
// absolute time rather than a relative time.
36
40
let r = unsafe {
37
- libc:: syscall (
38
- libc:: SYS_futex ,
39
- futex as * const AtomicU32 ,
40
- libc:: FUTEX_WAIT_BITSET | libc:: FUTEX_PRIVATE_FLAG ,
41
- expected,
42
- timespec. as_ref ( ) . map_or ( null ( ) , |t| & t. t as * const libc:: timespec ) ,
43
- null :: < u32 > ( ) , // This argument is unused for FUTEX_WAIT_BITSET.
44
- !0u32 , // A full bitmask, to make it behave like a regular FUTEX_WAIT.
45
- )
41
+ cfg_if:: cfg_if! {
42
+ if #[ cfg( target_os = "netbsd" ) ] {
43
+ // Netbsd's futex syscall takes addr2 and val2 as separate arguments.
44
+ // (Both are unused for FUTEX_WAIT[_BITSET].)
45
+ libc:: syscall(
46
+ SYS___futex ,
47
+ futex as * const AtomicU32 ,
48
+ libc:: FUTEX_WAIT_BITSET | libc:: FUTEX_PRIVATE_FLAG ,
49
+ expected,
50
+ timespec. as_ref( ) . map_or( null( ) , |t| & t. t as * const libc:: timespec) ,
51
+ null:: <u32 >( ) , // addr2: This argument is unused for FUTEX_WAIT_BITSET.
52
+ 0 , // val2: This argument is unused for FUTEX_WAIT_BITSET.
53
+ !0u32 , // val3 / bitmask: A full bitmask, to make it behave like a regular FUTEX_WAIT.
54
+ )
55
+ } else {
56
+ libc:: syscall(
57
+ libc:: SYS_futex ,
58
+ futex as * const AtomicU32 ,
59
+ libc:: FUTEX_WAIT_BITSET | libc:: FUTEX_PRIVATE_FLAG ,
60
+ expected,
61
+ timespec. as_ref( ) . map_or( null( ) , |t| & t. t as * const libc:: timespec) ,
62
+ null:: <u32 >( ) , // This argument is unused for FUTEX_WAIT_BITSET.
63
+ !0u32 , // A full bitmask, to make it behave like a regular FUTEX_WAIT.
64
+ )
65
+ }
66
+ }
46
67
} ;
47
68
48
69
match ( r < 0 ) . then ( super :: os:: errno) {
@@ -57,28 +78,34 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
57
78
///
58
79
/// Returns true if this actually woke up such a thread,
59
80
/// or false if no thread was waiting on this futex.
60
- #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
81
+ #[ cfg( any( target_os = "linux" , target_os = "android" , target_os = "netbsd" ) ) ]
61
82
pub fn futex_wake ( futex : & AtomicU32 ) -> bool {
83
+ let ptr = futex as * const AtomicU32 ;
84
+ let op = libc:: FUTEX_WAKE | libc:: FUTEX_PRIVATE_FLAG ;
62
85
unsafe {
63
- libc:: syscall (
64
- libc:: SYS_futex ,
65
- futex as * const AtomicU32 ,
66
- libc:: FUTEX_WAKE | libc:: FUTEX_PRIVATE_FLAG ,
67
- 1 ,
68
- ) > 0
86
+ cfg_if:: cfg_if! {
87
+ if #[ cfg( target_os = "netbsd" ) ] {
88
+ libc:: syscall( SYS___futex , ptr, op, 1 ) > 0
89
+ } else {
90
+ libc:: syscall( libc:: SYS_futex , ptr, op, 1 ) > 0
91
+ }
92
+ }
69
93
}
70
94
}
71
95
72
96
/// Wake up all threads that are waiting on futex_wait on this futex.
73
- #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
97
+ #[ cfg( any( target_os = "linux" , target_os = "android" , target_os = "netbsd" ) ) ]
74
98
pub fn futex_wake_all ( futex : & AtomicU32 ) {
99
+ let ptr = futex as * const AtomicU32 ;
100
+ let op = libc:: FUTEX_WAKE | libc:: FUTEX_PRIVATE_FLAG ;
75
101
unsafe {
76
- libc:: syscall (
77
- libc:: SYS_futex ,
78
- futex as * const AtomicU32 ,
79
- libc:: FUTEX_WAKE | libc:: FUTEX_PRIVATE_FLAG ,
80
- i32:: MAX ,
81
- ) ;
102
+ cfg_if:: cfg_if! {
103
+ if #[ cfg( target_os = "netbsd" ) ] {
104
+ libc:: syscall( SYS___futex , ptr, op, i32 :: MAX ) ;
105
+ } else {
106
+ libc:: syscall( libc:: SYS_futex , ptr, op, i32 :: MAX ) ;
107
+ }
108
+ }
82
109
}
83
110
}
84
111
0 commit comments