diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 3cbb2f17be7..f871857dab6 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -161,6 +161,54 @@ pub unsafe fn write(dst: *mut T, src: T) { intrinsics::move_val_init(&mut *dst, src) } +/// Performs a volatile read of the value from `src` without moving it. This +/// leaves the memory in `src` unchanged. +/// +/// Volatile operations are intended to act on I/O memory, and are guaranteed +/// to not be elided or reordered by the compiler across other volatile +/// operations. See the LLVM documentation on [[volatile]]. +/// +/// [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses +/// +/// # Safety +/// +/// Beyond accepting a raw pointer, this is unsafe because it semantically +/// moves the value out of `src` without preventing further usage of `src`. +/// If `T` is not `Copy`, then care must be taken to ensure that the value at +/// `src` is not used before the data is overwritten again (e.g. with `write`, +/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use +/// because it will attempt to drop the value previously at `*src`. +#[inline] +#[unstable(feature = "volatile", reason = "recently added", issue = "31756")] +pub unsafe fn read_volatile(src: *const T) -> T { + intrinsics::volatile_load(src) +} + +/// Performs a volatile write of a memory location with the given value without +/// reading or dropping the old value. +/// +/// Volatile operations are intended to act on I/O memory, and are guaranteed +/// to not be elided or reordered by the compiler across other volatile +/// operations. See the LLVM documentation on [[volatile]]. +/// +/// [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses +/// +/// # Safety +/// +/// This operation is marked unsafe because it accepts a raw pointer. +/// +/// It does not drop the contents of `dst`. This is safe, but it could leak +/// allocations or resources, so care must be taken not to overwrite an object +/// that should be dropped. +/// +/// This is appropriate for initializing uninitialized memory, or overwriting +/// memory that has previously been `read` from. +#[inline] +#[unstable(feature = "volatile", reason = "recently added", issue = "31756")] +pub unsafe fn write_volatile(dst: *mut T, src: T) { + intrinsics::volatile_store(dst, src); +} + #[lang = "const_ptr"] impl *const T { /// Returns true if the pointer is null. diff --git a/src/test/run-make/volatile-intrinsics/main.rs b/src/test/run-make/volatile-intrinsics/main.rs index 6c6afdc1303..4d0d7672101 100644 --- a/src/test/run-make/volatile-intrinsics/main.rs +++ b/src/test/run-make/volatile-intrinsics/main.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(core_intrinsics)] +#![feature(core_intrinsics, volatile)] use std::intrinsics::{volatile_load, volatile_store}; +use std::ptr::{read_volatile, write_volatile}; pub fn main() { unsafe { @@ -18,4 +19,9 @@ pub fn main() { volatile_store(&mut i, 2); assert_eq!(volatile_load(&i), 2); } + unsafe { + let mut i : isize = 1; + write_volatile(&mut i, 2); + assert_eq!(read_volatile(&i), 2); + } }