Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions src/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,10 @@ impl ShmBuffer {
fn alloc_segment(
&mut self,
conn: &impl Connection,
size: usize,
buffer_size: usize,
) -> Result<(), PushBufferError> {
// Round the size up to the next power of two to prevent frequent reallocations.
let size = size.next_power_of_two();
let size = buffer_size.next_power_of_two();

// Get the size of the segment currently in use.
let needs_realloc = match self.seg {
Expand All @@ -435,8 +435,10 @@ impl ShmBuffer {

// Reallocate if necessary.
if needs_realloc {
let new_seg = ShmSegment::new(size)?;
let new_seg = ShmSegment::new(size, buffer_size)?;
self.associate(conn, new_seg)?;
} else if let Some((ref mut seg, _)) = self.seg {
seg.set_buffer_size(buffer_size);
}

Ok(())
Expand All @@ -451,8 +453,10 @@ impl ShmBuffer {
unsafe fn as_ref(&self) -> &[u32] {
match self.seg.as_ref() {
Some((seg, _)) => {
let buffer_size = seg.buffer_size();

// SAFETY: No other code should be able to access the segment.
bytemuck::cast_slice(unsafe { seg.as_ref() })
bytemuck::cast_slice(unsafe { &seg.as_ref()[..buffer_size] })
}
None => {
// Nothing has been allocated yet.
Expand All @@ -470,8 +474,10 @@ impl ShmBuffer {
unsafe fn as_mut(&mut self) -> &mut [u32] {
match self.seg.as_mut() {
Some((seg, _)) => {
let buffer_size = seg.buffer_size();

// SAFETY: No other code should be able to access the segment.
bytemuck::cast_slice_mut(unsafe { seg.as_mut() })
bytemuck::cast_slice_mut(unsafe { &mut seg.as_mut()[..buffer_size] })
}
None => {
// Nothing has been allocated yet.
Expand Down Expand Up @@ -528,11 +534,14 @@ struct ShmSegment {
id: i32,
ptr: NonNull<i8>,
size: usize,
buffer_size: usize,
}

impl ShmSegment {
/// Create a new `ShmSegment` with the given size.
fn new(size: usize) -> io::Result<Self> {
fn new(size: usize, buffer_size: usize) -> io::Result<Self> {
assert!(size >= buffer_size);

unsafe {
// Create the shared memory segment.
let id = shmget(IPC_PRIVATE, size, 0o600);
Expand All @@ -552,7 +561,12 @@ impl ShmSegment {
}
};

Ok(Self { id, ptr, size })
Ok(Self {
id,
ptr,
size,
buffer_size,
})
}
}

Expand All @@ -574,6 +588,17 @@ impl ShmSegment {
unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.size) }
}

/// Set the size of the buffer for this shared memory segment.
fn set_buffer_size(&mut self, buffer_size: usize) {
assert!(self.size >= buffer_size);
self.buffer_size = buffer_size
}

/// Get the size of the buffer for this shared memory segment.
fn buffer_size(&self) -> usize {
self.buffer_size
}

/// Get the size of this shared memory segment.
fn size(&self) -> usize {
self.size
Expand Down Expand Up @@ -624,7 +649,7 @@ impl Drop for X11Impl {
/// Test to see if SHM is available.
fn is_shm_available(c: &impl Connection) -> bool {
// Create a small SHM segment.
let seg = match ShmSegment::new(0x1000) {
let seg = match ShmSegment::new(0x1000, 0x1000) {
Ok(seg) => seg,
Err(_) => return false,
};
Expand Down