Work around potential merging/duplication issues in sys/windows/compat.
This commit is contained in:
parent
09cbaf4367
commit
63b6007d5b
|
@ -38,11 +38,28 @@ macro_rules! compat_fn {
|
||||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
|
||||||
|
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
|
||||||
|
|
||||||
static PTR: AtomicUsize = AtomicUsize::new(0);
|
static PTR: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype $body
|
unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype $body
|
||||||
|
|
||||||
|
/// This address is stored in `PTR` to incidate an unavailable API.
|
||||||
|
///
|
||||||
|
/// This way, call() will end up calling fallback() if it is unavailable.
|
||||||
|
///
|
||||||
|
/// This is a `static` to avoid rustc duplicating `fn fallback()`
|
||||||
|
/// into both load() and is_available(), which would break
|
||||||
|
/// is_available()'s comparison. By using the same static variable
|
||||||
|
/// in both places, they'll refer to the same (copy of the)
|
||||||
|
/// function.
|
||||||
|
///
|
||||||
|
/// LLVM merging the address of fallback with other functions
|
||||||
|
/// (because of unnamed_addr) is fine, since it's only compared to
|
||||||
|
/// an address from GetProcAddress from an external dll.
|
||||||
|
static FALLBACK: F = fallback;
|
||||||
|
|
||||||
#[cold]
|
#[cold]
|
||||||
fn load() -> usize {
|
fn load() -> usize {
|
||||||
// There is no locking here. It's okay if this is executed by multiple threads in
|
// There is no locking here. It's okay if this is executed by multiple threads in
|
||||||
|
@ -51,7 +68,7 @@ macro_rules! compat_fn {
|
||||||
// about memory ordering, as this involves just a single atomic variable which is
|
// about memory ordering, as this involves just a single atomic variable which is
|
||||||
// not used to protect or order anything else.
|
// not used to protect or order anything else.
|
||||||
let addr = crate::sys::compat::lookup($module, stringify!($symbol))
|
let addr = crate::sys::compat::lookup($module, stringify!($symbol))
|
||||||
.unwrap_or(fallback as usize);
|
.unwrap_or(FALLBACK as usize);
|
||||||
PTR.store(addr, Ordering::Relaxed);
|
PTR.store(addr, Ordering::Relaxed);
|
||||||
addr
|
addr
|
||||||
}
|
}
|
||||||
|
@ -65,11 +82,10 @@ macro_rules! compat_fn {
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn is_available() -> bool {
|
pub fn is_available() -> bool {
|
||||||
addr() != fallback as usize
|
addr() != FALLBACK as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn call($($argname: $argtype),*) -> $rettype {
|
pub unsafe fn call($($argname: $argtype),*) -> $rettype {
|
||||||
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
|
|
||||||
mem::transmute::<usize, F>(addr())($($argname),*)
|
mem::transmute::<usize, F>(addr())($($argname),*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue