abi: change set/get_thread/process_option()

This commit is contained in:
Mark Poliakov 2025-01-12 14:42:52 +02:00
parent 26d8b9b3bd
commit 9fa940f011
28 changed files with 458 additions and 435 deletions

View File

@ -24,7 +24,11 @@ use libk_util::{
};
use yggdrasil_abi::{
error::Error,
process::{ExitCode, ProcessGroupId, ProcessId, Signal, ThreadSpawnOptions, WaitFlags},
option::OptionValue,
process::{
options::ProcessOptionVariant, ExitCode, ProcessGroupId, ProcessId, Signal,
ThreadSpawnOptions, WaitFlags,
},
};
use crate::{
@ -281,6 +285,43 @@ impl Process {
// unreachable!()
}
pub fn get_option(
&self,
option: ProcessOptionVariant,
buffer: &mut [u8],
) -> Result<usize, Error> {
use yggdrasil_abi::process::options;
match option {
ProcessOptionVariant::Name => options::Name::store(&self.name.as_str(), buffer),
ProcessOptionVariant::Directory => {
let io = self.io.lock();
let path = io.ioctx().cwd_path();
options::Directory::store(&path.as_str(), buffer)
}
ProcessOptionVariant::SignalEntry => {
options::SignalEntry::store(&self.signal_entry(), buffer)
}
}
}
pub fn set_option(&self, option: ProcessOptionVariant, buffer: &[u8]) -> Result<(), Error> {
use yggdrasil_abi::process::options;
match option {
ProcessOptionVariant::Name => Err(Error::ReadOnly),
ProcessOptionVariant::Directory => {
let value = options::Directory::load(buffer)?;
let mut io = self.io.lock();
io.ioctx_mut().set_cwd(value)
}
ProcessOptionVariant::SignalEntry => {
let value = options::SignalEntry::load(buffer)?;
self.set_signal_entry(value);
Ok(())
}
}
}
/// Returns the address space of the process
pub fn space(&self) -> Arc<ProcessAddressSpace> {
self.inner.read().space.clone().unwrap()

View File

@ -20,7 +20,11 @@ use yggdrasil_abi::{
arch::SavedFrame,
debug::DebugFrame,
error::Error,
process::{ExitCode, ProcessId, Signal, SignalEntryData},
option::OptionValue,
process::{
thread::{ThreadOptionVariant, ThreadSignalStack},
ExitCode, ProcessId, Signal, SignalEntryData,
},
};
use crate::task::{
@ -54,14 +58,8 @@ pub struct ThreadDebuggingInfo {
pub breakpoints: BTreeMap<usize, BreakpointType>,
}
#[derive(Default, Clone, Copy, Debug)]
pub struct SignalStack {
pub base: usize,
pub size: usize,
}
pub struct ThreadInfo {
pub signal_stack: SignalStack,
pub signal_stack: ThreadSignalStack,
}
/// Describes a single thread within the system
@ -136,7 +134,7 @@ impl Thread {
space,
info: IrqSafeRwLock::new(ThreadInfo {
signal_stack: SignalStack::default(),
signal_stack: ThreadSignalStack::default(),
}),
signal_queue: SegQueue::new(),
exit: Arc::new(BoolEvent::new()),
@ -177,6 +175,51 @@ impl Thread {
)
}
pub fn get_option(
&self,
option: ThreadOptionVariant,
buffer: &mut [u8],
) -> Result<usize, Error> {
use yggdrasil_abi::process::thread as options;
match option {
ThreadOptionVariant::Name => {
let name = self.name.read();
options::Name::store(&name.as_str(), buffer)
}
ThreadOptionVariant::SignalStack => {
options::SignalStack::store(&self.signal_stack(), buffer)
}
// There're better ways to do this, don't ask the kernel
ThreadOptionVariant::ThreadPointer => Err(Error::InvalidOperation),
}
}
pub fn set_option(&self, option: ThreadOptionVariant, buffer: &[u8]) -> Result<(), Error> {
use yggdrasil_abi::process::thread as options;
match option {
ThreadOptionVariant::Name => {
let value = options::Name::load(buffer)?;
self.set_name(value);
Ok(())
}
ThreadOptionVariant::SignalStack => {
let value = options::SignalStack::load(buffer)?;
if value.base.checked_add(value.size).is_none() {
return Err(Error::InvalidArgument);
}
self.set_signal_stack(value);
Ok(())
}
ThreadOptionVariant::ThreadPointer => {
let value = options::ThreadPointer::load(buffer)?;
self.set_thread_pointer(value);
Ok(())
}
}
}
/// Sets up arguments on the task's stack, if needed by the ABI.
///
/// # Safety
@ -230,13 +273,13 @@ impl Thread {
}
/// Updates the thread signal stack information
pub fn set_signal_stack(&self, stack: SignalStack) -> SignalStack {
pub fn set_signal_stack(&self, stack: ThreadSignalStack) -> ThreadSignalStack {
let mut info = self.info.write();
core::mem::replace(&mut info.signal_stack, stack)
}
/// Returns the currently set signal stack
pub fn signal_stack(&self) -> SignalStack {
pub fn signal_stack(&self) -> ThreadSignalStack {
self.info.read().signal_stack
}

View File

@ -116,7 +116,7 @@ pub fn global_control(option: u32, buffer: &mut [u8], len: usize) -> Result<usiz
}
}?;
return Ok(0);
Ok(0)
}
}
}

