Module: Mesa
Branch: main
Commit: 572a96aa5943fcc6668e80e2ef0f5a5ba6c08f89
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=572a96aa5943fcc6668e80e2ef0f5a5ba6c08f89

Author: LingMan <[email protected]>
Date:   Fri Nov 10 02:09:44 2023 +0100

rusticl: Turn pointers in enqueue_svm_memcpy_impl into slices

Allows the closure to implement `Send` and `Sync`, which we want for `EventSig`.
Includes detailed documentation on the casts and unsafe operations.

Reviewed-by: Karol Herbst <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26157>

---

 src/gallium/frontends/rusticl/api/memory.rs | 34 ++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/src/gallium/frontends/rusticl/api/memory.rs 
b/src/gallium/frontends/rusticl/api/memory.rs
index dbe51e4812b..7221d0e13cb 100644
--- a/src/gallium/frontends/rusticl/api/memory.rs
+++ b/src/gallium/frontends/rusticl/api/memory.rs
@@ -2481,6 +2481,33 @@ fn enqueue_svm_memcpy_impl(
         return Err(CL_MEM_COPY_OVERLAP);
     }
 
+    // Not technically guaranteed by the OpenCL spec, but required by 
`from_raw_parts` below.
+    if isize::try_from(size).is_err()
+        || src_ptr_addr.checked_add(size).is_none()
+        || dst_ptr_addr.checked_add(size).is_none()
+    {
+        return Err(CL_INVALID_VALUE);
+    }
+
+    // CAST: We have no idea about the type or initialization status of these 
bytes.
+    // MaybeUninit<u8> is the safe bet.
+    let src_ptr = src_ptr.cast::<MaybeUninit<u8>>();
+
+    // CAST: We have no idea about the type or initialization status of these 
bytes.
+    // MaybeUninit<u8> is the safe bet.
+    let dst_ptr = dst_ptr.cast::<MaybeUninit<u8>>();
+
+    // SAFETY: We've checked above that the pointer is not NULL, that the size 
isn't excessive, and
+    // that addr + size doesn't overflow. It is up to the application to 
ensure the memory is valid
+    // to read for `size` bytes and that it doesn't modify it until the 
command has completed.
+    let src = unsafe { slice::from_raw_parts(src_ptr, size) };
+
+    // SAFETY: We've checked above that the pointer is not NULL, that the size 
isn't excessive, and
+    // that addr + size doesn't overflow. We've also ensured there's no 
aliasing between src and
+    // dst. It is up to the application to ensure the memory is valid to read 
and write for `size`
+    // bytes and that it doesn't modify or read from it until the command has 
completed.
+    let dst = unsafe { slice::from_raw_parts_mut(dst_ptr, size) };
+
     create_and_queue(
         q,
         cmd_type,
@@ -2488,12 +2515,7 @@ fn enqueue_svm_memcpy_impl(
         event,
         block,
         Box::new(move |_, _| {
-            // SAFETY: We check for overlapping copies already and alignment 
doesn't matter for void
-            // pointers. And we also trust applications to provide properly 
allocated memory regions
-            // and if not it's all undefined anyway.
-            unsafe {
-                ptr::copy_nonoverlapping(src_ptr, dst_ptr, size);
-            }
+            dst.copy_from_slice(src);
             Ok(())
         }),
     )

Reply via email to