]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/vxworks/weak.rs
vxworks: Remove Linux-specific comments.
[rust.git] / src / libstd / sys / vxworks / weak.rs
1 //! Support for "weak linkage" to symbols on Unix
2 //!
3 //! Some I/O operations we do in libstd require newer versions of OSes but we
4 //! need to maintain binary compatibility with older releases for now. In order
5 //! to use the new functionality when available we use this module for
6 //! detection.
7 //!
8 //! One option to use here is weak linkage, but that is unfortunately only
9 //! really workable on Linux. Hence, use dlsym to get the symbol value at
10 //! runtime. This is also done for compatibility with older versions of glibc,
11 //! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that
12 //! we've been dynamically linked to the library the symbol comes from, but that
13 //! is currently always the case for things like libpthread/libc.
14 //!
15 //! A long time ago this used weak linkage for the __pthread_get_minstack
16 //! symbol, but that caused Debian to detect an unnecessarily strict versioned
17 //! dependency on libc6 (#23628).
18
19 use crate::ffi::CStr;
20 use crate::marker;
21 use crate::mem;
22 use crate::sync::atomic::{AtomicUsize, Ordering};
23
24 pub struct Weak<F> {
25     name: &'static str,
26     addr: AtomicUsize,
27     _marker: marker::PhantomData<F>,
28 }
29
30 impl<F> Weak<F> {
31     pub const fn new(name: &'static str) -> Weak<F> {
32         Weak {
33             name,
34             addr: AtomicUsize::new(1),
35             _marker: marker::PhantomData,
36         }
37     }
38
39     pub fn get(&self) -> Option<F> {
40         assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
41         unsafe {
42             if self.addr.load(Ordering::SeqCst) == 1 {
43                 self.addr.store(fetch(self.name), Ordering::SeqCst);
44             }
45             match self.addr.load(Ordering::SeqCst) {
46                 0 => None,
47                 addr => Some(mem::transmute_copy::<usize, F>(&addr)),
48             }
49         }
50     }
51 }
52
53 unsafe fn fetch(name: &str) -> usize {
54     let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
55         Ok(cstr) => cstr,
56         Err(..) => return 0,
57     };
58     assert!(false, "FIXME: fetch");
59    libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
60 }