View File

@ -10,11 +10,12 @@ pub(crate) use abi::{
mem::{MappingFlags, MappingSource},
net::{SocketShutdown, SocketType},
process::{Signal, SignalEntryData, SpawnOptions, WaitFlags},
system::SystemInfo,
};
use abi::{
option::OptionValue,
path::Path,
process::{ExecveOptions, ProcessId},
system::{self, SystemInfoVariant},
time::{ClockType, SystemTime},
};
use libk::{
@ -65,12 +66,10 @@ pub(crate) fn get_clock(ty: ClockType, value: &mut MaybeUninit<SystemTime>) -> R
Ok(())
}
pub(crate) fn get_system_info(element: &mut SystemInfo) -> Result<(), Error> {
match element {
SystemInfo::MemoryStats(stats) => {
*stats = phys::stats();
Ok(())
}
pub(crate) fn get_system_info(option: u32, buffer: &mut [u8]) -> Result<usize, Error> {
let option = SystemInfoVariant::try_from(option)?;
match option {
SystemInfoVariant::MemoryUsage => system::MemoryUsage::store(&phys::stats(), buffer),
}
}

View File

@ -1,25 +1,19 @@
use core::{
mem::MaybeUninit, num::NonZeroUsize, str::FromStr, sync::atomic::AtomicU32, time::Duration,
};
use core::{mem::MaybeUninit, num::NonZeroUsize, sync::atomic::AtomicU32, time::Duration};
use abi::{
error::Error,
mem::{MappingFlags, MappingSource},
process::{
ExitCode, MutexOperation, ProcessGroupId, ProcessId, ProcessOption, ProcessWait, Signal,
SpawnFlags, SpawnOption, SpawnOptions, ThreadOption, ThreadSpawnOptions, WaitFlags,
options::ProcessOptionVariant, thread::ThreadOptionVariant, ExitCode, MutexOperation,
ProcessGroupId, ProcessId, ProcessWait, Signal, SpawnFlags, SpawnOption, SpawnOptions,
ThreadSpawnOptions, WaitFlags,
},
util::FixedString,
};
use alloc::sync::Arc;
use libk::{
block,
task::{
binary::LoadOptions,
debug::ThreadDebugger,
process::Process,
runtime,
thread::{SignalStack, Thread},
binary::LoadOptions, debug::ThreadDebugger, process::Process, runtime, thread::Thread,
ThreadId,
},
time::monotonic_time,
@ -330,78 +324,28 @@ pub(crate) fn wait_thread(id: u32) -> Result<(), Error> {
block!(process.wait_for_thread(tid).await)?
}
pub(crate) fn get_thread_option(option: &mut ThreadOption) -> Result<(), Error> {
pub(crate) fn get_thread_option(option: u32, buffer: &mut [u8]) -> Result<usize, Error> {
let option = ThreadOptionVariant::try_from(option)?;
let thread = Thread::current();
match option {
// There're better ways to do this, don't ask the kernel
ThreadOption::ThreadPointer(_) => Err(Error::InvalidOperation),
ThreadOption::SignalStack(base, size) => {
let stack = thread.signal_stack();
*base = stack.base;
*size = stack.size;
Ok(())
}
ThreadOption::Name(_) => todo!(),
}
thread.get_option(option, buffer)
}
pub(crate) fn set_thread_option(option: &mut ThreadOption) -> Result<(), Error> {
pub(crate) fn set_thread_option(option: u32, buffer: &[u8]) -> Result<(), Error> {
let option = ThreadOptionVariant::try_from(option)?;
let thread = Thread::current();
match option {
ThreadOption::ThreadPointer(tp) => {
log::debug!("{:?}: set thread pointer: {:#x}", thread.id, tp);
thread.set_thread_pointer(*tp);
Ok(())
}
ThreadOption::SignalStack(base, size) => {
if base.checked_add(*size).is_none() {
return Err(Error::InvalidArgument);
}
let old = thread.set_signal_stack(SignalStack {
base: *base,
size: *size,
});
*base = old.base;
*size = old.size;
Ok(())
}
ThreadOption::Name(name) => {
// Make a kernel-owned string
log::debug!("{:?}: set thread name: {name:?}", thread.id);
thread.set_name(*name);
Ok(())
}
}
thread.set_option(option, buffer)
}
pub(crate) fn get_process_option(option: &mut ProcessOption) -> Result<(), Error> {
pub(crate) fn get_process_option(option: u32, buffer: &mut [u8]) -> Result<usize, Error> {
let option = ProcessOptionVariant::try_from(option)?;
let thread = Thread::current();
let process = thread.process();
match option {
ProcessOption::SignalEntry(entry) => {
*entry = process.signal_entry();
Ok(())
}
ProcessOption::Directory(dst) => run_with_io(&process, |io| {
let path = io.ioctx().cwd_path();
*dst = FixedString::from_str(path.as_str())?;
Ok(())
}),
}
process.get_option(option, buffer)
}
pub(crate) fn set_process_option(option: &mut ProcessOption) -> Result<(), Error> {
pub(crate) fn set_process_option(option: u32, buffer: &[u8]) -> Result<(), Error> {
let option = ProcessOptionVariant::try_from(option)?;
let thread = Thread::current();
let process = thread.process();
match option {
ProcessOption::SignalEntry(entry) => {
*entry = process.set_signal_entry(*entry);
Ok(())
}
ProcessOption::Directory(path) => run_with_io(&process, |mut io| {
let path = path.as_ref();
io.ioctx_mut().set_cwd(path)?;
Ok(())
}),
}
process.set_option(option, buffer)
}

View File

@ -29,10 +29,12 @@ impl_primitive_serde!(
i16: [read_i16, write_i16],
i32: [read_i32, write_i32],
i64: [read_i64, write_i64],
isize: [read_isize, write_isize],
u8: [read_u8, write_u8],
u16: [read_u16, write_u16],
u32: [read_u32, write_u32],
u64: [read_u64, write_u64]
u64: [read_u64, write_u64],
usize: [read_usize, write_usize]
);
impl Serialize for () {
@ -49,6 +51,39 @@ impl<'de> Deserialize<'de> for () {
}
}
impl Serialize for &str {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_str(self)
}
}
impl<'de> Deserialize<'de> for &'de str {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
deserializer.read_str()
}
}
impl<const N: usize> Serialize for [u8; N]
where
[u8; N]: Sized,
{
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_bytes(self)
}
}
impl<'de, const N: usize> Deserialize<'de> for [u8; N]
where
[u8; N]: Sized,
{
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
deserializer
.read_bytes()?
.try_into()
.map_err(|_| D::Error::INVALID_ARRAY_LEN)
}
}
impl<T: Serialize> Serialize for Option<T> {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
match self {

View File

@ -70,52 +70,11 @@ impl Serialize for SocketAddrV6 {
}
}
impl<'de> Deserialize<'de> for IpAddr {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
match deserializer.read_enum_variant()? {
4 => Ipv4Addr::deserialize(deserializer).map(Self::V4),
6 => Ipv6Addr::deserialize(deserializer).map(Self::V6),
_ => Err(D::Error::INVALID_ENUM_VARIANT),
}
}
}
impl<'de> Deserialize<'de> for SocketAddr {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
match deserializer.read_enum_variant()? {
4 => SocketAddrV4::deserialize(deserializer).map(Self::V4),
6 => SocketAddrV6::deserialize(deserializer).map(Self::V6),
_ => Err(D::Error::INVALID_ENUM_VARIANT),
}
}
}
impl Serialize for IpAddr {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
match self {
Self::V4(v4) => {
serializer.write_enum_variant(4)?;
v4.serialize(serializer)
}
Self::V6(v6) => {
serializer.write_enum_variant(6)?;
v6.serialize(serializer)
}
}
}
}
impl Serialize for SocketAddr {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
match self {
Self::V4(v4) => {
serializer.write_enum_variant(4)?;
v4.serialize(serializer)
}
Self::V6(v6) => {
serializer.write_enum_variant(6)?;
v6.serialize(serializer)
}
}
}
}
crate::impl_enum_serde!(IpAddr: [
V4 => 4,
V6 => 6
]);
crate::impl_enum_serde!(SocketAddr: [
V4 => 4,
V6 => 6
]);

