Skip to content

Commit 0b03f3d

Browse files
committed
Do exactly what libstd does
This means: - Relaxed Load - Release Store - Acquire fence when returning pointer Signed-off-by: Joe Richey <[email protected]>
1 parent 66b9089 commit 0b03f3d

File tree

1 file changed

+19
-11
lines changed

1 file changed

+19
-11
lines changed

src/util_libc.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::Error;
1010
use core::{
1111
num::NonZeroU32,
1212
ptr::NonNull,
13-
sync::atomic::{AtomicPtr, Ordering},
13+
sync::atomic::{fence, AtomicPtr, Ordering},
1414
};
1515
use libc::c_void;
1616

@@ -113,17 +113,25 @@ impl Weak {
113113
// dlsym function may be called multiple times.
114114
pub fn ptr(&self) -> Option<NonNull<c_void>> {
115115
// Despite having only a single atomic variable (self.addr), we still
116-
// need a "consume" ordering as we will generally be reading though
117-
// this value (by calling the function we dlsym'ed). Rust lacks this
118-
// ordering, so we have to go with the next strongest: Acquire/Release.
119-
// As noted in libstd, this might be unnecessary.
120-
let mut addr = self.addr.load(Ordering::Acquire);
121-
if addr == Self::UNINIT {
122-
let symbol = self.name.as_ptr() as *const _;
123-
addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, symbol) };
124-
self.addr.store(addr, Ordering::Release);
116+
// cannot always use Ordering::Relaxed, as we need to make sure a
117+
// successful call to dlsym() is "ordered before" any data read through
118+
// the returned pointer (which occurs when the function is called).
119+
// Our implementation mirrors that of the one in libstd, meaning that
120+
// the use of non-Relaxed operations is probably unnecessary.
121+
match self.addr.load(Ordering::Relaxed) {
122+
Self::UNINIT => {
123+
let symbol = self.name.as_ptr() as *const _;
124+
let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, symbol) };
125+
// Synchronizes with the Acquire fence below
126+
self.addr.store(addr, Ordering::Release);
127+
NonNull::new(addr)
128+
}
129+
addr => {
130+
let func = NonNull::new(addr)?;
131+
fence(Ordering::Acquire);
132+
Some(func)
133+
}
125134
}
126-
NonNull::new(addr)
127135
}
128136
}
129137

0 commit comments

Comments
 (0)