From 2fb8bb3c4926a8d0bdc64a69642815c8f5dc4f09 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Wed, 11 Sep 2024 16:37:29 +0200 Subject: [PATCH] rusticl: move SVM allocation into core Reviewed-by: Adam Jackson Part-of: --- src/gallium/frontends/rusticl/api/memory.rs | 43 ++----------------- src/gallium/frontends/rusticl/core/context.rs | 41 ++++++++++++++++-- 2 files changed, 40 insertions(+), 44 deletions(-) diff --git a/src/gallium/frontends/rusticl/api/memory.rs b/src/gallium/frontends/rusticl/api/memory.rs index 065f9d00ab1..9ab6df9210a 100644 --- a/src/gallium/frontends/rusticl/api/memory.rs +++ b/src/gallium/frontends/rusticl/api/memory.rs @@ -19,8 +19,6 @@ use rusticl_opencl_gen::*; use rusticl_proc_macros::cl_entrypoint; use rusticl_proc_macros::cl_info_entrypoint; -use std::alloc; -use std::alloc::Layout; use std::cmp; use std::cmp::Ordering; use std::mem::{self, MaybeUninit}; @@ -2386,32 +2384,7 @@ pub fn svm_alloc( mem::size_of::<[u64; 16]>() }; - // clSVMAlloc will fail if alignment is not a power of two. - // `from_size_align()` verifies this condition is met. - let layout = Layout::from_size_align(size, alignment).or(Err(CL_INVALID_VALUE))?; - - // clSVMAlloc will fail if size is 0 or > CL_DEVICE_MAX_MEM_ALLOC_SIZE value - // for any device in context. - // Verify that the requested size, once adjusted to be a multiple of - // alignment, fits within the maximum allocation size. While - // `from_size_align()` ensures that the allocation will fit in host memory, - // the maximum allocation may be smaller due to limitations from gallium or - // devices. - let size_aligned = layout.pad_to_align().size(); - if size == 0 || checked_compare(size_aligned, Ordering::Greater, c.max_mem_alloc()) { - return Err(CL_INVALID_VALUE); - } - - // SAFETY: `size` is verified to be non-zero and the returned pointer is not - // expected to point to initialized memory. - let ptr = unsafe { alloc::alloc(layout) }; - - if ptr.is_null() { - return Err(CL_OUT_OF_HOST_MEMORY); - } - - c.add_svm_ptr(ptr as usize, layout); - Ok(ptr.cast()) + c.alloc_svm_ptr(size, alignment) // Values specified in flags do not follow rules described for supported values in the SVM Memory Flags table. // CL_MEM_SVM_FINE_GRAIN_BUFFER or CL_MEM_SVM_ATOMICS is specified in flags and these are not supported by at least one device in context. @@ -2420,19 +2393,9 @@ pub fn svm_alloc( // There was a failure to allocate resources. } -fn svm_free_impl(c: &Context, svm_pointer: usize) { - if let Some(layout) = c.remove_svm_ptr(svm_pointer) { - // SAFETY: we make sure that svm_pointer is a valid allocation and reuse the same layout - // from the allocation - unsafe { - alloc::dealloc(svm_pointer as *mut u8, layout); - } - } -} - pub fn svm_free(context: cl_context, svm_pointer: usize) -> CLResult<()> { let c = Context::ref_from_raw(context)?; - svm_free_impl(c, svm_pointer); + c.remove_svm_ptr(svm_pointer); Ok(()) } @@ -2493,7 +2456,7 @@ fn enqueue_svm_free_impl( cb.call(q, &mut svm_pointers); } else { for ptr in svm_pointers { - svm_free_impl(&q.context, ptr); + q.context.remove_svm_ptr(ptr); } } diff --git a/src/gallium/frontends/rusticl/core/context.rs b/src/gallium/frontends/rusticl/core/context.rs index c9a1dbf32e5..ee201ef3485 100644 --- a/src/gallium/frontends/rusticl/core/context.rs +++ b/src/gallium/frontends/rusticl/core/context.rs @@ -1,5 +1,6 @@ use crate::api::icd::*; use crate::api::types::DeleteContextCB; +use crate::api::util::checked_compare; use crate::core::device::*; use crate::core::format::*; use crate::core::gl::*; @@ -16,7 +17,9 @@ use mesa_rust_util::ptr::AllocSize; use mesa_rust_util::ptr::TrackedPointers; use rusticl_opencl_gen::*; +use std::alloc; use std::alloc::Layout; +use std::cmp::Ordering; use std::collections::HashMap; use std::convert::TryInto; use std::mem; @@ -207,8 +210,32 @@ impl Context { self.devs.iter().any(|dev| dev.svm_supported()) } - pub fn add_svm_ptr(&self, ptr: usize, layout: Layout) { - self.svm_ptrs.lock().unwrap().insert(ptr, layout); + pub fn alloc_svm_ptr(&self, size: usize, alignment: usize) -> CLResult<*mut c_void> { + // clSVMAlloc will fail if alignment is not a power of two. + // `from_size_align()` verifies this condition is met. + let layout = Layout::from_size_align(size, alignment).or(Err(CL_INVALID_VALUE))?; + + // clSVMAlloc will fail if size is 0 or > CL_DEVICE_MAX_MEM_ALLOC_SIZE value + // for any device in context. + // Verify that the requested size, once adjusted to be a multiple of + // alignment, fits within the maximum allocation size. While + // `from_size_align()` ensures that the allocation will fit in host memory, + // the maximum allocation may be smaller due to limitations from gallium or + // devices. + let size_aligned = layout.pad_to_align().size(); + if size == 0 || checked_compare(size_aligned, Ordering::Greater, self.max_mem_alloc()) { + return Err(CL_INVALID_VALUE); + } + + // SAFETY: `size` is verified to be non-zero and the returned pointer is not + // expected to point to initialized memory. + let ptr = unsafe { alloc::alloc(layout) }; + + if ptr.is_null() { + Err(CL_OUT_OF_HOST_MEMORY) + } else { + Ok(ptr.cast()) + } } pub fn find_svm_alloc(&self, ptr: usize) -> Option<(*const c_void, usize)> { @@ -219,8 +246,14 @@ impl Context { .map(|(ptr, layout)| (ptr as *const c_void, layout.size())) } - pub fn remove_svm_ptr(&self, ptr: usize) -> Option { - self.svm_ptrs.lock().unwrap().remove(ptr) + pub fn remove_svm_ptr(&self, ptr: usize) { + if let Some(layout) = self.svm_ptrs.lock().unwrap().remove(ptr) { + // SAFETY: we make sure that svm_pointer is a valid allocation and reuse the same layout + // from the allocation + unsafe { + alloc::dealloc(ptr as *mut u8, layout); + } + } } pub fn add_bda_ptr(&self, buffer: &Arc) {