rusticl/memory: make closures Send and Sync

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27747>
This commit is contained in:
Karol Herbst 2024-02-21 15:54:54 +01:00 committed by Marge Bot
parent aa3b44c02b
commit a97108d3c7
2 changed files with 107 additions and 20 deletions

View file

@ -1060,6 +1060,8 @@ fn enqueue_read_buffer(
return Err(CL_INVALID_OPERATION);
}
// SAFETY: it's required that applications do not cause data races
let ptr = unsafe { MutMemoryPtr::from_ptr(ptr) };
create_and_queue(
q,
CL_COMMAND_READ_BUFFER,
@ -1113,6 +1115,8 @@ fn enqueue_write_buffer(
return Err(CL_INVALID_OPERATION);
}
// SAFETY: it's required that applications do not cause data races
let ptr = unsafe { ConstMemoryPtr::from_ptr(ptr) };
create_and_queue(
q,
CL_COMMAND_WRITE_BUFFER,
@ -1282,6 +1286,8 @@ fn enqueue_read_buffer_rect(
return Err(CL_INVALID_CONTEXT);
}
// SAFETY: it's required that applications do not cause data races
let ptr = unsafe { MutMemoryPtr::from_ptr(ptr) };
create_and_queue(
q,
CL_COMMAND_READ_BUFFER_RECT,
@ -1405,6 +1411,8 @@ fn enqueue_write_buffer_rect(
return Err(CL_INVALID_CONTEXT);
}
// SAFETY: it's required that applications do not cause data races
let ptr = unsafe { ConstMemoryPtr::from_ptr(ptr) };
create_and_queue(
q,
CL_COMMAND_WRITE_BUFFER_RECT,
@ -1670,7 +1678,7 @@ fn enqueue_map_buffer(
Box::new(move |q, ctx| b.sync_shadow(q, ctx, ptr)),
)?;
Ok(ptr)
Ok(ptr.as_ptr())
// TODO
// CL_MISALIGNED_SUB_BUFFER_OFFSET if buffer is a sub-buffer object and offset specified when the sub-buffer object is created is not aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for the device associated with queue. This error code is missing before version 1.1.
@ -1741,6 +1749,8 @@ fn enqueue_read_image(
slice_pitch = row_pitch * r[1];
}
// SAFETY: it's required that applications do not cause data races
let ptr = unsafe { MutMemoryPtr::from_ptr(ptr) };
create_and_queue(
q,
CL_COMMAND_READ_IMAGE,
@ -1819,6 +1829,8 @@ fn enqueue_write_image(
slice_pitch = row_pitch * r[1];
}
// SAFETY: it's required that applications do not cause data races
let ptr = unsafe { ConstMemoryPtr::from_ptr(ptr) };
create_and_queue(
q,
CL_COMMAND_WRITE_BUFFER_RECT,
@ -2118,13 +2130,15 @@ fn enqueue_map_image(
image_slice_pitch,
)?;
// SAFETY: it's required that applications do not cause data races
let sync_ptr = unsafe { MutMemoryPtr::from_ptr(ptr) };
create_and_queue(
q,
CL_COMMAND_MAP_IMAGE,
evs,
event,
block,
Box::new(move |q, ctx| i.sync_shadow(q, ctx, ptr)),
Box::new(move |q, ctx| i.sync_shadow(q, ctx, sync_ptr)),
)?;
Ok(ptr)
@ -2181,6 +2195,8 @@ fn enqueue_unmap_mem_object(
return Err(CL_INVALID_VALUE);
}
// SAFETY: it's required that applications do not cause data races
let mapped_ptr = unsafe { MutMemoryPtr::from_ptr(mapped_ptr) };
create_and_queue(
q,
CL_COMMAND_UNMAP_MEM_OBJECT,

View file

@ -111,6 +111,50 @@ impl Mappings {
}
}
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct ConstMemoryPtr {
ptr: *const c_void,
}
unsafe impl Send for ConstMemoryPtr {}
unsafe impl Sync for ConstMemoryPtr {}
impl ConstMemoryPtr {
pub fn as_ptr(&self) -> *const c_void {
self.ptr
}
/// # Safety
///
/// Users need to ensure that `ptr` is only accessed in a thread-safe manner sufficient for
/// [Send] and [Sync]
pub unsafe fn from_ptr(ptr: *const c_void) -> Self {
Self { ptr: ptr }
}
}
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct MutMemoryPtr {
ptr: *mut c_void,
}
unsafe impl Send for MutMemoryPtr {}
unsafe impl Sync for MutMemoryPtr {}
impl MutMemoryPtr {
pub fn as_ptr(&self) -> *mut c_void {
self.ptr
}
/// # Safety
///
/// Users need to ensure that `ptr` is only accessed in a thread-safe manner sufficient for
/// [Send] and [Sync]
pub unsafe fn from_ptr(ptr: *mut c_void) -> Self {
Self { ptr: ptr }
}
}
pub enum Mem {
Buffer(Arc<Buffer>),
Image(Arc<Image>),
@ -128,7 +172,7 @@ impl Deref for Mem {
}
impl Mem {
pub fn unmap(&self, q: &Queue, ctx: &PipeContext, ptr: *mut c_void) -> CLResult<()> {
pub fn unmap(&self, q: &Queue, ctx: &PipeContext, ptr: MutMemoryPtr) -> CLResult<()> {
match self {
Self::Buffer(b) => b.unmap(q, ctx, ptr),
Self::Image(i) => i.unmap(q, ctx, ptr),
@ -851,7 +895,7 @@ impl Buffer {
Ok(())
}
pub fn map(&self, dev: &'static Device, offset: usize) -> CLResult<*mut c_void> {
pub fn map(&self, dev: &'static Device, offset: usize) -> CLResult<MutMemoryPtr> {
let ptr = if self.has_user_shadow_buffer(dev)? {
self.host_ptr()
} else {
@ -868,7 +912,8 @@ impl Buffer {
};
let ptr = unsafe { ptr.add(offset) };
Ok(ptr)
// SAFETY: it's required that applications do not cause data races
Ok(unsafe { MutMemoryPtr::from_ptr(ptr) })
}
pub fn read(
@ -876,9 +921,10 @@ impl Buffer {
q: &Queue,
ctx: &PipeContext,
offset: usize,
ptr: *mut c_void,
ptr: MutMemoryPtr,
size: usize,
) -> CLResult<()> {
let ptr = ptr.as_ptr();
let tx = self.tx(q, ctx, offset, size, RWFlags::RD)?;
unsafe {
@ -890,7 +936,7 @@ impl Buffer {
pub fn read_rect(
&self,
dst: *mut c_void,
dst: MutMemoryPtr,
q: &Queue,
ctx: &PipeContext,
region: &CLVec<usize>,
@ -901,6 +947,7 @@ impl Buffer {
dst_row_pitch: usize,
dst_slice_pitch: usize,
) -> CLResult<()> {
let dst = dst.as_ptr();
let (offset, size) =
CLVec::calc_offset_size(src_origin, region, [1, src_row_pitch, src_slice_pitch]);
let tx = self.tx(q, ctx, offset, size, RWFlags::RD)?;
@ -922,14 +969,22 @@ impl Buffer {
}
// TODO: only sync on map when the memory is not mapped with discard
pub fn sync_shadow(&self, q: &Queue, ctx: &PipeContext, ptr: *mut c_void) -> CLResult<()> {
pub fn sync_shadow(&self, q: &Queue, ctx: &PipeContext, ptr: MutMemoryPtr) -> CLResult<()> {
let ptr = ptr.as_ptr();
let mut lock = self.maps.lock().unwrap();
if !lock.increase_ref(q.device, ptr) {
return Ok(());
}
if self.has_user_shadow_buffer(q.device)? {
self.read(q, ctx, 0, self.host_ptr(), self.size)
self.read(
q,
ctx,
0,
// SAFETY: it's required that applications do not cause data races
unsafe { MutMemoryPtr::from_ptr(self.host_ptr()) },
self.size,
)
} else {
if let Some(shadow) = lock.tx.get(&q.device).and_then(|tx| tx.shadow.as_ref()) {
let res = self.get_res_of_dev(q.device)?;
@ -998,7 +1053,8 @@ impl Buffer {
}
// TODO: only sync on unmap when the memory is not mapped for writing
pub fn unmap(&self, q: &Queue, ctx: &PipeContext, ptr: *mut c_void) -> CLResult<()> {
pub fn unmap(&self, q: &Queue, ctx: &PipeContext, ptr: MutMemoryPtr) -> CLResult<()> {
let ptr = ptr.as_ptr();
let mut lock = self.maps.lock().unwrap();
if !lock.contains_ptr(ptr) {
return Ok(());
@ -1017,7 +1073,14 @@ impl Buffer {
ctx.resource_copy_region(shadow, res, &[offset, 0, 0], &bx);
} else if self.has_user_shadow_buffer(q.device)? {
self.write(q, ctx, 0, self.host_ptr(), self.size)?;
self.write(
q,
ctx,
0,
// SAFETY: it's required that applications do not cause data races
unsafe { ConstMemoryPtr::from_ptr(self.host_ptr()) },
self.size,
)?;
}
}
@ -1031,9 +1094,10 @@ impl Buffer {
q: &Queue,
ctx: &PipeContext,
offset: usize,
ptr: *const c_void,
ptr: ConstMemoryPtr,
size: usize,
) -> CLResult<()> {
let ptr = ptr.as_ptr();
let offset = self.apply_offset(offset)?;
let r = self.get_res_of_dev(q.device)?;
ctx.buffer_subdata(
@ -1047,7 +1111,7 @@ impl Buffer {
pub fn write_rect(
&self,
src: *const c_void,
src: ConstMemoryPtr,
q: &Queue,
ctx: &PipeContext,
region: &CLVec<usize>,
@ -1058,6 +1122,7 @@ impl Buffer {
dst_row_pitch: usize,
dst_slice_pitch: usize,
) -> CLResult<()> {
let src = src.as_ptr();
let (offset, size) =
CLVec::calc_offset_size(dst_origin, region, [1, dst_row_pitch, dst_slice_pitch]);
let tx = self.tx(q, ctx, offset, size, RWFlags::WR)?;
@ -1302,7 +1367,7 @@ impl Image {
} else if let Some(Mem::Buffer(buffer)) = &self.parent {
*row_pitch = self.image_desc.image_row_pitch;
*slice_pitch = self.image_desc.image_slice_pitch;
buffer.map(dev, 0)?
buffer.map(dev, 0)?.as_ptr()
} else {
let mut lock = self.maps.lock().unwrap();
@ -1355,7 +1420,7 @@ impl Image {
pub fn read(
&self,
dst: *mut c_void,
dst: MutMemoryPtr,
q: &Queue,
ctx: &PipeContext,
region: &CLVec<usize>,
@ -1363,6 +1428,7 @@ impl Image {
dst_row_pitch: usize,
dst_slice_pitch: usize,
) -> CLResult<()> {
let dst = dst.as_ptr();
let pixel_size = self.image_format.pixel_size().unwrap();
let tx;
@ -1403,7 +1469,8 @@ impl Image {
}
// TODO: only sync on map when the memory is not mapped with discard
pub fn sync_shadow(&self, q: &Queue, ctx: &PipeContext, ptr: *mut c_void) -> CLResult<()> {
pub fn sync_shadow(&self, q: &Queue, ctx: &PipeContext, ptr: MutMemoryPtr) -> CLResult<()> {
let ptr = ptr.as_ptr();
let mut lock = self.maps.lock().unwrap();
if !lock.increase_ref(q.device, ptr) {
return Ok(());
@ -1411,7 +1478,8 @@ impl Image {
if self.has_user_shadow_buffer(q.device)? {
self.read(
self.host_ptr(),
// SAFETY: it's required that applications do not cause data races
unsafe { MutMemoryPtr::from_ptr(self.host_ptr()) },
q,
ctx,
&self.image_desc.size(),
@ -1482,7 +1550,8 @@ impl Image {
}
// TODO: only sync on unmap when the memory is not mapped for writing
pub fn unmap(&self, q: &Queue, ctx: &PipeContext, ptr: *mut c_void) -> CLResult<()> {
pub fn unmap(&self, q: &Queue, ctx: &PipeContext, ptr: MutMemoryPtr) -> CLResult<()> {
let ptr = ptr.as_ptr();
let mut lock = self.maps.lock().unwrap();
if !lock.contains_ptr(ptr) {
return Ok(());
@ -1496,7 +1565,8 @@ impl Image {
ctx.resource_copy_region(shadow, res, &[0, 0, 0], &bx);
} else if self.has_user_shadow_buffer(q.device)? {
self.write(
self.host_ptr(),
// SAFETY: it's required that applications do not cause data races
unsafe { ConstMemoryPtr::from_ptr(self.host_ptr()) },
q,
ctx,
&self.image_desc.size(),
@ -1514,7 +1584,7 @@ impl Image {
pub fn write(
&self,
src: *const c_void,
src: ConstMemoryPtr,
q: &Queue,
ctx: &PipeContext,
region: &CLVec<usize>,
@ -1522,6 +1592,7 @@ impl Image {
mut src_slice_pitch: usize,
dst_origin: &CLVec<usize>,
) -> CLResult<()> {
let src = src.as_ptr();
let dst_row_pitch = self.image_desc.image_row_pitch;
let dst_slice_pitch = self.image_desc.image_slice_pitch;