Skip to content

Commit

Permalink
libuser: Implement clone IPC control cmd
Browse files Browse the repository at this point in the history
Session objects should now implement `Clone`. For complex types that
have some inner mutable state (like FS types), we'll Arc<Mutex> that
inner state.
  • Loading branch information
roblabla committed Oct 17, 2019
1 parent 44e17b4 commit 1b1bd82
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 36 deletions.
2 changes: 1 addition & 1 deletion ahci/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ fn main() {
///
/// As hotplug/remove of a disk is not supported, a disk id remains valid for the whole
/// lifetime of the ahci driver.
#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
struct AhciInterface;

impl IAhciInterface for AhciInterface {
Expand Down
2 changes: 1 addition & 1 deletion fs/src/detail/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ impl<'a> Iterator for PartitionIterator<'a> {
/// Entry point of the file system interface.
///
/// Allows to interract with various filesytem.
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
pub struct FileSystemProxy {

}
Expand Down
32 changes: 16 additions & 16 deletions fs/src/ipc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::interface::filesystem::{convert_path, DirectoryOperations, FileOperat
use alloc::sync::Arc;
use spin::Mutex;

#[derive(Debug)]
#[derive(Debug, Clone)]
/// This is the ipc interface for a raw device, usually a block device.
pub struct Storage {
/// The detail implementation of this ipc interface.
Expand Down Expand Up @@ -83,7 +83,7 @@ impl IStorageServer for Storage {
}
}

#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
/// Entry point of the file system interface.
///
/// Allows to interract with various filesytem via IPC.
Expand Down Expand Up @@ -122,16 +122,16 @@ impl sunrise_libuser::fs::IFileSystemService for FileSystemService {
}

/// Represent a file in the IPC.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct File {
/// The detail implementation of this ipc interface.
inner: Box<dyn FileOperations>
inner: Arc<Mutex<Box<dyn FileOperations>>>
}

impl File {
/// Create a new IFile instance from it's detail.
pub fn new(inner: Box<dyn FileOperations>) -> Self {
File { inner }
File { inner: Arc::new(Mutex::new(inner)) }
}
}

Expand All @@ -145,7 +145,7 @@ impl IFile for File {
return Err(FileSystemError::OutOfRange.into());
}

self.inner.read(offset, &mut out_buffer[..length as usize])
self.inner.lock().read(offset, &mut out_buffer[..length as usize])
}

fn write(&mut self, _manager: WorkQueue<'static>, _unknown_0: u32, offset: u64, length: u64, in_buffer: &[u8]) -> Result<(), Error> {
Expand All @@ -157,33 +157,33 @@ impl IFile for File {
return Err(FileSystemError::OutOfRange.into());
}

self.inner.write(offset, &in_buffer[..length as usize])
self.inner.lock().write(offset, &in_buffer[..length as usize])
}

fn flush(&mut self, _manager: WorkQueue<'static>) -> Result<(), Error> {
self.inner.flush()
self.inner.lock().flush()
}

fn set_size(&mut self, _manager: WorkQueue<'static>, new_size: u64) -> Result<(), Error> {
self.inner.set_len(new_size)
self.inner.lock().set_len(new_size)
}

fn get_size(&mut self, _manager: WorkQueue<'static>) -> Result<u64, Error> {
self.inner.get_len()
self.inner.lock().get_len()
}
}

/// Represent a file in the IPC.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Directory {
/// The detail implementation of this ipc interface.
inner: Box<dyn DirectoryOperations>
inner: Arc<Mutex<Box<dyn DirectoryOperations>>>
}

impl Directory {
/// Create a new IFile instance from it's detail.
pub fn new(inner: Box<dyn DirectoryOperations>) -> Self {
Directory { inner }
Directory { inner: Arc::new(Mutex::new(inner)) }
}
}

Expand All @@ -193,16 +193,16 @@ impl sunrise_libuser::fs::IDirectory for Directory {
return Ok(0)
}

self.inner.read(out_buffer)
self.inner.lock().read(out_buffer)
}

fn get_entry_count(&mut self, _manager: WorkQueue<'static>) -> Result<u64, Error> {
self.inner.entry_count()
self.inner.lock().entry_count()
}
}

