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,
|
buffers::KernelBufferAllocator,
|
||||||
syscalls::{copy_to, drop_space, map_assert_unused, map_only_unused, map_free, new_space},
|
syscalls::{copy_to, drop_space, map_assert_unused, map_only_unused, map_free, new_space},
|
||||||
};
|
};
|
||||||
@ -6,26 +9,35 @@
|
|||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::sync::Mutex;
|
use crate::sync::Mutex;
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
structures::paging::{Page, PageTableFlags},
|
structures::paging::PageTableFlags,
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
|
pub use x86_64::structures::paging::Page;
|
||||||
|
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub static ACTIVE_SPACE: Mutex<AddressSpace> = Mutex::new(AddressSpace(0));
|
pub static ACTIVE_SPACE: Mutex<AddressSpace> = Mutex::new(AddressSpace(0));
|
||||||
|
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AddressSpace(u64);
|
pub struct AddressSpace(u64);
|
||||||
|
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PagingError;
|
pub struct PagingError;
|
||||||
|
|
||||||
#[allow(clippy::new_without_default)] // The idea of a "default" address space makes no sense
|
#[allow(clippy::new_without_default)] // The idea of a "default" address space makes no sense
|
||||||
impl AddressSpace {
|
impl AddressSpace {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(new_space())
|
Self(new_space())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
pub fn into_raw(self) -> u64 {
|
pub fn into_raw(self) -> u64 {
|
||||||
let id = self.0;
|
let id = self.0;
|
||||||
mem::forget(self);
|
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.
|
/// 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.
|
/// The requested virtual page range is asserted to be unmapped, making this function safe.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
pub fn map_assert_unused(&mut self, page: Page, num_pages: usize) -> Result<(), PagingError> {
|
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_assert_unused(self.0, page, num_pages, PageTableFlags::USER_ACCESSIBLE)
|
||||||
.map_err(|_| PagingError)
|
.map_err(|_| PagingError)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
pub fn map_only_unused(&mut self, page: Page, num_pages: usize) -> Result<(), PagingError> {
|
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_only_unused(self.0, page, num_pages, PageTableFlags::USER_ACCESSIBLE)
|
||||||
.map_err(|_| PagingError)
|
.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,
|
/// 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.
|
/// as it doesn't make sense to map garbage data read only.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
pub fn map_free(&mut self, num_pages: usize) -> Result<Page, PagingError> {
|
pub fn map_free(&mut self, num_pages: usize) -> Result<Page, PagingError> {
|
||||||
Page::from_start_address(VirtAddr::from_ptr(
|
Page::from_start_address(VirtAddr::from_ptr(
|
||||||
map_free(self.0, num_pages, PageTableFlags::USER_ACCESSIBLE)
|
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)
|
.map_err(|_| PagingError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "mikros", since = "1.80.0")]
|
||||||
pub fn copy_to(&self, dst: *mut u8, src: &[u8]) -> Result<(), PagingError> {
|
pub fn copy_to(&self, dst: *mut u8, src: &[u8]) -> Result<(), PagingError> {
|
||||||
let mut buf = Vec::with_capacity_in(src.len(), KernelBufferAllocator::new());
|
let mut buf = Vec::with_capacity_in(src.len(), KernelBufferAllocator::new());
|
||||||
buf.extend_from_slice(src);
|
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 {
|
impl Drop for AddressSpace {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
drop_space(self.0);
|
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;
|
pub mod l4re;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub mod macos;
|
pub mod macos;
|
||||||
|
#[cfg(target_os = "mikros")]
|
||||||
|
pub mod mikros;
|
||||||
#[cfg(target_os = "netbsd")]
|
#[cfg(target_os = "netbsd")]
|
||||||
pub mod netbsd;
|
pub mod netbsd;
|
||||||
#[cfg(target_os = "nto")]
|
#[cfg(target_os = "nto")]
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
ptr::NonNull
|
ptr::NonNull
|
||||||
};
|
};
|
||||||
use linked_list_allocator::hole::HoleList;
|
use linked_list_allocator::hole::HoleList;
|
||||||
use super::address_space;
|
use crate::os::mikros::address_space;
|
||||||
|
|
||||||
struct Wrap(Mutex<HoleList>);
|
struct Wrap(Mutex<HoleList>);
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
use crate::io as std_io;
|
use crate::io as std_io;
|
||||||
|
use crate::os::mikros::ipc::rpc;
|
||||||
|
|
||||||
// SAFETY: must be called only once during runtime initialization.
|
// SAFETY: must be called only once during runtime initialization.
|
||||||
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
|
// 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.
|
// SAFETY: must be called only once during runtime cleanup.
|
||||||
// NOTE: this is not guaranteed to run, for example when the program aborts.
|
// NOTE: this is not guaranteed to run, for example when the program aborts.
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(exported_private_dependencies)]
|
#![allow(exported_private_dependencies)]
|
||||||
|
|
||||||
mod address_space;
|
pub mod syscalls;
|
||||||
mod syscalls;
|
pub mod buffers;
|
||||||
mod buffers;
|
|
||||||
|
|
||||||
pub mod alloc;
|
pub mod alloc;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
|
@ -8,10 +8,8 @@
|
|||||||
use x86_64::structures::paging::{Page, PageTableFlags};
|
use x86_64::structures::paging::{Page, PageTableFlags};
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
|
|
||||||
use super::{
|
use super::buffers::{IntoId, KernelBuffer, KernelBufferAllocator};
|
||||||
address_space::AddressSpace,
|
use crate::os::mikros::address_space::AddressSpace;
|
||||||
buffers::{IntoId, KernelBuffer, KernelBufferAllocator},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) fn print_char(chr: char) {
|
pub(crate) fn print_char(chr: char) {
|
||||||
syscall1(0, chr as u64);
|
syscall1(0, chr as u64);
|
||||||
|
Loading…
Reference in New Issue
Block a user