A volatile read or write operation is intended for the case where your memory behaves like an IO device. For example, some chips might have specific locations in memory where writing to them has some effect such as turning on an LED, and the write therefore should not get optimized out even if the written value is never read.
Volatile operations are not intended for thread safety. That's the job of atomics. (note that volatile is intended for thread safety in some other languages such as Java)
Interesting ... so whether or not write_bytes or volatile_set_memory is needed depends on context. If I never want the optimization to occur, then volatile is needed. Would using a simple for loop, setting each pointee value to c ensure that the compiler won't optimize it out? Or, is volatile necessary?
Specifically, I need to zeroize memory on drop via memset(ptr, 0, len). I know I could just use the zeroize crate, but I'd prefer to be as lean as possible.
#[inline]
unsafe fn volatile_set<T: Copy + Sized>(dst: *mut T, src: T, count: usize) {
// TODO(tarcieri): use `volatile_set_memory` when stabilized
for i in 0..count {
// Safety:
//
// This is safe because there is room for at least `count` objects of type `T` in the
// allocation pointed to by `dst`, because `count <= isize::MAX` and because
// `dst.add(count)` must not wrap around the address space.
let ptr = dst.add(i);
// Safety:
//
// This is safe, because the pointer is valid and because `dst` is well aligned for `T` and
// `ptr` is an offset of `dst` by a multiple of `mem::size_of::<T>()` bytes.
ptr::write_volatile(ptr, src);
}
}