akern-gkgoat-fork/kernel/src/messaging.rs
2022-04-12 18:17:48 -05:00

194 lines
5.3 KiB
Rust

//! Interprocess communication.
use alloc::vec::Vec;
use crate::{proccess::PID, time::Time};
extern crate alloc;
/// 131070 * 128
pub const TINY_MESSAGE_COUNT: usize = 131070;
/// 16384 * 1024
pub const SMALL_MESSAGE_COUNT: usize = 16384;
/// 65536 * 256
pub const MEDIUM_MESSAGE_COUNT: usize = 256;
/// 262144 * 16
pub const LARGE_MESSAGE_COUNT: usize = 16;
/// 16777216 * 4
pub const HUGE_MESSAGE_COUNT: usize = 4;
/// 128 Bytes
pub type Tiny = [u8; 128];
/// 1 KiB
pub type Small = [u8; 1024];
/// 65.536 KiB
pub type Medium = [u8; 65536];
/// 1MiB
pub type Large = [u8; 1048576];
/// 16MiB
pub type Huge = [u8; 16777216];
/// An internal message to be held in a process message
pub enum Message {
/// A Tiny message
///
/// The message is 128 bytes long
Tiny(Tiny),
/// A Small message
///
/// The message is 1 KiB long
Small(Small),
/// A Medium message
///
/// The message is 65.536 KiB long
Medium(Medium),
/// A Large message
///
/// The message is 1 MiB long
Large(Large),
/// A Huge message
///
/// The message is 16 MiB long
Huge(Huge),
}
/// A message that can be sent between processes
pub struct ProcessMessage {
/// The sender of the message
pub to_pid: PID,
/// The receiver of the message
pub from_pid: PID,
/// The message
pub message: Message,
/// The time the message was sent
pub sender_time: Time,
/// The time the message was received
pub receiver_time: Time,
}
impl ProcessMessage {
/// Return the size of the message
pub fn size(&self) -> usize {
match &self.message {
Message::Tiny(_) => 128,
Message::Small(_) => 1024,
Message::Medium(_) => 65536,
Message::Large(_) => 1048576,
Message::Huge(_) => 16777216,
}
}
}
#[derive(Debug)]
/// An enum of all possible errors that can occur when sending a message
pub enum MessagingError {
/// The message is too large to be sent
MessageTooLarge,
/// The reciever of the message is not valid
ProcessNonExistant,
/// The message Queue is full
TooManyMessages,
}
/// A mailbox that holds messages and PipeState
pub struct Mailbox {
/// The messages in the mailbox
pub messages: Vec<ProcessMessage>,
/// The count of messages in the mailbox
pub message_count: MessageCount,
}
impl Mailbox {
/// append a message to the mailbox
pub fn append(&mut self, message: ProcessMessage) -> Result<(), MessagingError> {
let msg_size = message.size();
if self.message_count.total() > 147730 {
return Err(MessagingError::TooManyMessages);
}
match msg_size {
TINY_MESSAGE_COUNT => {
if self.message_count.tiny < TINY_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.tiny += 1;
Ok(())
} else {
Err(MessagingError::TooManyMessages)
}
}
SMALL_MESSAGE_COUNT => {
if self.message_count.small < SMALL_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.small += 1;
Ok(())
} else {
Err(MessagingError::TooManyMessages)
}
}
MEDIUM_MESSAGE_COUNT => {
if self.message_count.medium < MEDIUM_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.medium += 1;
Ok(())
} else {
Err(MessagingError::TooManyMessages)
}
}
LARGE_MESSAGE_COUNT => {
if self.message_count.large < LARGE_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.large += 1;
Ok(())
} else {
Err(MessagingError::TooManyMessages)
}
}
HUGE_MESSAGE_COUNT => {
if self.message_count.huge < HUGE_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.huge += 1;
Ok(())
} else {
return Err(MessagingError::TooManyMessages);
}
}
_ => Err(MessagingError::MessageTooLarge),
}
}
}
/// A proper struct to list the number of messages in the mailbox
pub struct MessageCount {
/// The number of tiny messages in the mailbox
pub tiny: usize,
/// The number of small messages in the mailbox
pub small: usize,
/// The number of medium messages in the mailbox
pub medium: usize,
/// The number of large messages in the mailbox
pub large: usize,
/// The number of huge messages in the mailbox
pub huge: usize,
}
impl MessageCount {
/// Return the total number of messages in the mailbox
pub fn total(&self) -> usize {
self.tiny + self.small + self.medium + self.large + self.huge
}
}
impl Default for MessageCount {
fn default() -> Self {
MessageCount {
tiny: 0,
small: 0,
medium: 0,
large: 0,
huge: 0,
}
}
}