diff --git a/src/mem.rs b/src/mem.rs index be7849ff..76372d9b 100644 --- a/src/mem.rs +++ b/src/mem.rs @@ -5,7 +5,7 @@ type c_int = i16; #[cfg(not(target_pointer_width = "16"))] type c_int = i32; -use core::intrinsics::{atomic_load_unordered, atomic_store_unordered, unchecked_div}; +use core::intrinsics::{atomic_load_unordered, atomic_store_unordered, exact_div}; use core::mem; use core::ops::{BitOr, Shl}; @@ -63,9 +63,10 @@ pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { 0 } +// `bytes` must be a multiple of `mem::size_of::()` fn memcpy_element_unordered_atomic(dest: *mut T, src: *const T, bytes: usize) { unsafe { - let n = unchecked_div(bytes, mem::size_of::()); + let n = exact_div(bytes, mem::size_of::()); let mut i = 0; while i < n { atomic_store_unordered(dest.add(i), atomic_load_unordered(src.add(i))); @@ -74,9 +75,10 @@ fn memcpy_element_unordered_atomic(dest: *mut T, src: *const T, bytes: } } +// `bytes` must be a multiple of `mem::size_of::()` fn memmove_element_unordered_atomic(dest: *mut T, src: *const T, bytes: usize) { unsafe { - let n = unchecked_div(bytes, mem::size_of::()); + let n = exact_div(bytes, mem::size_of::()); if src < dest as *const T { // copy from end let mut i = n; @@ -95,18 +97,24 @@ fn memmove_element_unordered_atomic(dest: *mut T, src: *const T, bytes: } } +// `T` must be a primitive integer type, and `bytes` must be a multiple of `mem::size_of::()` fn memset_element_unordered_atomic(s: *mut T, c: u8, bytes: usize) where T: Copy + From + Shl + BitOr, { unsafe { - let n = unchecked_div(bytes, mem::size_of::()); + let n = exact_div(bytes, mem::size_of::()); + + // Construct a value of type `T` consisting of repeated `c` + // bytes, to let us ensure we write each `T` atomically. let mut x = T::from(c); let mut i = 1; while i < mem::size_of::() { x = x << 8 | T::from(c); i += 1; } + + // Write it to `s` let mut i = 0; while i < n { atomic_store_unordered(s.add(i), x);