View File

@ -10,3 +10,86 @@ pub mod wire;
pub use des::Deserialize;
pub use ser::Serialize;
#[macro_export]
macro_rules! impl_enum_serde {
(
$name:ident $(<$lifetime:lifetime>)? : [
$(
$variant:ident => $discriminant:literal
),* $(,)?
]
) => {
impl $(<$lifetime>)? $crate::Serialize for $name $(<$lifetime>)? {
fn serialize<S: $crate::ser::Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
match self {
$(
Self::$variant(value) => {
serializer.write_enum_variant($discriminant)?;
$crate::Serialize::serialize(value, serializer)
}
)*
}
}
}
impl<'de> $crate::Deserialize<'de> for $name $(<$lifetime>)? {
fn deserialize<D: $crate::des::Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
let variant = deserializer.read_enum_variant()?;
match variant {
$(
$discriminant => $crate::Deserialize::deserialize(deserializer).map(Self::$variant),
)*
_ => Err(<D::Error as $crate::des::DeserializeError>::INVALID_ENUM_VARIANT)
}
}
}
};
}
#[macro_export]
macro_rules! impl_struct_serde {
(
$name:ident $(<$lifetime:lifetime>)? : [$($field:ident),* $(,)?]
) => {
impl $(<$lifetime>)? $crate::Serialize for $name $(<$lifetime>)? {
fn serialize<S: $crate::ser::Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
$(
$crate::Serialize::serialize(&self.$field, serializer)?;
)*
Ok(())
}
}
impl<'de> $crate::Deserialize<'de> for $name $(<$lifetime:lifetime>)? {
fn deserialize<D: $crate::des::Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
$(
let $field = $crate::Deserialize::deserialize(deserializer)?;
)*
Ok(Self {$($field),*})
}
}
}
}
#[macro_export]
macro_rules! impl_newtype_serde {
($name:ident) => {
impl $crate::Serialize for $name {
fn serialize<S: $crate::ser::Serializer>(
&self,
serializer: &mut S,
) -> Result<(), S::Error> {
$crate::Serialize::serialize(&self.0, serializer)
}
}
impl<'de> $crate::Deserialize<'de> for $name {
fn deserialize<D: $crate::des::Deserializer<'de>>(
deserializer: &mut D,
) -> Result<Self, D::Error> {
$crate::Deserialize::deserialize(deserializer).map(Self)
}
}
};
}

