channel: send files over channels
This commit is contained in:
parent
21ff2616f9
commit
293dcfea6a
@ -1,10 +1,17 @@
|
|||||||
use core::task::{Context, Poll};
|
use core::task::{Context, Poll};
|
||||||
|
|
||||||
use alloc::{boxed::Box, format, sync::Arc};
|
use alloc::{boxed::Box, format, sync::Arc};
|
||||||
use futures_util::{task::waker_ref, Future};
|
use futures_util::{
|
||||||
|
task::{waker_ref, ArcWake, WakerRef},
|
||||||
|
Future,
|
||||||
|
};
|
||||||
use yggdrasil_abi::error::Error;
|
use yggdrasil_abi::error::Error;
|
||||||
|
|
||||||
use crate::thread::Thread;
|
use crate::{
|
||||||
|
api::__cpu_index,
|
||||||
|
cpu_index,
|
||||||
|
thread::{CurrentThread, Thread},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
task::{Task, Termination},
|
task::{Task, Termination},
|
||||||
@ -48,6 +55,7 @@ pub fn run_to_completion<'a, T, F: Future<Output = T> + Send + 'a>(future: F) ->
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
let thread = Thread::current();
|
let thread = Thread::current();
|
||||||
|
|
||||||
let waker = waker_ref(&thread);
|
let waker = waker_ref(&thread);
|
||||||
let context = &mut Context::from_waker(&waker);
|
let context = &mut Context::from_waker(&waker);
|
||||||
|
|
||||||
|
@ -15,18 +15,29 @@ use kernel_util::{
|
|||||||
block,
|
block,
|
||||||
sync::{mutex::Mutex, IrqSafeSpinlock, LockMethod},
|
sync::{mutex::Mutex, IrqSafeSpinlock, LockMethod},
|
||||||
};
|
};
|
||||||
use yggdrasil_abi::{error::Error, io::MessageDestination};
|
use yggdrasil_abi::{
|
||||||
|
error::Error,
|
||||||
|
io::{MessageDestination, ReceivedMessageMetadata},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::FileReadiness;
|
use crate::{FileReadiness, FileRef};
|
||||||
|
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
last_id: AtomicU32,
|
last_id: AtomicU32,
|
||||||
subscriptions: Mutex<BTreeMap<u32, Arc<Subscription>>>,
|
subscriptions: Mutex<BTreeMap<u32, Arc<Subscription>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes message payload
|
||||||
|
pub enum MessagePayload {
|
||||||
|
/// Payload contains a file
|
||||||
|
File(FileRef),
|
||||||
|
/// Payload contains byte data
|
||||||
|
Data(Box<[u8]>),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
source: u32,
|
pub source: u32,
|
||||||
data: Box<[u8]>,
|
pub payload: MessagePayload,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Subscription {
|
pub struct Subscription {
|
||||||
@ -54,27 +65,22 @@ impl ChannelDescriptor {
|
|||||||
Self { tx, rx, id }
|
Self { tx, rx, id }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn receive_message(&self, buf: &mut [u8]) -> Result<(u32, usize), Error> {
|
pub fn receive_message(&self) -> Result<Arc<Message>, Error> {
|
||||||
let Some(rx) = self.rx.as_ref() else {
|
let Some(rx) = self.rx.as_ref() else {
|
||||||
return Err(Error::InvalidOperation);
|
return Err(Error::InvalidOperation);
|
||||||
};
|
};
|
||||||
|
|
||||||
let message = rx.receive_message_inner()?;
|
rx.receive_message_inner()
|
||||||
let len = message.data.len();
|
|
||||||
|
|
||||||
if buf.len() < len {
|
|
||||||
return Err(Error::MissingData);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[..len].copy_from_slice(&message.data);
|
|
||||||
|
|
||||||
Ok((message.source, len))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_message(&self, msg: &[u8], dst: MessageDestination) -> Result<(), Error> {
|
pub fn send_message(
|
||||||
|
&self,
|
||||||
|
payload: MessagePayload,
|
||||||
|
dst: MessageDestination,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let message = Arc::new(Message {
|
let message = Arc::new(Message {
|
||||||
source: self.id,
|
source: self.id,
|
||||||
data: Box::from(msg),
|
payload,
|
||||||
});
|
});
|
||||||
|
|
||||||
let lock = self.tx.subscriptions.lock()?;
|
let lock = self.tx.subscriptions.lock()?;
|
||||||
|
@ -37,7 +37,7 @@ mod pipe;
|
|||||||
mod regular;
|
mod regular;
|
||||||
|
|
||||||
/// Per-file optional instance data created when a regular file is opened
|
/// Per-file optional instance data created when a regular file is opened
|
||||||
pub type InstanceData = Box<dyn Any + Send + Sync>;
|
pub type InstanceData = Arc<dyn Any + Send + Sync>;
|
||||||
|
|
||||||
/// Describes the starting position of the directory
|
/// Describes the starting position of the directory
|
||||||
pub enum DirectoryOpenPosition {
|
pub enum DirectoryOpenPosition {
|
||||||
@ -159,6 +159,14 @@ impl File {
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clones an open file for sending it to another process
|
||||||
|
pub fn send(&self) -> Result<Arc<Self>, Error> {
|
||||||
|
match self {
|
||||||
|
Self::Regular(file) => Ok(Arc::new(Self::Regular(file.clone()))),
|
||||||
|
_ => Err(Error::InvalidOperation),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads entries from the directory
|
/// Reads entries from the directory
|
||||||
pub fn read_dir(&self, entries: &mut [MaybeUninit<DirectoryEntry>]) -> Result<usize, Error> {
|
pub fn read_dir(&self, entries: &mut [MaybeUninit<DirectoryEntry>]) -> Result<usize, Error> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -4,6 +4,7 @@ use yggdrasil_abi::{error::Error, io::SeekFrom};
|
|||||||
use super::InstanceData;
|
use super::InstanceData;
|
||||||
use crate::node::NodeRef;
|
use crate::node::NodeRef;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct RegularFile {
|
pub struct RegularFile {
|
||||||
pub(super) node: NodeRef,
|
pub(super) node: NodeRef,
|
||||||
pub(super) read: bool,
|
pub(super) read: bool,
|
||||||
|
@ -19,6 +19,7 @@ pub(crate) mod path;
|
|||||||
pub(crate) mod poll;
|
pub(crate) mod poll;
|
||||||
pub(crate) mod traits;
|
pub(crate) mod traits;
|
||||||
|
|
||||||
|
pub use channel::MessagePayload;
|
||||||
pub use device::CharDevice;
|
pub use device::CharDevice;
|
||||||
pub use file::{DirectoryOpenPosition, File, FileRef, FileSet, InstanceData};
|
pub use file::{DirectoryOpenPosition, File, FileRef, FileSet, InstanceData};
|
||||||
pub use ioctx::{Action, IoContext};
|
pub use ioctx::{Action, IoContext};
|
||||||
|
@ -141,7 +141,7 @@ where
|
|||||||
return Err(Error::ReadOnly);
|
return Err(Error::ReadOnly);
|
||||||
}
|
}
|
||||||
let t = (self.read)()?;
|
let t = (self.read)()?;
|
||||||
Ok((0, Some(Box::new(t.as_instance_data()))))
|
Ok((0, Some(Arc::new(t.as_instance_data()))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(
|
fn read(
|
||||||
@ -240,10 +240,10 @@ where
|
|||||||
if opts.contains(OpenOptions::READ | OpenOptions::WRITE) {
|
if opts.contains(OpenOptions::READ | OpenOptions::WRITE) {
|
||||||
Err(Error::InvalidOperation)
|
Err(Error::InvalidOperation)
|
||||||
} else if opts.contains(OpenOptions::WRITE) {
|
} else if opts.contains(OpenOptions::WRITE) {
|
||||||
Ok((0, Some(Box::new(FnNodeData::write()))))
|
Ok((0, Some(Arc::new(FnNodeData::write()))))
|
||||||
} else if opts.contains(OpenOptions::READ) {
|
} else if opts.contains(OpenOptions::READ) {
|
||||||
let t = (self.read)()?;
|
let t = (self.read)()?;
|
||||||
Ok((0, Some(Box::new(FnNodeData::read(t)))))
|
Ok((0, Some(Arc::new(FnNodeData::read(t)))))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidOperation)
|
Err(Error::InvalidOperation)
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,10 @@ use kernel_util::{
|
|||||||
sync::IrqGuard,
|
sync::IrqGuard,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{mem::phys::PhysicalMemoryRegion, task::sched::CpuQueue};
|
use crate::{
|
||||||
|
mem::phys::PhysicalMemoryRegion,
|
||||||
|
task::{sched::CpuQueue, Cpu},
|
||||||
|
};
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(target_arch = "aarch64")] {
|
if #[cfg(target_arch = "aarch64")] {
|
||||||
@ -278,8 +281,7 @@ fn __release_irq_guard(mask: bool) {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn __cpu_index() -> usize {
|
fn __cpu_index() -> usize {
|
||||||
todo!()
|
Cpu::local().id() as _
|
||||||
// Cpu::local_id() as _
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -5,15 +5,15 @@ use abi::{
|
|||||||
error::Error,
|
error::Error,
|
||||||
io::{
|
io::{
|
||||||
DeviceRequest, DirectoryEntry, FileAttr, FileMode, MessageDestination, OpenOptions,
|
DeviceRequest, DirectoryEntry, FileAttr, FileMode, MessageDestination, OpenOptions,
|
||||||
PollControl, RawFd, SeekFrom,
|
PollControl, RawFd, ReceivedMessageMetadata, SeekFrom, SentMessage,
|
||||||
},
|
},
|
||||||
mem::MappingSource,
|
mem::MappingSource,
|
||||||
process::{ExitCode, MutexOperation, Signal, SpawnOption, SpawnOptions, ThreadSpawnOptions},
|
process::{ExitCode, MutexOperation, Signal, SpawnOption, SpawnOptions, ThreadSpawnOptions},
|
||||||
syscall::SyscallFunction,
|
syscall::SyscallFunction,
|
||||||
};
|
};
|
||||||
use alloc::sync::Arc;
|
use alloc::{boxed::Box, sync::Arc};
|
||||||
use kernel_util::{block, mem::table::EntryLevelExt, runtime, sync::IrqSafeSpinlockGuard};
|
use kernel_util::{block, mem::table::EntryLevelExt, runtime, sync::IrqSafeSpinlockGuard};
|
||||||
use vfs::{File, IoContext, NodeRef, Read, Seek, Write};
|
use vfs::{File, IoContext, MessagePayload, NodeRef, Read, Seek, Write};
|
||||||
use yggdrasil_abi::{error::SyscallResult, io::MountOptions};
|
use yggdrasil_abi::{error::SyscallResult, io::MountOptions};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -372,31 +372,63 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
|||||||
}
|
}
|
||||||
SyscallFunction::SendMessage => {
|
SyscallFunction::SendMessage => {
|
||||||
let fd = RawFd::from(args[0] as u32);
|
let fd = RawFd::from(args[0] as u32);
|
||||||
let buf = arg_buffer_ref(args[1] as usize, args[2] as usize)?;
|
let message = arg_user_ref::<SentMessage>(args[1] as usize)?;
|
||||||
let destination = MessageDestination::from(args[3]);
|
let destination = MessageDestination::from(args[2]);
|
||||||
|
|
||||||
run_with_io(process, |io| {
|
run_with_io(process, |io| {
|
||||||
let file = io.files.file(fd)?;
|
let file = io.files.file(fd)?;
|
||||||
let channel = file.as_message_channel()?;
|
let channel = file.as_message_channel()?;
|
||||||
|
|
||||||
channel.send_message(buf, destination)?;
|
match message {
|
||||||
|
&SentMessage::File(fd) => {
|
||||||
|
let sent_file = io.files.file(fd)?;
|
||||||
|
|
||||||
|
channel
|
||||||
|
.send_message(MessagePayload::File(sent_file.clone()), destination)?;
|
||||||
|
}
|
||||||
|
&SentMessage::Data(data) => {
|
||||||
|
channel.send_message(MessagePayload::Data(Box::from(data)), destination)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(0)
|
Ok(0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
SyscallFunction::ReceiveMessage => {
|
SyscallFunction::ReceiveMessage => {
|
||||||
let fd = RawFd::from(args[0] as u32);
|
let fd = RawFd::from(args[0] as u32);
|
||||||
let buf = arg_buffer_mut(args[1] as usize, args[2] as usize)?;
|
let metadata = arg_user_mut::<MaybeUninit<ReceivedMessageMetadata>>(args[1] as usize)?;
|
||||||
let from = arg_user_mut::<MaybeUninit<u32>>(args[3] as usize)?;
|
let buf = arg_buffer_mut(args[2] as usize, args[3] as usize)?;
|
||||||
|
let from = arg_user_mut::<MaybeUninit<u32>>(args[4] as usize)?;
|
||||||
|
|
||||||
run_with_io(process, |io| {
|
run_with_io(process, |mut io| {
|
||||||
let file = io.files.file(fd)?;
|
let file = io.files.file(fd)?;
|
||||||
let channel = file.as_message_channel()?;
|
let channel = file.as_message_channel()?;
|
||||||
|
|
||||||
let (id, len) = channel.receive_message(buf)?;
|
let message = channel.receive_message()?;
|
||||||
from.write(id);
|
|
||||||
|
|
||||||
Ok(len)
|
from.write(message.source);
|
||||||
|
|
||||||
|
match &message.payload {
|
||||||
|
MessagePayload::Data(data) => {
|
||||||
|
// TODO allow truncated messages?
|
||||||
|
let len = data.len();
|
||||||
|
if buf.len() < len {
|
||||||
|
return Err(Error::MissingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.write(ReceivedMessageMetadata::Data(len));
|
||||||
|
buf[..len].copy_from_slice(&data);
|
||||||
|
|
||||||
|
Ok(len)
|
||||||
|
}
|
||||||
|
MessagePayload::File(file) => {
|
||||||
|
let fd = io.files.place_file(file.clone(), true)?;
|
||||||
|
|
||||||
|
metadata.write(ReceivedMessageMetadata::File(fd));
|
||||||
|
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Process management
|
// Process management
|
||||||
|
Loading…
x
Reference in New Issue
Block a user