33 target_os = "android" ,
44 all( target_os = "emscripten" , target_feature = "atomics" ) ,
55 target_os = "openbsd" ,
6+ target_os = "netbsd" ,
67) ) ]
78
89use crate :: sync:: atomic:: AtomicU32 ;
910use crate :: time:: Duration ;
1011
12+ #[ cfg( target_os = "netbsd" ) ]
13+ pub const SYS___futex : i32 = 166 ;
14+
1115/// Wait for a futex_wake operation to wake us.
1216///
1317/// Returns directly if the futex doesn't hold the expected value.
1418///
1519/// 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" ) ) ]
1721pub fn futex_wait ( futex : & AtomicU32 , expected : u32 , timeout : Option < Duration > ) -> bool {
1822 use super :: time:: Timespec ;
1923 use crate :: ptr:: null;
@@ -34,15 +38,32 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
3438 // Use FUTEX_WAIT_BITSET rather than FUTEX_WAIT to be able to give an
3539 // absolute time rather than a relative time.
3640 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+ }
4667 } ;
4768
4869 match ( r < 0 ) . then ( super :: os:: errno) {
@@ -57,28 +78,34 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
5778///
5879/// Returns true if this actually woke up such a thread,
5980/// 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" ) ) ]
6182pub fn futex_wake ( futex : & AtomicU32 ) -> bool {
83+ let ptr = futex as * const AtomicU32 ;
84+ let op = libc:: FUTEX_WAKE | libc:: FUTEX_PRIVATE_FLAG ;
6285 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+ }
6993 }
7094}
7195
7296/// 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" ) ) ]
7498pub fn futex_wake_all ( futex : & AtomicU32 ) {
99+ let ptr = futex as * const AtomicU32 ;
100+ let op = libc:: FUTEX_WAKE | libc:: FUTEX_PRIVATE_FLAG ;
75101 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+ }
82109 }
83110}
84111
0 commit comments