View File

@ -11,14 +11,10 @@ extern {
// TODO "tagged union" enums are not yet implemented
type MappingSource;
type SystemInfo = yggdrasil_abi::system::SystemInfo;
type SignalEntryData = yggdrasil_abi::process::SignalEntryData;
type MutexOperation = yggdrasil_abi::process::MutexOperation;
#[thin]
type ExitCode = yggdrasil_abi::process::ExitCode;
type ThreadOption = yggdrasil_abi::process::ThreadOption;
type ProcessOption = yggdrasil_abi::process::ProcessOption;
type ProcessWait = yggdrasil_abi::process::ProcessWait;
type SocketAddr = core::net::SocketAddr;
@ -72,12 +68,14 @@ bitfield MappingFlags(u32) {
syscall get_random(buffer: &mut [u8]);
syscall get_clock(clock: ClockType, out: &mut MaybeUninit<SystemTime>) -> Result<()>;
syscall get_system_info(info: &mut SystemInfo) -> Result<()>;
syscall mount(opts: &MountOptions<'_>) -> Result<()>;
syscall unmount(opts: &UnmountOptions) -> Result<()>;
syscall load_module(path: &str) -> Result<()>;
syscall filesystem_control(fd: Option<RawFd>, option: u32, value: &mut [u8], len: usize) -> Result<usize>;
syscall get_system_info(option: u32, value: &mut [u8]) -> Result<usize>;
// Memory management
syscall map_memory(
hint: Option<NonZeroUsize>,
@ -101,10 +99,10 @@ syscall get_tid() -> u32;
syscall spawn_thread(options: &ThreadSpawnOptions) -> Result<u32>;
syscall exit_thread() -> !;
syscall wait_thread(tid: u32) -> Result<()>;
syscall get_thread_option(option: &mut ThreadOption<'_>) -> Result<()>;
syscall set_thread_option(option: &mut ThreadOption<'_>) -> Result<()>;
syscall get_process_option(option: &mut ProcessOption) -> Result<()>;
syscall set_process_option(option: &mut ProcessOption) -> Result<()>;
syscall get_thread_option(option: u32, value: &mut [u8]) -> Result<usize>;
syscall set_thread_option(option: u32, value: &[u8]) -> Result<()>;
syscall get_process_option(option: u32, value: &mut [u8]) -> Result<usize>;
syscall set_process_option(option: u32, value: &[u8]) -> Result<()>;
syscall nanosleep(duration: &Duration, remaining: &mut MaybeUninit<Duration>) -> Result<()>;

View File

@ -1,5 +1,4 @@
//! Device data structures and options
use abi_serde::{des::Deserializer, ser::Serializer, Deserialize, Serialize};
use crate::{io::terminal, process::ProcessGroupId};
@ -56,27 +55,6 @@ request_group!(
}
);
impl<'de> Deserialize<'de> for Framebuffer {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
let width = deserializer.read_u32()?;
let height = deserializer.read_u32()?;
let stride = deserializer.read_usize()?;
let size = deserializer.read_usize()?;
Ok(Self {
width,
height,
stride,
size,
})
}
}
impl Serialize for Framebuffer {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_u32(self.width)?;
serializer.write_u32(self.height)?;
serializer.write_usize(self.stride)?;
serializer.write_usize(self.size)?;
Ok(())
}
}
abi_serde::impl_struct_serde!(Framebuffer: [
width, height, stride, size
]);

View File

@ -1,5 +1,3 @@
use abi_serde::{des::Deserializer, ser::Serializer, Deserialize, Serialize};
pub use crate::generated::{
TerminalControlCharacters, TerminalInputOptions, TerminalLineOptions, TerminalOptions,
TerminalOutputOptions, TerminalSize,
@ -65,107 +63,15 @@ impl Default for TerminalOptions {
}
}
impl<'de> Deserialize<'de> for TerminalLineOptions {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
Ok(unsafe { Self::from_raw(deserializer.read_u32()?) })
}
}
impl Serialize for TerminalLineOptions {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_u32(self.bits())
}
}
impl<'de> Deserialize<'de> for TerminalInputOptions {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
Ok(unsafe { Self::from_raw(deserializer.read_u32()?) })
}
}
impl Serialize for TerminalInputOptions {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_u32(self.bits())
}
}
impl<'de> Deserialize<'de> for TerminalOutputOptions {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
Ok(unsafe { Self::from_raw(deserializer.read_u32()?) })
}
}
impl Serialize for TerminalOutputOptions {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_u32(self.bits())
}
}
impl<'de> Deserialize<'de> for TerminalControlCharacters {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
let eof = deserializer.read_u8()?;
let interrupt = deserializer.read_u8()?;
let erase = deserializer.read_u8()?;
let werase = deserializer.read_u8()?;
let kill = deserializer.read_u8()?;
Ok(Self {
eof,
interrupt,
erase,
werase,
kill,
})
}
}
impl Serialize for TerminalControlCharacters {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_u8(self.eof)?;
serializer.write_u8(self.interrupt)?;
serializer.write_u8(self.erase)?;
serializer.write_u8(self.werase)?;
serializer.write_u8(self.kill)?;
Ok(())
}
}
impl<'de> Deserialize<'de> for TerminalOptions {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
let line = TerminalLineOptions::deserialize(deserializer)?;
let input = TerminalInputOptions::deserialize(deserializer)?;
let output = TerminalOutputOptions::deserialize(deserializer)?;
let chars = TerminalControlCharacters::deserialize(deserializer)?;
Ok(Self {
line,
input,
output,
chars,
})
}
}
impl Serialize for TerminalOptions {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
self.line.serialize(serializer)?;
self.input.serialize(serializer)?;
self.output.serialize(serializer)?;
self.chars.serialize(serializer)?;
Ok(())
}
}
impl<'de> Deserialize<'de> for TerminalSize {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
let rows = deserializer.read_usize()?;
let columns = deserializer.read_usize()?;
Ok(Self { rows, columns })
}
}
impl Serialize for TerminalSize {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_usize(self.rows)?;
serializer.write_usize(self.columns)?;
Ok(())
}
}
abi_serde::impl_newtype_serde!(TerminalLineOptions);
abi_serde::impl_newtype_serde!(TerminalInputOptions);
abi_serde::impl_newtype_serde!(TerminalOutputOptions);
abi_serde::impl_struct_serde!(TerminalControlCharacters: [
eof, kill, erase, werase, interrupt
]);
abi_serde::impl_struct_serde!(TerminalOptions: [
line, input, output, chars
]);
abi_serde::impl_struct_serde!(TerminalSize: [
rows, columns
]);

