about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-02-21 00:56:08 +0000
committerbors <bors@rust-lang.org>2016-02-21 00:56:08 +0000
commita2fb48e9f76aabd543e4f6352ac32109e09fab22 (patch)
treeeab0306c3ac87aa48fa4d8c2bbab528b377014c8
parentc894ff6b1249fc59ce583054011cf5966c6fcc97 (diff)
parent3b67e467b26d54111da36c7af62fbfdbf611ebe3 (diff)
downloadrust-a2fb48e9f76aabd543e4f6352ac32109e09fab22.tar.gz
rust-a2fb48e9f76aabd543e4f6352ac32109e09fab22.zip
Auto merge of #31761 - Amanieu:volatile, r=alexcrichton
Tracking issue: #31756
RFC: rust-lang/rfcs#1467

I've made these unstable for now. Should they be stabilized straight away since we've had plenty of experience with people using the unstable intrinsics?
-rw-r--r--src/libcore/ptr.rs48
-rw-r--r--src/test/run-make/volatile-intrinsics/main.rs8
2 files changed, 55 insertions, 1 deletions
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<T>(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<T>(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<T>(dst: *mut T, src: T) {
+    intrinsics::volatile_store(dst, src);
+}
+
 #[lang = "const_ptr"]
 impl<T: ?Sized> *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);
+    }
 }