]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
1 | use std::marker; |
2 | use std::mem; | |
3 | use std::sync::atomic::{AtomicUsize, Ordering}; | |
4 | ||
5 | use libc; | |
6 | ||
7 | macro_rules! dlsym { | |
8 | (fn $name:ident($($t:ty),*) -> $ret:ty) => ( | |
9 | #[allow(bad_style)] | |
10 | static $name: ::sys::unix::dlsym::DlSym<unsafe extern fn($($t),*) -> $ret> = | |
11 | ::sys::unix::dlsym::DlSym { | |
12 | name: concat!(stringify!($name), "\0"), | |
13 | addr: ::std::sync::atomic::ATOMIC_USIZE_INIT, | |
14 | _marker: ::std::marker::PhantomData, | |
15 | }; | |
16 | ) | |
17 | } | |
18 | ||
19 | pub struct DlSym<F> { | |
20 | pub name: &'static str, | |
21 | pub addr: AtomicUsize, | |
22 | pub _marker: marker::PhantomData<F>, | |
23 | } | |
24 | ||
25 | impl<F> DlSym<F> { | |
26 | pub fn get(&self) -> Option<&F> { | |
27 | assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>()); | |
28 | unsafe { | |
29 | if self.addr.load(Ordering::SeqCst) == 0 { | |
30 | self.addr.store(fetch(self.name), Ordering::SeqCst); | |
31 | } | |
32 | if self.addr.load(Ordering::SeqCst) == 1 { | |
33 | None | |
34 | } else { | |
35 | mem::transmute::<&AtomicUsize, Option<&F>>(&self.addr) | |
36 | } | |
37 | } | |
38 | } | |
39 | } | |
40 | ||
41 | unsafe fn fetch(name: &str) -> usize { | |
42 | assert_eq!(name.as_bytes()[name.len() - 1], 0); | |
43 | match libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize { | |
44 | 0 => 1, | |
45 | n => n, | |
46 | } | |
47 | } |