View File

@ -1,11 +1,5 @@
//! Defines data types for network operations
use abi_serde::{
des::{DeserializeError, Deserializer},
ser::Serializer,
Deserialize, Serialize,
};
#[cfg(any(feature = "alloc", feature = "rustc_std_alloc"))]
pub mod dns;
#[cfg(feature = "alloc")]
@ -46,30 +40,10 @@ impl From<u32> for SocketInterfaceQuery<'_> {
}
}
impl<'de> Deserialize<'de> for SocketInterfaceQuery<'de> {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
match deserializer.read_enum_variant()? {
1 => deserializer.read_u32().map(Self::ById),
2 => deserializer.read_str().map(Self::ByName),
_ => Err(D::Error::INVALID_ENUM_VARIANT),
}
}
}
impl Serialize for SocketInterfaceQuery<'_> {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
match *self {
Self::ById(id) => {
serializer.write_enum_variant(1)?;
serializer.write_u32(id)
}
Self::ByName(name) => {
serializer.write_enum_variant(2)?;
serializer.write_str(name)
}
}
}
}
abi_serde::impl_enum_serde!(SocketInterfaceQuery<'de>: [
ById => 1,
ByName => 2
]);
#[cfg(test)]
mod tests {

View File

@ -2,12 +2,6 @@
use core::fmt;
use abi_serde::{
des::{DeserializeError, Deserializer},
ser::Serializer,
Deserialize, Serialize,
};
pub mod ip_addr;
pub mod net_value;
pub mod socket_addr;
@ -54,18 +48,4 @@ impl fmt::Display for MacAddress {
}
}
impl<'de> Deserialize<'de> for MacAddress {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
deserializer
.read_bytes()?
.try_into()
.map_err(|_| D::Error::INVALID_ARRAY_LEN)
.map(Self)
}
}
impl Serialize for MacAddress {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_bytes(&self.0)
}
}
abi_serde::impl_newtype_serde!(MacAddress);

View File

@ -2,21 +2,17 @@
use core::{ffi::CStr, fmt, marker::PhantomData, time::Duration};
use crate::{
io::{FileMode, RawFd},
util::FixedString,
};
use crate::io::{FileMode, RawFd};
mod exit;
pub mod options;
pub mod thread;
pub use crate::generated::{
ExecveOptions, ProcessGroupId, ProcessId, Signal, SignalEntryData, SpawnFlags, SpawnOptions,
ThreadId, ThreadSpawnOptions, WaitFlags,
};
use abi_serde::{des::Deserializer, ser::Serializer, Deserialize, Serialize};
pub use exit::ExitCode;
pub use thread::ThreadOption;
// TODO this is ugly
pub mod auxv {
@ -47,16 +43,6 @@ pub enum ProcessWait {
AnyChild,
}
/// Represents a process option being set/retrieved
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum ProcessOption {
/// Signal entry point address
SignalEntry(usize),
/// Current working directory
Directory(FixedString<4096>),
}
/// Defines an optional argument for controlling process creation
#[derive(Debug)]
pub enum SpawnOption {
@ -229,14 +215,5 @@ impl Signal {
}
}
impl<'de> Deserialize<'de> for ProcessGroupId {
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
deserializer.read_u32().map(Self)
}
}
impl Serialize for ProcessGroupId {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.write_u32(self.0)
}
}
abi_serde::impl_newtype_serde!(ProcessGroupId);
abi_serde::impl_newtype_serde!(ProcessId);

