shm: mmap logic
This commit is contained in:
parent
48424da89b
commit
12dc3b65d8
|
@ -5,3 +5,4 @@ authors = ["Victor Berger <victor.berger@thalesgroup.com>"]
|
|||
|
||||
[dependencies]
|
||||
wayland-server = "0.8.4"
|
||||
nix = "0.7.0"
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
|
||||
#[macro_use]
|
||||
extern crate wayland_server;
|
||||
extern crate nix;
|
||||
|
||||
pub mod shm;
|
||||
|
|
|
@ -32,7 +32,7 @@ use std::sync::Arc;
|
|||
use wayland_server::{GlobalHandler, EventLoopHandle, Client, Init, Resource, Destroy, resource_is_registered};
|
||||
use wayland_server::protocol::{wl_shm, wl_shm_pool, wl_buffer};
|
||||
|
||||
use self::pool::Pool;
|
||||
use self::pool::{Pool, ResizeError};
|
||||
|
||||
mod pool;
|
||||
|
||||
|
@ -156,9 +156,20 @@ impl Init for ShmHandler {
|
|||
}
|
||||
|
||||
impl wl_shm::Handler for ShmHandler {
|
||||
fn create_pool(&mut self, evqh: &mut EventLoopHandle, _client: &Client, _shm: &wl_shm::WlShm,
|
||||
fn create_pool(&mut self, evqh: &mut EventLoopHandle, _client: &Client, shm: &wl_shm::WlShm,
|
||||
pool: wl_shm_pool::WlShmPool, fd: RawFd, size: i32) {
|
||||
let arc_pool = Box::new(Arc::new(Pool::new(fd, size)));
|
||||
if size <= 0 {
|
||||
shm.post_error(wl_shm::Error::InvalidFd as u32, "Invalid size for a new wl_shm_pool.".into());
|
||||
return
|
||||
}
|
||||
let mmap_pool = match Pool::new(fd, size as usize) {
|
||||
Ok(p) => p,
|
||||
Err(()) => {
|
||||
shm.post_error(wl_shm::Error::InvalidFd as u32, format!("Failed mmap of fd {}.", fd));
|
||||
return
|
||||
}
|
||||
};
|
||||
let arc_pool = Box::new(Arc::new(mmap_pool));
|
||||
evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&pool, self.my_id);
|
||||
pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
|
||||
}
|
||||
|
@ -221,8 +232,14 @@ impl wl_shm_pool::Handler for ShmHandler {
|
|||
pool: &wl_shm_pool::WlShmPool, size: i32)
|
||||
{
|
||||
let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
|
||||
if arc_pool.resize(size).is_err() {
|
||||
pool.post_error(wl_shm::Error::InvalidFd as u32, "Invalid new size for a wl_shm_pool.".into())
|
||||
match arc_pool.resize(size) {
|
||||
Ok(()) => {},
|
||||
Err(ResizeError::InvalidSize) => {
|
||||
pool.post_error(wl_shm::Error::InvalidFd as u32, "Invalid new size for a wl_shm_pool.".into());
|
||||
},
|
||||
Err(ResizeError::MremapFailed) => {
|
||||
pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,93 @@
|
|||
use std::os::unix::io::RawFd;
|
||||
use std::sync::RwLock;
|
||||
use std::ptr;
|
||||
|
||||
pub struct Pool;
|
||||
use nix::sys::mman;
|
||||
|
||||
pub struct Pool {
|
||||
map: RwLock<MemMap>
|
||||
}
|
||||
|
||||
pub enum ResizeError {
|
||||
InvalidSize,
|
||||
MremapFailed
|
||||
}
|
||||
|
||||
impl Pool {
|
||||
pub fn new(fd: RawFd, size: i32) -> Pool {
|
||||
unimplemented!()
|
||||
pub fn new(fd: RawFd, size: usize) -> Result<Pool,()> {
|
||||
let memmap = MemMap::new(fd, size)?;
|
||||
Ok(Pool {
|
||||
map: RwLock::new(memmap)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resize(&self, newsize: i32) -> Result<(),()> {
|
||||
unimplemented!()
|
||||
pub fn resize(&self, newsize: i32) -> Result<(),ResizeError> {
|
||||
let mut guard = self.map.write().unwrap();
|
||||
if newsize <= 0 || guard.size() > (newsize as usize) {
|
||||
return Err(ResizeError::InvalidSize)
|
||||
}
|
||||
guard.remap(newsize as usize).map_err(|()| ResizeError::MremapFailed)
|
||||
}
|
||||
|
||||
pub fn with_data_slice<F: FnOnce(&[u8])>(&self, f: F) -> Result<(),()> {
|
||||
unimplemented!()
|
||||
// TODO: handle SIGBUS
|
||||
let guard = self.map.read().unwrap();
|
||||
|
||||
let slice = guard.get_slice();
|
||||
f(slice);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct MemMap {
|
||||
ptr: *mut u8,
|
||||
fd: RawFd,
|
||||
size: usize
|
||||
}
|
||||
|
||||
impl MemMap {
|
||||
fn new(fd: RawFd, size: usize) -> Result<MemMap,()> {
|
||||
Ok(MemMap {
|
||||
ptr: map(fd, size)?,
|
||||
fd: fd,
|
||||
size: size
|
||||
})
|
||||
}
|
||||
|
||||
fn remap(&mut self, newsize: usize) -> Result<(),()> {
|
||||
unmap(self.ptr, self.size)?;
|
||||
self.ptr = map(self.fd, newsize)?;
|
||||
self.size = newsize;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
|
||||
fn get_slice(&self) -> &[u8] {
|
||||
unsafe { ::std::slice::from_raw_parts(self.ptr, self.size) }
|
||||
}
|
||||
}
|
||||
|
||||
// mman::mmap should really be unsafe... why isn't it?
|
||||
#[allow(unused_unsafe)]
|
||||
fn map(fd: RawFd, size: usize) -> Result<*mut u8, ()> {
|
||||
let ret = unsafe { mman::mmap(
|
||||
ptr::null_mut(),
|
||||
size,
|
||||
mman::PROT_READ,
|
||||
mman::MAP_SHARED,
|
||||
fd,
|
||||
0
|
||||
) };
|
||||
ret.map(|p| p as *mut u8).map_err(|_| ())
|
||||
}
|
||||
|
||||
// mman::munmap should really be unsafe... why isn't it?
|
||||
#[allow(unused_unsafe)]
|
||||
fn unmap(ptr: *mut u8, size: usize) -> Result<(),()> {
|
||||
let ret = unsafe { mman::munmap(ptr as *mut _, size) };
|
||||
ret.map_err(|_| ())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue