diff --git a/src/lib.rs b/src/lib.rs index b97bdfd71c..692acf827a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,6 +67,7 @@ pub mod ld_so; pub mod out; pub mod platform; pub mod pthread; +pub mod raw_cell; pub mod start; pub mod sync; diff --git a/src/raw_cell.rs b/src/raw_cell.rs new file mode 100644 index 0000000000..cad0326210 --- /dev/null +++ b/src/raw_cell.rs @@ -0,0 +1,46 @@ +use core::cell::UnsafeCell; + +/// Wrapper over `UnsafeCell` that can directly be used in statics, where all modifications require +/// unsafe. +#[repr(transparent)] +pub struct RawCell { + inner: UnsafeCell, +} +impl RawCell { + #[inline] + pub const fn new(t: T) -> Self { + Self { + inner: UnsafeCell::new(t), + } + } + #[inline] + pub unsafe fn get(&self) -> T { + self.inner.get().read() + } + #[inline] + pub unsafe fn set(&self, t: T) { + self.inner.get().write(t) + } + #[inline] + pub fn as_mut_ptr(&self) -> *mut T { + self.inner.get() + } + #[inline] + pub fn get_mut(&mut self) -> &mut T { + self.inner.get_mut() + } + #[inline] + pub fn into_inner(self) -> T { + self.inner.into_inner() + } +} + +// SAFETY: Sync requires that no safe interface be allowed to act on &self in a way that is +// undefined behavior when accessed concurrently. The interface above only allows get, set, and +// as_mut_ptr, where the former two that access memory are unsafe anyway. +unsafe impl Sync for RawCell {} + +const _: () = { + // Check that RawCell works for non-Sync types. + static X: RawCell<*mut ()> = RawCell::new(core::ptr::null_mut()); +};