shm: mmap logic
This commit is contained in:
parent
48424da89b
commit
12dc3b65d8
|
@ -5,3 +5,4 @@ authors = ["Victor Berger <victor.berger@thalesgroup.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wayland-server = "0.8.4"
|
wayland-server = "0.8.4"
|
||||||
|
nix = "0.7.0"
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate wayland_server;
|
extern crate wayland_server;
|
||||||
|
extern crate nix;
|
||||||
|
|
||||||
pub mod shm;
|
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::{GlobalHandler, EventLoopHandle, Client, Init, Resource, Destroy, resource_is_registered};
|
||||||
use wayland_server::protocol::{wl_shm, wl_shm_pool, wl_buffer};
|
use wayland_server::protocol::{wl_shm, wl_shm_pool, wl_buffer};
|
||||||
|
|
||||||
use self::pool::Pool;
|
use self::pool::{Pool, ResizeError};
|
||||||
|
|
||||||
mod pool;
|
mod pool;
|
||||||
|
|
||||||
|
@ -156,9 +156,20 @@ impl Init for ShmHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl wl_shm::Handler 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) {
|
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);
|
evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&pool, self.my_id);
|
||||||
pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
|
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)
|
pool: &wl_shm_pool::WlShmPool, size: i32)
|
||||||
{
|
{
|
||||||
let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
|
let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
|
||||||
if arc_pool.resize(size).is_err() {
|
match arc_pool.resize(size) {
|
||||||
pool.post_error(wl_shm::Error::InvalidFd as u32, "Invalid new size for a wl_shm_pool.".into())
|
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::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 {
|
impl Pool {
|
||||||
pub fn new(fd: RawFd, size: i32) -> Pool {
|
pub fn new(fd: RawFd, size: usize) -> Result<Pool,()> {
|
||||||
unimplemented!()
|
let memmap = MemMap::new(fd, size)?;
|
||||||
|
Ok(Pool {
|
||||||
|
map: RwLock::new(memmap)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&self, newsize: i32) -> Result<(),()> {
|
pub fn resize(&self, newsize: i32) -> Result<(),ResizeError> {
|
||||||
unimplemented!()
|
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<(),()> {
|
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