Skip to content

Commit 8b2bdfd

Browse files
committed
Improve std::sys::windows::compat.
- Module name can now be any string, not just an ident. (Not all Windows api modules are valid Rust identifiers.) - Adds c::FuncName::is_available() for checking if a function is really available without having to do a duplicate lookup. - Add comment explaining the lack of locking. - Use `$_:block` to simplify the macro_rules. - Apply allow(unused_variables) only to the fallback instead of everything.
1 parent d92d28e commit 8b2bdfd

File tree

2 files changed

+35
-28
lines changed

2 files changed

+35
-28
lines changed

library/std/src/sys/windows/c.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ extern "system" {
10321032
// Functions that aren't available on every version of Windows that we support,
10331033
// but we still use them and just provide some form of a fallback implementation.
10341034
compat_fn! {
1035-
kernel32:
1035+
"kernel32":
10361036

10371037
pub fn CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
10381038
_lpTargetFileName: LPCWSTR,

library/std/src/sys/windows/compat.rs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//! function is available but afterwards it's just a load and a jump.
1313
1414
use crate::ffi::CString;
15-
use crate::sync::atomic::{AtomicUsize, Ordering};
1615
use crate::sys::c;
1716

1817
pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
@@ -28,45 +27,53 @@ pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
2827
}
2928
}
3029

31-
pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str, fallback: usize) -> usize {
32-
let value = lookup(module, symbol).unwrap_or(fallback);
33-
ptr.store(value, Ordering::SeqCst);
34-
value
35-
}
36-
3730
macro_rules! compat_fn {
38-
($module:ident: $(
31+
($module:literal: $(
3932
$(#[$meta:meta])*
40-
pub fn $symbol:ident($($argname:ident: $argtype:ty),*)
41-
-> $rettype:ty {
42-
$($body:expr);*
43-
}
33+
pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $body:block
4434
)*) => ($(
45-
#[allow(unused_variables)]
4635
$(#[$meta])*
47-
pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
36+
pub mod $symbol {
37+
use super::*;
4838
use crate::sync::atomic::{AtomicUsize, Ordering};
4939
use crate::mem;
50-
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
5140

5241
static PTR: AtomicUsize = AtomicUsize::new(0);
5342

43+
#[allow(unused_variables)]
44+
unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype $body
45+
46+
#[cold]
5447
fn load() -> usize {
55-
crate::sys::compat::store_func(&PTR,
56-
stringify!($module),
57-
stringify!($symbol),
58-
fallback as usize)
48+
// There is no locking here. It's okay if this is executed by multiple threads in
49+
// parallel. `lookup` will result in the same value, and it's okay if they overwrite
50+
// eachothers result as long as they do so atomically. We don't need any guarantees
51+
// about memory ordering, as this involves just a single atomic variable which is
52+
// not used to protect or order anything else.
53+
let addr = crate::sys::compat::lookup($module, stringify!($symbol))
54+
.unwrap_or(fallback as usize);
55+
PTR.store(addr, Ordering::Relaxed);
56+
addr
5957
}
60-
unsafe extern "system" fn fallback($($argname: $argtype),*)
61-
-> $rettype {
62-
$($body);*
58+
59+
fn addr() -> usize {
60+
match PTR.load(Ordering::Relaxed) {
61+
0 => load(),
62+
addr => addr,
63+
}
6364
}
6465

65-
let addr = match PTR.load(Ordering::SeqCst) {
66-
0 => load(),
67-
n => n,
68-
};
69-
mem::transmute::<usize, F>(addr)($($argname),*)
66+
#[allow(dead_code)]
67+
pub fn is_available() -> bool {
68+
addr() != fallback as usize
69+
}
70+
71+
pub unsafe fn call($($argname: $argtype),*) -> $rettype {
72+
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
73+
mem::transmute::<usize, F>(addr())($($argname),*)
74+
}
7075
}
76+
77+
pub use $symbol::call as $symbol;
7178
)*)
7279
}

0 commit comments

Comments
 (0)