Add ipc from old mikros std
This commit is contained in:
parent
b68449acff
commit
a428b626e5
@ -1,4 +1,7 @@
|
||||
use super::{
|
||||
#![stable(feature = "mikros", since = "1.80.0")]
|
||||
#![allow(exported_private_dependencies)]
|
||||
|
||||
use crate::sys::{
|
||||
buffers::KernelBufferAllocator,
|
||||
syscalls::{copy_to, drop_space, map_assert_unused, map_only_unused, map_free, new_space},
|
||||
};
|
||||
@ -6,26 +9,35 @@
|
||||
use crate::mem;
|
||||
use crate::sync::Mutex;
|
||||
use x86_64::{
|
||||
structures::paging::{Page, PageTableFlags},
|
||||
structures::paging::PageTableFlags,
|
||||
VirtAddr,
|
||||
};
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub use x86_64::structures::paging::Page;
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
#[allow(unused)]
|
||||
pub static ACTIVE_SPACE: Mutex<AddressSpace> = Mutex::new(AddressSpace(0));
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct AddressSpace(u64);
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct PagingError;
|
||||
|
||||
#[allow(clippy::new_without_default)] // The idea of a "default" address space makes no sense
|
||||
impl AddressSpace {
|
||||
#[must_use]
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn new() -> Self {
|
||||
Self(new_space())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn into_raw(self) -> u64 {
|
||||
let id = self.0;
|
||||
mem::forget(self);
|
||||
@ -37,12 +49,14 @@ pub fn into_raw(self) -> u64 {
|
||||
/// as it doesn't make sense to map garbage data read only.
|
||||
/// The requested virtual page range is asserted to be unmapped, making this function safe.
|
||||
#[allow(unused)]
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn map_assert_unused(&mut self, page: Page, num_pages: usize) -> Result<(), PagingError> {
|
||||
map_assert_unused(self.0, page, num_pages, PageTableFlags::USER_ACCESSIBLE)
|
||||
.map_err(|_| PagingError)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn map_only_unused(&mut self, page: Page, num_pages: usize) -> Result<(), PagingError> {
|
||||
map_only_unused(self.0, page, num_pages, PageTableFlags::USER_ACCESSIBLE)
|
||||
.map_err(|_| PagingError)
|
||||
@ -52,6 +66,7 @@ pub fn map_only_unused(&mut self, page: Page, num_pages: usize) -> Result<(), Pa
|
||||
/// The newly allocated physical memory contains garbage data, so the mapping will always be writable,
|
||||
/// as it doesn't make sense to map garbage data read only.
|
||||
#[allow(unused)]
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn map_free(&mut self, num_pages: usize) -> Result<Page, PagingError> {
|
||||
Page::from_start_address(VirtAddr::from_ptr(
|
||||
map_free(self.0, num_pages, PageTableFlags::USER_ACCESSIBLE)
|
||||
@ -60,6 +75,7 @@ pub fn map_free(&mut self, num_pages: usize) -> Result<Page, PagingError> {
|
||||
.map_err(|_| PagingError)
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn copy_to(&self, dst: *mut u8, src: &[u8]) -> Result<(), PagingError> {
|
||||
let mut buf = Vec::with_capacity_in(src.len(), KernelBufferAllocator::new());
|
||||
buf.extend_from_slice(src);
|
||||
@ -67,6 +83,7 @@ pub fn copy_to(&self, dst: *mut u8, src: &[u8]) -> Result<(), PagingError> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
impl Drop for AddressSpace {
|
||||
fn drop(&mut self) {
|
||||
drop_space(self.0);
|
53
library/std/src/os/mikros/ipc.rs
Normal file
53
library/std/src/os/mikros/ipc.rs
Normal file
@ -0,0 +1,53 @@
|
||||
#![stable(feature = "mikros", since = "1.80.0")]
|
||||
|
||||
pub mod rpc;
|
||||
|
||||
use crate::sync::{LazyLock, RwLock};
|
||||
|
||||
use crate::sys::{
|
||||
buffers::KernelBufferAllocator, syscalls::{get_pid, ipc_recv, ipc_send}
|
||||
};
|
||||
|
||||
use crate::collections::HashMap;
|
||||
|
||||
#[allow(clippy::type_complexity)] // Pulling out fn(Message) makes the type longer
|
||||
static CALLBACKS: LazyLock<RwLock<HashMap<u16, fn(Message)>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub struct Message {
|
||||
pub from: u64,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn register_callback(proto: u16, callback: fn(Message)) {
|
||||
CALLBACKS.write().unwrap().insert(proto, callback);
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn unregister_callback(proto: u16) {
|
||||
CALLBACKS.write().unwrap().remove(&proto);
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn send_msg(dst: u64, proto: u16, data: &[u8]) {
|
||||
let mut buffer = Vec::with_capacity_in(data.len() + 16, KernelBufferAllocator::new());
|
||||
buffer.extend_from_slice(&(get_pid().to_le_bytes()));
|
||||
buffer.extend_from_slice(&(proto.to_le_bytes()));
|
||||
buffer.extend_from_slice(data);
|
||||
ipc_send(dst, buffer).unwrap();
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn process_messages() {
|
||||
while let Some(msg) = ipc_recv() {
|
||||
let proto = u16::from_le_bytes(msg[8..10].try_into().unwrap());
|
||||
if let Some(callback) = CALLBACKS.read().unwrap().get(&proto) {
|
||||
callback(Message {
|
||||
from: u64::from_le_bytes(msg[0..8].try_into().unwrap()),
|
||||
data: Vec::from(&msg[10..]),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
161
library/std/src/os/mikros/ipc/rpc.rs
Normal file
161
library/std/src/os/mikros/ipc/rpc.rs
Normal file
@ -0,0 +1,161 @@
|
||||
#![stable(feature = "mikros", since = "1.80.0")]
|
||||
|
||||
use core::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use crate::sync::{Mutex, RwLock, LazyLock};
|
||||
|
||||
use crate::collections::HashMap;
|
||||
|
||||
type MessageCallback = fn(IncomingCall);
|
||||
|
||||
static CALLBACKS: LazyLock<RwLock<HashMap<u16, MessageCallback>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
static RETURNS: LazyLock<Mutex<HashMap<CallId, Vec<u8>>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
#[derive(Copy, Clone, Eq, Hash, PartialEq)]
|
||||
pub struct CallId(u64);
|
||||
|
||||
static NEXT_ID: AtomicU64 = AtomicU64::new(1);
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub struct IncomingCall {
|
||||
pub from: u64,
|
||||
call_id: CallId,
|
||||
pub proto: u16,
|
||||
pub func: u16,
|
||||
pub args: Vec<u8>,
|
||||
}
|
||||
|
||||
impl IncomingCall {
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn send_return(self, data: &[u8]) {
|
||||
let msg = Message {
|
||||
typ: MessageType::Return,
|
||||
call_id: self.call_id,
|
||||
proto: 0,
|
||||
func: 0,
|
||||
data,
|
||||
};
|
||||
let mut buf = Vec::new();
|
||||
msg.serialize(&mut buf);
|
||||
super::send_msg(self.from, 0, &buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl CallId {
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn try_get_return(&self) -> Option<Vec<u8>> {
|
||||
RETURNS.lock().unwrap().remove(self)
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn get_return(self) -> Vec<u8> {
|
||||
loop {
|
||||
super::process_messages();
|
||||
if let Some(ret) = self.try_get_return() {
|
||||
break ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone)]
|
||||
enum MessageType {
|
||||
Call,
|
||||
Return,
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for MessageType {
|
||||
type Error = u8;
|
||||
|
||||
fn try_from(val: u8) -> Result<Self, Self::Error> {
|
||||
match val {
|
||||
0 => Ok(MessageType::Call),
|
||||
1 => Ok(MessageType::Return),
|
||||
_ => Err(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Message<'a> {
|
||||
typ: MessageType,
|
||||
call_id: CallId,
|
||||
proto: u16,
|
||||
func: u16,
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Message<'a> {
|
||||
fn serialize(&self, buf: &mut Vec<u8>) {
|
||||
buf.push(self.typ as u8);
|
||||
buf.extend_from_slice(&self.call_id.0.to_ne_bytes());
|
||||
buf.extend_from_slice(&self.proto.to_ne_bytes());
|
||||
buf.extend_from_slice(&self.func.to_ne_bytes());
|
||||
buf.extend_from_slice(self.data);
|
||||
}
|
||||
|
||||
fn deserialize(buf: &'a [u8]) -> Self {
|
||||
Self {
|
||||
typ: MessageType::try_from(buf[0]).unwrap(),
|
||||
call_id: CallId(u64::from_ne_bytes(buf[1..9].try_into().unwrap())),
|
||||
proto: u16::from_ne_bytes(buf[9..11].try_into().unwrap()),
|
||||
func: u16::from_ne_bytes(buf[11..13].try_into().unwrap()),
|
||||
data: &buf[13..],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn register_callback(proto: u16, callback: MessageCallback) {
|
||||
CALLBACKS.write().unwrap().insert(proto, callback);
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn unregister_callback(proto: u16) {
|
||||
CALLBACKS.write().unwrap().remove(&proto);
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn send_call(dst: u64, proto: u16, func: u16, data: &[u8]) -> CallId {
|
||||
let call_id = CallId(NEXT_ID.fetch_add(1, Ordering::Relaxed));
|
||||
let msg = Message {
|
||||
typ: MessageType::Call,
|
||||
call_id,
|
||||
proto,
|
||||
func,
|
||||
data,
|
||||
};
|
||||
let mut buf = Vec::new();
|
||||
msg.serialize(&mut buf);
|
||||
super::send_msg(dst, 0, &buf);
|
||||
call_id
|
||||
}
|
||||
|
||||
#[stable(feature = "mikros", since = "1.80.0")]
|
||||
pub fn msg_callback(msg: super::Message) {
|
||||
let from = msg.from;
|
||||
let msg = Message::deserialize(&msg.data);
|
||||
match msg.typ {
|
||||
MessageType::Call => {
|
||||
if let Some(callback) = CALLBACKS.read().unwrap().get(&msg.proto) {
|
||||
callback(IncomingCall {
|
||||
from,
|
||||
call_id: msg.call_id,
|
||||
proto: msg.proto,
|
||||
func: msg.func,
|
||||
args: msg.data.into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
MessageType::Return => {
|
||||
RETURNS.lock().unwrap().insert(msg.call_id, msg.data.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn init() {
|
||||
super::register_callback(0, msg_callback);
|
||||
}
|
7
library/std/src/os/mikros/mod.rs
Normal file
7
library/std/src/os/mikros/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
//! Mikros-specific definitions
|
||||
|
||||
#![stable(feature = "mikros", since = "1.80.0")]
|
||||
|
||||
pub mod ipc;
|
||||
pub mod address_space;
|
||||
|
@ -132,6 +132,8 @@ pub mod windows {}
|
||||
pub mod l4re;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos;
|
||||
#[cfg(target_os = "mikros")]
|
||||
pub mod mikros;
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub mod netbsd;
|
||||
#[cfg(target_os = "nto")]
|
||||
|
@ -6,7 +6,7 @@
|
||||
ptr::NonNull
|
||||
};
|
||||
use linked_list_allocator::hole::HoleList;
|
||||
use super::address_space;
|
||||
use crate::os::mikros::address_space;
|
||||
|
||||
struct Wrap(Mutex<HoleList>);
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
use crate::io as std_io;
|
||||
use crate::os::mikros::ipc::rpc;
|
||||
|
||||
// SAFETY: must be called only once during runtime initialization.
|
||||
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
|
||||
pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
|
||||
pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {
|
||||
rpc::init();
|
||||
}
|
||||
|
||||
// SAFETY: must be called only once during runtime cleanup.
|
||||
// NOTE: this is not guaranteed to run, for example when the program aborts.
|
||||
|
@ -2,9 +2,8 @@
|
||||
#![allow(dead_code)]
|
||||
#![allow(exported_private_dependencies)]
|
||||
|
||||
mod address_space;
|
||||
mod syscalls;
|
||||
mod buffers;
|
||||
pub mod syscalls;
|
||||
pub mod buffers;
|
||||
|
||||
pub mod alloc;
|
||||
pub mod args;
|
||||
|
@ -8,10 +8,8 @@
|
||||
use x86_64::structures::paging::{Page, PageTableFlags};
|
||||
use crate::ptr;
|
||||
|
||||
use super::{
|
||||
address_space::AddressSpace,
|
||||
buffers::{IntoId, KernelBuffer, KernelBufferAllocator},
|
||||
};
|
||||
use super::buffers::{IntoId, KernelBuffer, KernelBufferAllocator};
|
||||
use crate::os::mikros::address_space::AddressSpace;
|
||||
|
||||
pub(crate) fn print_char(chr: char) {
|
||||
syscall1(0, chr as u64);
|
||||
|
Loading…
Reference in New Issue
Block a user