/// Represent a filesystem in the IPC.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct FileSystem {
/// The detail implementation of this ipc interface.
inner: Arc<Mutex<Box<dyn FileSystemOperations>>>
Expand Down
6 changes: 3 additions & 3 deletions keyboard/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ impl Keyboard {
}

/// Get the writeable update event of the Keyboard.
///
///
/// # Note:
///
///
/// This consume the internal writable_event.q
pub fn take_writable_event(&mut self) -> Option<WritableEvent> {
self.writable_event.take()
Expand Down Expand Up @@ -157,7 +157,7 @@ impl Keyboard {
static KEYBOARD_INSTANCE: Once<Mutex<Keyboard>> = Once::new();

/// Entry point interface.
#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
struct StaticService;

impl sunrise_libuser::keyboard::StaticService for StaticService {
Expand Down
46 changes: 39 additions & 7 deletions libuser/src/ipc/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ fn common_port_handler<T, DISPATCH>(work_queue: WorkQueue<'static>, port: Server
where
DISPATCH: for<'b> hrtb_hack::FutureCallback<(&'b mut T, WorkQueue<'static>, u32, &'b mut [u8]), Result<(), Error>>,
DISPATCH: Clone + Unpin + Send + 'static,
T: Default + Unpin + Send + 'static,
T: Default + Clone + Unpin + Send + 'static,
{
crate::loop_future::loop_fn((work_queue, dispatch, port), |(work_queue, dispatch, port)| {
port.wait_async(work_queue.clone())
Expand Down Expand Up @@ -331,7 +331,7 @@ pub fn port_handler<T, DISPATCH>(work_queue: WorkQueue<'static>, server_name: &s
where
DISPATCH: for<'b> hrtb_hack::FutureCallback<(&'b mut T, WorkQueue<'static>, u32, &'b mut [u8]), Result<(), Error>>,
DISPATCH: Clone + Unpin + Send + 'static,
T: Default + Unpin + Send + 'static,
T: Default + Clone + Unpin + Send + 'static,
{
use crate::sm::IUserInterfaceProxy;
// We use `new()` and not `raw_new()` in order to avoid deadlocking when closing the
Expand All @@ -349,7 +349,7 @@ pub fn managed_port_handler<T, DISPATCH>(work_queue: WorkQueue<'static>, server_
where
DISPATCH: for<'b> hrtb_hack::FutureCallback<(&'b mut T, WorkQueue<'static>, u32, &'b mut [u8]), Result<(), Error>>,
DISPATCH: Clone + Unpin + Send + 'static,
T: Default + Unpin + Send + 'static,
T: Default + Clone + Unpin + Send + 'static,
{
let port = syscalls::manage_named_port(server_name, 0)?;
Ok(common_port_handler(work_queue, port, dispatch))
Expand Down Expand Up @@ -409,8 +409,8 @@ pub mod hrtb_hack {
pub fn new_session_wrapper<T, DISPATCH>(work_queue: WorkQueue<'static>, handle: ServerSession, mut object: T, mut dispatch: DISPATCH) -> impl Future<Output = ()> + Send
where
DISPATCH: for<'b> hrtb_hack::FutureCallback<(&'b mut T, WorkQueue<'static>, u32, &'b mut [u8]), Result<(), Error>>,
DISPATCH: Unpin + Send + 'static,
T: Unpin + Send + 'static,
DISPATCH: Unpin + Send + Clone + 'static,
T: Unpin + Send + Clone + 'static,
{
let mut buf = Align16([0; 0x100]);
let mut pointer_buf = [0; 0x400];
Expand Down Expand Up @@ -444,12 +444,14 @@ where
debug!("Got request for: {:?}", tycmdid);

let close = match tycmdid {
// TODO: Handle other types.
Some((4, cmdid)) | Some((6, cmdid)) => dispatch.call((&mut object, work_queue.clone(), cmdid, &mut buf[..])).await
.map(|_| false)
.unwrap_or_else(|err| { error!("Dispatch method errored out: {:?}", err); true }),
Some((2, _)) => true,
_ => true
Some((5, cmdid)) | Some((7, cmdid)) => control_dispatch(&mut object, dispatch.clone(), work_queue.clone(), cmdid, &mut buf[..])
.map(|_| false)
.unwrap_or_else(|err| { error!("Dispatch method errored out: {:?}", err); true }),
_ => true,
};

if close {
Expand All @@ -460,3 +462,33 @@ where
}
}
}

/// Implement the Control ipc cmd types.
///
/// See [switchbrew](https://switchbrew.org/w/index.php?title=IPC_Marshalling#Control)
fn control_dispatch<T, DISPATCH>(object: &mut T, dispatch: DISPATCH, manager: WorkQueue<'static>, cmdid: u32, buf: &mut [u8]) -> Result<(), Error>
where
DISPATCH: for<'b> hrtb_hack::FutureCallback<(&'b mut T, WorkQueue<'static>, u32, &'b mut [u8]), Result<(), Error>>,
DISPATCH: Unpin + Send + Clone + 'static,
T: Unpin + Send + Clone + 'static
{
match cmdid {
2 | 4 => {
let (server, client) = syscalls::create_session(false, 0)?;
let new_object = object.clone();
let future = new_session_wrapper(manager.clone(), server, new_object, dispatch);
manager.spawn(FutureObj::new(Box::new(future)));

let mut msg__ = Message::<(), [_; 0], [_; 0], [_; 1]>::new_response(None);
msg__.push_handle_move(client.into_handle());
msg__.pack(buf);
Ok(())
},
_ => {
let mut msg__ = Message::<(), [_; 0], [_; 0], [_; 0]>::new_response(None);
msg__.set_error(KernelError::PortRemoteDead.make_ret() as u32);
msg__.pack(buf);
Ok(())
}
}
}
2 changes: 1 addition & 1 deletion loader/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ lazy_static! {
}

/// Struct implementing the ldr:shel service.
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
struct LoaderIface;

impl ILoaderInterfaceAsync for LoaderIface {
Expand Down
2 changes: 1 addition & 1 deletion sm/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ use crate::libuser::futures_rs as futures;
/// or register new services (assuming they have the appropriate capabilities).
///
/// Make sure to call the `IUserInterface::initialize` method before using it.
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
struct UserInterface;

lazy_static! {
Expand Down
4 changes: 2 additions & 2 deletions time/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ capabilities!(CAPABILITIES = Capabilities {
});

/// Entry point interface.
#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
struct StaticService;

impl sunrise_libuser::time::StaticService for StaticService {
Expand Down Expand Up @@ -193,7 +193,7 @@ impl Default for Rtc {
static RTC_INSTANCE: Once<Rtc> = Once::new();

/// RTC interface.
#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
struct RTCManager;

/// Task responsible for updating the RTC_INSTANCE's current time every second.
Expand Down
2 changes: 1 addition & 1 deletion time/src/timezone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ pub static TZ_MANAGER: Mutex<TimeZoneManager> = Mutex::new(unsafe {
};

/// TimeZone service object.
#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
pub struct TimeZoneService {
/// A dummy field present to just avoid having a zero sized type.
pub dummy: u64
Expand Down
6 changes: 3 additions & 3 deletions vi/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use libuser::mem::{find_free_address, PAGE_SIZE};
use crate::libuser::vi::{IBuffer as IBufferInterface, IBufferProxy, ViInterface as IViInterface};

/// Entry point interface.
#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
struct ViInterface;

impl IViInterface for ViInterface {
Expand Down Expand Up @@ -77,7 +77,7 @@ impl IViInterface for ViInterface {
let wrapper = new_session_wrapper(manager.clone(), server, buf, IBuffer::dispatch);
//let future : Box<dyn Send + 'static> = Box::new(wrapper);
//let future : FutureObj<'static, _> = FutureObj::new(Box::new(wrapper));
manager.spawn( FutureObj::new(Box::new(wrapper)));
manager.spawn(FutureObj::new(Box::new(wrapper)));
Ok(IBufferProxy::from(client))
}

Expand Down Expand Up @@ -204,7 +204,7 @@ impl Buffer {
}

/// IPC Window object
#[derive(Debug)]
#[derive(Debug, Clone)]
struct IBuffer {
/// The Buffer linked with this window object instance.
buffer: Arc<Buffer>,
Expand Down

0 comments on commit 1b1bd82

Please sign in to comment.