Skip to content

Commit

Permalink
Do exactly what libstd does
Browse files Browse the repository at this point in the history
This means:
  - Relaxed Load
  - Release Store
  - Acquire fence when returning pointer

Signed-off-by: Joe Richey <joerichey@google.com>
  • Loading branch information
josephlr committed Jun 9, 2022
1 parent 66b9089 commit 2085d7d
Showing 1 changed file with 19 additions and 11 deletions.
30 changes: 19 additions & 11 deletions src/util_libc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::Error;
use core::{
num::NonZeroU32,
ptr::NonNull,
sync::atomic::{AtomicPtr, Ordering},
sync::atomic::{AtomicPtr, Ordering, fence},
};
use libc::c_void;

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

Expand Down

0 comments on commit 2085d7d

Please sign in to comment.