View File

@ -0,0 +1,13 @@
//! Process option definitions
option_group!(
#[doc = "Process options"]
pub enum ProcessOptionVariant<'a> {
#[doc = "Process signal entry point address"]
0x1000: SignalEntry # 8 (usize),
#[doc = "Current working directory"]
0x1001: Directory(&'a str),
#[doc = "Process name"]
0x1002: Name(&'a str)
}
);

View File

@ -1,12 +1,24 @@
//! Thread data structures
//! Thread option definitions
/// Represents a thread option being set/retrieved
#[derive(Debug)]
pub enum ThreadOption<'a> {
/// Thread-local storage base pointer
ThreadPointer(usize),
/// Thread signal entry stack base and size
SignalStack(usize, usize),
/// Thread display name
Name(&'a str),
/// Thread signal stack
#[derive(Clone, Copy, Debug, Default)]
pub struct ThreadSignalStack {
/// Base address
pub base: usize,
/// Size
pub size: usize,
}
option_group!(
#[doc = "Thread options"]
pub enum ThreadOptionVariant<'a> {
#[doc = "Thread-local storage pointer"]
0x1000: ThreadPointer # 8(usize),
#[doc = "Signal stack information"]
0x1001: SignalStack # 16(ThreadSignalStack),
#[doc = "Thread display name"]
0x1002: Name(&'a str),
}
);
abi_serde::impl_struct_serde!(ThreadSignalStack: [base, size]);

View File

@ -13,9 +13,14 @@ pub struct SystemMemoryStats {
pub page_size: usize,
}
/// Describes a piece of system information
#[derive(Clone, Debug)]
pub enum SystemInfo {
/// Memory usage stats
MemoryStats(SystemMemoryStats),
option_group!(
#[doc = "System information requests"]
pub enum SystemInfoVariant<'de> {
#[doc = "Memory usage information"]
0x1000: MemoryUsage # 64 (SystemMemoryStats),
}
);
abi_serde::impl_struct_serde!(
SystemMemoryStats: [total_usable_pages, allocated_pages, free_pages, page_size]
);

View File

@ -1,8 +1,8 @@
use core::str::FromStr;
use abi::{error::Error, process::ProcessOption, util::FixedString};
use abi::error::Error;
use alloc::string::String;
use crate::process;
pub fn current_exe<T, F: FnOnce(&str) -> T>(_mapper: F) -> Result<T, Error> {
todo!()
}
@ -12,13 +12,9 @@ pub fn home_directory<T, F: FnOnce(&str) -> T>(_mapper: F) -> Result<T, Error> {
}
pub fn current_directory<T, F: FnOnce(&str) -> T>(mapper: F) -> Result<T, Error> {
let mut option = ProcessOption::Directory(FixedString::empty());
unsafe { crate::sys::get_process_option(&mut option) }?;
let ProcessOption::Directory(path) = &option else {
unreachable!()
};
Ok(mapper(path.as_ref()))
let mut buffer = [0; 512];
let path = process::get_process_option::<process::options::Directory>(&mut buffer)?;
Ok(mapper(path))
}
pub fn current_directory_string() -> Result<String, Error> {
@ -26,9 +22,8 @@ pub fn current_directory_string() -> Result<String, Error> {
}
pub fn set_current_directory(path: &str) -> Result<(), Error> {
let mut option = ProcessOption::Directory(FixedString::from_str(path)?);
unsafe { crate::sys::set_process_option(&mut option) }?;
Ok(())
let mut buffer = [0; 512];
process::set_process_option_with::<process::options::Directory>(&mut buffer, &path)
}
pub fn make_temp_directory(_template: &mut [u8]) -> Result<(), Error> {

View File

@ -30,7 +30,7 @@ pub fn get_terminal_size(fd: RawFd) -> Result<TerminalSize, Error> {
}
pub fn set_terminal_size(fd: RawFd, size: &TerminalSize) -> Result<(), Error> {
let mut buffer = [0; 32];
device_request::<device::SetTerminalSize>(fd, &mut buffer, &size)
device_request::<device::SetTerminalSize>(fd, &mut buffer, size)
}
pub fn is_terminal(fd: RawFd) -> bool {

View File

@ -32,10 +32,5 @@ pub mod net;
pub mod process;
pub mod sync;
pub mod sys;
pub mod system;
pub mod time;
pub mod system {
//! System-related data structures
pub use abi::system::*;
}

View File

@ -2,12 +2,15 @@
use core::{mem::MaybeUninit, time::Duration};
use abi::error::Error;
pub use abi::process::{
auxv, AuxValue, AuxValueIter, ExecveOptions, ExitCode, MutexOperation, ProcessGroupId,
ProcessId, ProcessInfoElement, ProcessWait, ProgramArgumentInner, Signal, SignalEntryData,
SpawnFlags, SpawnOption, SpawnOptions, StringArgIter, ThreadId, ThreadSpawnOptions, WaitFlags,
};
use abi::{
error::Error,
option::{OptionSizeHint, OptionValue},
};
use crate::sys;
@ -15,6 +18,8 @@ pub mod signal;
pub mod thread;
pub mod thread_local;
pub use abi::process::options;
/// Makes the current thread wait until *at least* the amount of time specified in `duration`
/// passes.
///
@ -39,3 +44,71 @@ pub fn uninterruptible_sleep(mut duration: Duration) {
}
}
}
/// Helper macro for [get_process_option].
pub macro get_process_option($variant_ty:ty) {{
let mut buffer = [0; <$variant_ty as $crate::io::OptionSizeHint>::SIZE_HINT];
$crate::process::get_process_option::<$variant_ty>(&mut buffer)
}}
/// Retrieves a process option value.
pub fn get_process_option<'de, T: OptionValue<'de>>(
buffer: &'de mut [u8],
) -> Result<T::Value, Error> {
let len = unsafe { crate::sys::get_process_option(T::VARIANT.into(), buffer) }?;
T::load(&buffer[..len])
}
/// Helper macro for [get_thread_option].
pub macro get_thread_option($variant_ty:ty) {{
let mut buffer = [0; <$variant_ty as $crate::io::OptionSizeHint>::SIZE_HINT];
$crate::process::get_thread_option::<$variant_ty>(&mut buffer)
}}
/// Retrieves a thread option value.
pub fn get_thread_option<'de, T: OptionValue<'de>>(
buffer: &'de mut [u8],
) -> Result<T::Value, Error> {
let len = unsafe { crate::sys::get_thread_option(T::VARIANT.into(), buffer) }?;
T::load(&buffer[..len])
}
/// Update a process option value. Requires `T`: [OptionSizeHint].
pub fn set_process_option<'de, T: OptionValue<'de> + OptionSizeHint>(
value: &T::Value,
) -> Result<(), Error>
where
[u8; T::SIZE_HINT]: Sized,
{
let mut buffer = [0; T::SIZE_HINT];
set_process_option_with::<T>(&mut buffer, value)
}
/// Update a process option value, using provided buffer for serialization.
pub fn set_process_option_with<'de, T: OptionValue<'de>>(
buffer: &mut [u8],
value: &T::Value,
) -> Result<(), Error> {
let len = T::store(value, buffer)?;
unsafe { crate::sys::set_process_option(T::VARIANT.into(), &buffer[..len]) }
}
/// Update a thread option value. Requires `T`: [OptionSizeHint].
pub fn set_thread_option<'de, T: OptionValue<'de> + OptionSizeHint>(
value: &T::Value,
) -> Result<(), Error>
where
[u8; T::SIZE_HINT]: Sized,
{
let mut buffer = [0; T::SIZE_HINT];
set_thread_option_with::<T>(&mut buffer, value)
}
/// Update a thread option value, using provided buffer for serialization.
pub fn set_thread_option_with<'de, T: OptionValue<'de>>(
buffer: &mut [u8],
value: &T::Value,
) -> Result<(), Error> {
let len = T::store(value, buffer)?;
unsafe { crate::sys::set_thread_option(T::VARIANT.into(), &buffer[..len]) }
}

View File

View File

@ -4,10 +4,13 @@ use core::ffi::c_int;
use abi::{
error::Error,
mem::{MappingFlags, MappingSource},
process::{ExitCode, ProcessOption, Signal, SignalEntryData, ThreadOption},
process::{ExitCode, Signal, SignalEntryData},
};
use crate::sync::rwlock::RwLock;
use crate::{
process::{self, thread},
sync::rwlock::RwLock,
};
/// Describes how a signal should be handled
#[derive(Debug, Clone, Copy)]
@ -76,23 +79,18 @@ pub unsafe fn set_handler(signal: Signal, handler: SignalHandler) -> SignalHandl
/// below it. It is up to the caller to make sure `sp` points to a proper stack's top.
///
/// TLDR: just use [setup_signal_stack].
pub unsafe fn set_signal_stack(base: usize, size: usize) -> (usize, usize) {
let mut option = ThreadOption::SignalStack(base, size);
crate::sys::set_thread_option(&mut option).expect("set_signal_stack() failed");
let ThreadOption::SignalStack(base, size) = option else {
unreachable!()
};
(base, size)
pub unsafe fn set_signal_stack(base: usize, size: usize) {
process::set_thread_option::<thread::options::SignalStack>(
&thread::options::ThreadSignalStack { base, size },
)
.expect("set_signal_stack() failed")
}
/// Returns the currently set signal stack base:size.
pub fn get_signal_stack() -> (usize, usize) {
let mut option = ThreadOption::SignalStack(0, 0);
unsafe { crate::sys::get_thread_option(&mut option) }.expect("get_signal_stack() failed");
let ThreadOption::SignalStack(base, size) = option else {
unreachable!()
};
(base, size)
let stack = process::get_thread_option!(thread::options::SignalStack)
.expect("get_signal_stack() failed");
(stack.base, stack.size)
}
/// Sets the program's signal entry function.
@ -103,15 +101,9 @@ pub fn get_signal_stack() -> (usize, usize) {
///
/// 1. It must not return, it must call `exit_thread` instead.
/// 2. It must conform to the kernel's signal entry ABI.
pub unsafe fn set_signal_entry(entry: usize) -> usize {
let mut option = ProcessOption::SignalEntry(entry);
crate::sys::set_process_option(&mut option).expect("set_signal_entry() failed");
#[allow(irrefutable_let_patterns)]
let ProcessOption::SignalEntry(entry) = option
else {
unreachable!()
};
entry
pub unsafe fn set_signal_entry(entry: usize) {
process::set_process_option::<process::options::SignalEntry>(&entry)
.expect("set_signal_entry() failed");
}
fn allocate_signal_stack(mut size: usize) -> Result<(usize, usize), Error> {

View File

@ -8,7 +8,7 @@ use core::{
use abi::{
error::Error,
mem::{MappingFlags, MappingSource},
process::{ThreadOption, ThreadSpawnOptions},
process::ThreadSpawnOptions,
};
use alloc::{boxed::Box, sync::Arc};
@ -16,6 +16,11 @@ use crate::{process::thread_local, sync::rwlock::RwLock};
use super::{signal, thread_local::TlsImage};
pub mod options {
//! Thread option definitions
pub use abi::process::thread::*;
}
/// Describes a runtime thread.
///
/// `R` generic parameter denotes the thread's return type.
@ -135,7 +140,8 @@ impl<R> Thread<R> {
/// Sets the current thread name.
pub fn set_name(name: &str) {
unsafe { crate::sys::set_thread_option(&mut ThreadOption::Name(name)).ok() };
let mut buffer = [0; 256];
crate::process::set_thread_option_with::<options::Name>(&mut buffer, &name).ok();
}
/// # Safety

View File

@ -1,6 +1,8 @@
#![allow(missing_docs)]
use abi::{error::Error, process::ThreadOption};
use abi::error::Error;
use crate::process::{self, thread};
pub fn get_thread_pointer() -> usize {
let tp: usize;
@ -17,7 +19,7 @@ pub fn get_thread_pointer() -> usize {
/// `value` must hold an address to a structure, first element of which is a pointer to itself.
/// Usual pointer safety requirements apply.
pub unsafe fn set_thread_pointer(value: usize) -> Result<(), Error> {
crate::sys::set_thread_option(&mut ThreadOption::ThreadPointer(value))
process::set_process_option::<thread::options::ThreadPointer>(&value)
}
// ___tls_get_addr, TLS_index structure address gets passed in the %eax register

View File

@ -1,6 +1,6 @@
#![allow(missing_docs)]
use abi::{error::Error, process::ThreadOption};
use abi::{error::Error, process::thread};
pub fn get_thread_pointer() -> usize {
let tp: usize;
@ -17,5 +17,5 @@ pub fn get_thread_pointer() -> usize {
/// `value` must hold an address to a structure, first element of which is a pointer to itself.
/// Usual pointer safety requirements apply.
pub unsafe fn set_thread_pointer(value: usize) -> Result<(), Error> {
crate::sys::set_thread_option(&mut ThreadOption::ThreadPointer(value))
crate::process::set_thread_option::<thread::ThreadPointer>(&value)
}

16
lib/runtime/src/system.rs Normal file
View File

@ -0,0 +1,16 @@
//! System-related parameters
pub use abi::system::*;
use abi::{error::Error, option::OptionValue};
/// Helper macro for [get_system_info]
pub macro get_system_info($variant_ty:ty) {{
let mut buffer = [0; <$variant_ty as $crate::io::OptionSizeHint>::SIZE_HINT];
$crate::system::get_system_info::<$variant_ty>(&mut buffer)
}}
/// Retrieves a system information object
pub fn get_system_info<'de, T: OptionValue<'de>>(buffer: &'de mut [u8]) -> Result<T::Value, Error> {
let len = unsafe { crate::sys::get_system_info(T::VARIANT.into(), buffer) }?;
T::load(&buffer[..len])
}

View File

@ -2,18 +2,15 @@
use std::{
collections::VecDeque,
fmt::Write,
os::yggdrasil::{get_system_info, SystemInfo, SystemMemoryStats},
fmt::Write
};
use humansize::FormatSize;
use libterm::{Clear, Term};
use yggdrasil_rt::system;
fn get_memory_stats() -> SystemMemoryStats {
let mut info = SystemInfo::MemoryStats(SystemMemoryStats::default());
get_system_info(&mut info).unwrap();
let SystemInfo::MemoryStats(stats) = info;
stats
fn get_memory_stats() -> system::SystemMemoryStats {
system::get_system_info!(system::MemoryUsage).unwrap()
}
fn main() {