abi: change set/get_thread/process_option()
This commit is contained in:
parent
26d8b9b3bd
commit
9fa940f011
@ -24,7 +24,11 @@ use libk_util::{
|
|||||||
};
|
};
|
||||||
use yggdrasil_abi::{
|
use yggdrasil_abi::{
|
||||||
error::Error,
|
error::Error,
|
||||||
process::{ExitCode, ProcessGroupId, ProcessId, Signal, ThreadSpawnOptions, WaitFlags},
|
option::OptionValue,
|
||||||
|
process::{
|
||||||
|
options::ProcessOptionVariant, ExitCode, ProcessGroupId, ProcessId, Signal,
|
||||||
|
ThreadSpawnOptions, WaitFlags,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -281,6 +285,43 @@ impl Process {
|
|||||||
// unreachable!()
|
// 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
|
/// Returns the address space of the process
|
||||||
pub fn space(&self) -> Arc<ProcessAddressSpace> {
|
pub fn space(&self) -> Arc<ProcessAddressSpace> {
|
||||||
self.inner.read().space.clone().unwrap()
|
self.inner.read().space.clone().unwrap()
|
||||||
|
@ -20,7 +20,11 @@ use yggdrasil_abi::{
|
|||||||
arch::SavedFrame,
|
arch::SavedFrame,
|
||||||
debug::DebugFrame,
|
debug::DebugFrame,
|
||||||
error::Error,
|
error::Error,
|
||||||
process::{ExitCode, ProcessId, Signal, SignalEntryData},
|
option::OptionValue,
|
||||||
|
process::{
|
||||||
|
thread::{ThreadOptionVariant, ThreadSignalStack},
|
||||||
|
ExitCode, ProcessId, Signal, SignalEntryData,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::task::{
|
use crate::task::{
|
||||||
@ -54,14 +58,8 @@ pub struct ThreadDebuggingInfo {
|
|||||||
pub breakpoints: BTreeMap<usize, BreakpointType>,
|
pub breakpoints: BTreeMap<usize, BreakpointType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy, Debug)]
|
|
||||||
pub struct SignalStack {
|
|
||||||
pub base: usize,
|
|
||||||
pub size: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ThreadInfo {
|
pub struct ThreadInfo {
|
||||||
pub signal_stack: SignalStack,
|
pub signal_stack: ThreadSignalStack,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes a single thread within the system
|
/// Describes a single thread within the system
|
||||||
@ -136,7 +134,7 @@ impl Thread {
|
|||||||
space,
|
space,
|
||||||
|
|
||||||
info: IrqSafeRwLock::new(ThreadInfo {
|
info: IrqSafeRwLock::new(ThreadInfo {
|
||||||
signal_stack: SignalStack::default(),
|
signal_stack: ThreadSignalStack::default(),
|
||||||
}),
|
}),
|
||||||
signal_queue: SegQueue::new(),
|
signal_queue: SegQueue::new(),
|
||||||
exit: Arc::new(BoolEvent::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.
|
/// Sets up arguments on the task's stack, if needed by the ABI.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@ -230,13 +273,13 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the thread signal stack information
|
/// 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();
|
let mut info = self.info.write();
|
||||||
core::mem::replace(&mut info.signal_stack, stack)
|
core::mem::replace(&mut info.signal_stack, stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the currently set signal stack
|
/// Returns the currently set signal stack
|
||||||
pub fn signal_stack(&self) -> SignalStack {
|
pub fn signal_stack(&self) -> ThreadSignalStack {
|
||||||
self.info.read().signal_stack
|
self.info.read().signal_stack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ pub fn global_control(option: u32, buffer: &mut [u8], len: usize) -> Result<usiz
|
|||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
return Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,12 @@ pub(crate) use abi::{
|
|||||||
mem::{MappingFlags, MappingSource},
|
mem::{MappingFlags, MappingSource},
|
||||||
net::{SocketShutdown, SocketType},
|
net::{SocketShutdown, SocketType},
|
||||||
process::{Signal, SignalEntryData, SpawnOptions, WaitFlags},
|
process::{Signal, SignalEntryData, SpawnOptions, WaitFlags},
|
||||||
system::SystemInfo,
|
|
||||||
};
|
};
|
||||||
use abi::{
|
use abi::{
|
||||||
|
option::OptionValue,
|
||||||
path::Path,
|
path::Path,
|
||||||
process::{ExecveOptions, ProcessId},
|
process::{ExecveOptions, ProcessId},
|
||||||
|
system::{self, SystemInfoVariant},
|
||||||
time::{ClockType, SystemTime},
|
time::{ClockType, SystemTime},
|
||||||
};
|
};
|
||||||
use libk::{
|
use libk::{
|
||||||
@ -65,12 +66,10 @@ pub(crate) fn get_clock(ty: ClockType, value: &mut MaybeUninit<SystemTime>) -> R
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_system_info(element: &mut SystemInfo) -> Result<(), Error> {
|
pub(crate) fn get_system_info(option: u32, buffer: &mut [u8]) -> Result<usize, Error> {
|
||||||
match element {
|
let option = SystemInfoVariant::try_from(option)?;
|
||||||
SystemInfo::MemoryStats(stats) => {
|
match option {
|
||||||
*stats = phys::stats();
|
SystemInfoVariant::MemoryUsage => system::MemoryUsage::store(&phys::stats(), buffer),
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,19 @@
|
|||||||
use core::{
|
use core::{mem::MaybeUninit, num::NonZeroUsize, sync::atomic::AtomicU32, time::Duration};
|
||||||
mem::MaybeUninit, num::NonZeroUsize, str::FromStr, sync::atomic::AtomicU32, time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use abi::{
|
use abi::{
|
||||||
error::Error,
|
error::Error,
|
||||||
mem::{MappingFlags, MappingSource},
|
mem::{MappingFlags, MappingSource},
|
||||||
process::{
|
process::{
|
||||||
ExitCode, MutexOperation, ProcessGroupId, ProcessId, ProcessOption, ProcessWait, Signal,
|
options::ProcessOptionVariant, thread::ThreadOptionVariant, ExitCode, MutexOperation,
|
||||||
SpawnFlags, SpawnOption, SpawnOptions, ThreadOption, ThreadSpawnOptions, WaitFlags,
|
ProcessGroupId, ProcessId, ProcessWait, Signal, SpawnFlags, SpawnOption, SpawnOptions,
|
||||||
|
ThreadSpawnOptions, WaitFlags,
|
||||||
},
|
},
|
||||||
util::FixedString,
|
|
||||||
};
|
};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use libk::{
|
use libk::{
|
||||||
block,
|
block,
|
||||||
task::{
|
task::{
|
||||||
binary::LoadOptions,
|
binary::LoadOptions, debug::ThreadDebugger, process::Process, runtime, thread::Thread,
|
||||||
debug::ThreadDebugger,
|
|
||||||
process::Process,
|
|
||||||
runtime,
|
|
||||||
thread::{SignalStack, Thread},
|
|
||||||
ThreadId,
|
ThreadId,
|
||||||
},
|
},
|
||||||
time::monotonic_time,
|
time::monotonic_time,
|
||||||
@ -330,78 +324,28 @@ pub(crate) fn wait_thread(id: u32) -> Result<(), Error> {
|
|||||||
block!(process.wait_for_thread(tid).await)?
|
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();
|
let thread = Thread::current();
|
||||||
match option {
|
thread.get_option(option, buffer)
|
||||||
// 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!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
let thread = Thread::current();
|
||||||
match option {
|
thread.set_option(option, buffer)
|
||||||
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 thread = Thread::current();
|
||||||
let process = thread.process();
|
let process = thread.process();
|
||||||
match option {
|
process.get_option(option, buffer)
|
||||||
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(())
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 thread = Thread::current();
|
||||||
let process = thread.process();
|
let process = thread.process();
|
||||||
match option {
|
process.set_option(option, buffer)
|
||||||
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(())
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,12 @@ impl_primitive_serde!(
|
|||||||
i16: [read_i16, write_i16],
|
i16: [read_i16, write_i16],
|
||||||
i32: [read_i32, write_i32],
|
i32: [read_i32, write_i32],
|
||||||
i64: [read_i64, write_i64],
|
i64: [read_i64, write_i64],
|
||||||
|
isize: [read_isize, write_isize],
|
||||||
u8: [read_u8, write_u8],
|
u8: [read_u8, write_u8],
|
||||||
u16: [read_u16, write_u16],
|
u16: [read_u16, write_u16],
|
||||||
u32: [read_u32, write_u32],
|
u32: [read_u32, write_u32],
|
||||||
u64: [read_u64, write_u64]
|
u64: [read_u64, write_u64],
|
||||||
|
usize: [read_usize, write_usize]
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Serialize for () {
|
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> {
|
impl<T: Serialize> Serialize for Option<T> {
|
||||||
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
|
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -70,52 +70,11 @@ impl Serialize for SocketAddrV6 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for IpAddr {
|
crate::impl_enum_serde!(IpAddr: [
|
||||||
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
|
V4 => 4,
|
||||||
match deserializer.read_enum_variant()? {
|
V6 => 6
|
||||||
4 => Ipv4Addr::deserialize(deserializer).map(Self::V4),
|
]);
|
||||||
6 => Ipv6Addr::deserialize(deserializer).map(Self::V6),
|
crate::impl_enum_serde!(SocketAddr: [
|
||||||
_ => Err(D::Error::INVALID_ENUM_VARIANT),
|
V4 => 4,
|
||||||
}
|
V6 => 6
|
||||||
}
|
]);
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -10,3 +10,86 @@ pub mod wire;
|
|||||||
|
|
||||||
pub use des::Deserialize;
|
pub use des::Deserialize;
|
||||||
pub use ser::Serialize;
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -11,14 +11,10 @@ extern {
|
|||||||
// TODO "tagged union" enums are not yet implemented
|
// TODO "tagged union" enums are not yet implemented
|
||||||
type MappingSource;
|
type MappingSource;
|
||||||
|
|
||||||
type SystemInfo = yggdrasil_abi::system::SystemInfo;
|
|
||||||
|
|
||||||
type SignalEntryData = yggdrasil_abi::process::SignalEntryData;
|
type SignalEntryData = yggdrasil_abi::process::SignalEntryData;
|
||||||
type MutexOperation = yggdrasil_abi::process::MutexOperation;
|
type MutexOperation = yggdrasil_abi::process::MutexOperation;
|
||||||
#[thin]
|
#[thin]
|
||||||
type ExitCode = yggdrasil_abi::process::ExitCode;
|
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 ProcessWait = yggdrasil_abi::process::ProcessWait;
|
||||||
|
|
||||||
type SocketAddr = core::net::SocketAddr;
|
type SocketAddr = core::net::SocketAddr;
|
||||||
@ -72,12 +68,14 @@ bitfield MappingFlags(u32) {
|
|||||||
|
|
||||||
syscall get_random(buffer: &mut [u8]);
|
syscall get_random(buffer: &mut [u8]);
|
||||||
syscall get_clock(clock: ClockType, out: &mut MaybeUninit<SystemTime>) -> Result<()>;
|
syscall get_clock(clock: ClockType, out: &mut MaybeUninit<SystemTime>) -> Result<()>;
|
||||||
syscall get_system_info(info: &mut SystemInfo) -> Result<()>;
|
|
||||||
syscall mount(opts: &MountOptions<'_>) -> Result<()>;
|
syscall mount(opts: &MountOptions<'_>) -> Result<()>;
|
||||||
syscall unmount(opts: &UnmountOptions) -> Result<()>;
|
syscall unmount(opts: &UnmountOptions) -> Result<()>;
|
||||||
syscall load_module(path: &str) -> Result<()>;
|
syscall load_module(path: &str) -> Result<()>;
|
||||||
|
|
||||||
syscall filesystem_control(fd: Option<RawFd>, option: u32, value: &mut [u8], len: usize) -> Result<usize>;
|
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
|
// Memory management
|
||||||
syscall map_memory(
|
syscall map_memory(
|
||||||
hint: Option<NonZeroUsize>,
|
hint: Option<NonZeroUsize>,
|
||||||
@ -101,10 +99,10 @@ syscall get_tid() -> u32;
|
|||||||
syscall spawn_thread(options: &ThreadSpawnOptions) -> Result<u32>;
|
syscall spawn_thread(options: &ThreadSpawnOptions) -> Result<u32>;
|
||||||
syscall exit_thread() -> !;
|
syscall exit_thread() -> !;
|
||||||
syscall wait_thread(tid: u32) -> Result<()>;
|
syscall wait_thread(tid: u32) -> Result<()>;
|
||||||
syscall get_thread_option(option: &mut ThreadOption<'_>) -> Result<()>;
|
syscall get_thread_option(option: u32, value: &mut [u8]) -> Result<usize>;
|
||||||
syscall set_thread_option(option: &mut ThreadOption<'_>) -> Result<()>;
|
syscall set_thread_option(option: u32, value: &[u8]) -> Result<()>;
|
||||||
syscall get_process_option(option: &mut ProcessOption) -> Result<()>;
|
syscall get_process_option(option: u32, value: &mut [u8]) -> Result<usize>;
|
||||||
syscall set_process_option(option: &mut ProcessOption) -> Result<()>;
|
syscall set_process_option(option: u32, value: &[u8]) -> Result<()>;
|
||||||
|
|
||||||
syscall nanosleep(duration: &Duration, remaining: &mut MaybeUninit<Duration>) -> Result<()>;
|
syscall nanosleep(duration: &Duration, remaining: &mut MaybeUninit<Duration>) -> Result<()>;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
//! Device data structures and options
|
//! Device data structures and options
|
||||||
use abi_serde::{des::Deserializer, ser::Serializer, Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::{io::terminal, process::ProcessGroupId};
|
use crate::{io::terminal, process::ProcessGroupId};
|
||||||
|
|
||||||
@ -56,27 +55,6 @@ request_group!(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Framebuffer {
|
abi_serde::impl_struct_serde!(Framebuffer: [
|
||||||
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
|
width, height, stride, size
|
||||||
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use abi_serde::{des::Deserializer, ser::Serializer, Deserialize, Serialize};
|
|
||||||
|
|
||||||
pub use crate::generated::{
|
pub use crate::generated::{
|
||||||
TerminalControlCharacters, TerminalInputOptions, TerminalLineOptions, TerminalOptions,
|
TerminalControlCharacters, TerminalInputOptions, TerminalLineOptions, TerminalOptions,
|
||||||
TerminalOutputOptions, TerminalSize,
|
TerminalOutputOptions, TerminalSize,
|
||||||
@ -65,107 +63,15 @@ impl Default for TerminalOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for TerminalLineOptions {
|
abi_serde::impl_newtype_serde!(TerminalLineOptions);
|
||||||
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
|
abi_serde::impl_newtype_serde!(TerminalInputOptions);
|
||||||
Ok(unsafe { Self::from_raw(deserializer.read_u32()?) })
|
abi_serde::impl_newtype_serde!(TerminalOutputOptions);
|
||||||
}
|
abi_serde::impl_struct_serde!(TerminalControlCharacters: [
|
||||||
}
|
eof, kill, erase, werase, interrupt
|
||||||
|
]);
|
||||||
impl Serialize for TerminalLineOptions {
|
abi_serde::impl_struct_serde!(TerminalOptions: [
|
||||||
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
|
line, input, output, chars
|
||||||
serializer.write_u32(self.bits())
|
]);
|
||||||
}
|
abi_serde::impl_struct_serde!(TerminalSize: [
|
||||||
}
|
rows, columns
|
||||||
|
]);
|
||||||
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
//! Defines data types for network operations
|
//! Defines data types for network operations
|
||||||
|
|
||||||
use abi_serde::{
|
|
||||||
des::{DeserializeError, Deserializer},
|
|
||||||
ser::Serializer,
|
|
||||||
Deserialize, Serialize,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(any(feature = "alloc", feature = "rustc_std_alloc"))]
|
#[cfg(any(feature = "alloc", feature = "rustc_std_alloc"))]
|
||||||
pub mod dns;
|
pub mod dns;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
@ -46,30 +40,10 @@ impl From<u32> for SocketInterfaceQuery<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for SocketInterfaceQuery<'de> {
|
abi_serde::impl_enum_serde!(SocketInterfaceQuery<'de>: [
|
||||||
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
|
ById => 1,
|
||||||
match deserializer.read_enum_variant()? {
|
ByName => 2
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -2,12 +2,6 @@
|
|||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use abi_serde::{
|
|
||||||
des::{DeserializeError, Deserializer},
|
|
||||||
ser::Serializer,
|
|
||||||
Deserialize, Serialize,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub mod ip_addr;
|
pub mod ip_addr;
|
||||||
pub mod net_value;
|
pub mod net_value;
|
||||||
pub mod socket_addr;
|
pub mod socket_addr;
|
||||||
@ -54,18 +48,4 @@ impl fmt::Display for MacAddress {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for MacAddress {
|
abi_serde::impl_newtype_serde!(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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
use core::{ffi::CStr, fmt, marker::PhantomData, time::Duration};
|
use core::{ffi::CStr, fmt, marker::PhantomData, time::Duration};
|
||||||
|
|
||||||
use crate::{
|
use crate::io::{FileMode, RawFd};
|
||||||
io::{FileMode, RawFd},
|
|
||||||
util::FixedString,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod exit;
|
mod exit;
|
||||||
|
pub mod options;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
|
|
||||||
pub use crate::generated::{
|
pub use crate::generated::{
|
||||||
ExecveOptions, ProcessGroupId, ProcessId, Signal, SignalEntryData, SpawnFlags, SpawnOptions,
|
ExecveOptions, ProcessGroupId, ProcessId, Signal, SignalEntryData, SpawnFlags, SpawnOptions,
|
||||||
ThreadId, ThreadSpawnOptions, WaitFlags,
|
ThreadId, ThreadSpawnOptions, WaitFlags,
|
||||||
};
|
};
|
||||||
use abi_serde::{des::Deserializer, ser::Serializer, Deserialize, Serialize};
|
|
||||||
pub use exit::ExitCode;
|
pub use exit::ExitCode;
|
||||||
pub use thread::ThreadOption;
|
|
||||||
|
|
||||||
// TODO this is ugly
|
// TODO this is ugly
|
||||||
pub mod auxv {
|
pub mod auxv {
|
||||||
@ -47,16 +43,6 @@ pub enum ProcessWait {
|
|||||||
AnyChild,
|
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
|
/// Defines an optional argument for controlling process creation
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SpawnOption {
|
pub enum SpawnOption {
|
||||||
@ -229,14 +215,5 @@ impl Signal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for ProcessGroupId {
|
abi_serde::impl_newtype_serde!(ProcessGroupId);
|
||||||
fn deserialize<D: Deserializer<'de>>(deserializer: &mut D) -> Result<Self, D::Error> {
|
abi_serde::impl_newtype_serde!(ProcessId);
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
13
lib/abi/src/process/options.rs
Normal file
13
lib/abi/src/process/options.rs
Normal 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)
|
||||||
|
}
|
||||||
|
);
|
@ -1,12 +1,24 @@
|
|||||||
//! Thread data structures
|
//! Thread option definitions
|
||||||
|
|
||||||
/// Represents a thread option being set/retrieved
|
/// Thread signal stack
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub enum ThreadOption<'a> {
|
pub struct ThreadSignalStack {
|
||||||
/// Thread-local storage base pointer
|
/// Base address
|
||||||
ThreadPointer(usize),
|
pub base: usize,
|
||||||
/// Thread signal entry stack base and size
|
/// Size
|
||||||
SignalStack(usize, usize),
|
pub size: usize,
|
||||||
/// Thread display name
|
|
||||||
Name(&'a str),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
@ -13,9 +13,14 @@ pub struct SystemMemoryStats {
|
|||||||
pub page_size: usize,
|
pub page_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes a piece of system information
|
option_group!(
|
||||||
#[derive(Clone, Debug)]
|
#[doc = "System information requests"]
|
||||||
pub enum SystemInfo {
|
pub enum SystemInfoVariant<'de> {
|
||||||
/// Memory usage stats
|
#[doc = "Memory usage information"]
|
||||||
MemoryStats(SystemMemoryStats),
|
0x1000: MemoryUsage # 64 (SystemMemoryStats),
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
abi_serde::impl_struct_serde!(
|
||||||
|
SystemMemoryStats: [total_usable_pages, allocated_pages, free_pages, page_size]
|
||||||
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use core::str::FromStr;
|
use abi::error::Error;
|
||||||
|
|
||||||
use abi::{error::Error, process::ProcessOption, util::FixedString};
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
|
|
||||||
|
use crate::process;
|
||||||
|
|
||||||
pub fn current_exe<T, F: FnOnce(&str) -> T>(_mapper: F) -> Result<T, Error> {
|
pub fn current_exe<T, F: FnOnce(&str) -> T>(_mapper: F) -> Result<T, Error> {
|
||||||
todo!()
|
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> {
|
pub fn current_directory<T, F: FnOnce(&str) -> T>(mapper: F) -> Result<T, Error> {
|
||||||
let mut option = ProcessOption::Directory(FixedString::empty());
|
let mut buffer = [0; 512];
|
||||||
unsafe { crate::sys::get_process_option(&mut option) }?;
|
let path = process::get_process_option::<process::options::Directory>(&mut buffer)?;
|
||||||
let ProcessOption::Directory(path) = &option else {
|
Ok(mapper(path))
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(mapper(path.as_ref()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_directory_string() -> Result<String, Error> {
|
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> {
|
pub fn set_current_directory(path: &str) -> Result<(), Error> {
|
||||||
let mut option = ProcessOption::Directory(FixedString::from_str(path)?);
|
let mut buffer = [0; 512];
|
||||||
unsafe { crate::sys::set_process_option(&mut option) }?;
|
process::set_process_option_with::<process::options::Directory>(&mut buffer, &path)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_temp_directory(_template: &mut [u8]) -> Result<(), Error> {
|
pub fn make_temp_directory(_template: &mut [u8]) -> Result<(), Error> {
|
||||||
|
@ -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> {
|
pub fn set_terminal_size(fd: RawFd, size: &TerminalSize) -> Result<(), Error> {
|
||||||
let mut buffer = [0; 32];
|
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 {
|
pub fn is_terminal(fd: RawFd) -> bool {
|
||||||
|
@ -32,10 +32,5 @@ pub mod net;
|
|||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
|
pub mod system;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
|
|
||||||
pub mod system {
|
|
||||||
//! System-related data structures
|
|
||||||
|
|
||||||
pub use abi::system::*;
|
|
||||||
}
|
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
use core::{mem::MaybeUninit, time::Duration};
|
use core::{mem::MaybeUninit, time::Duration};
|
||||||
|
|
||||||
use abi::error::Error;
|
|
||||||
pub use abi::process::{
|
pub use abi::process::{
|
||||||
auxv, AuxValue, AuxValueIter, ExecveOptions, ExitCode, MutexOperation, ProcessGroupId,
|
auxv, AuxValue, AuxValueIter, ExecveOptions, ExitCode, MutexOperation, ProcessGroupId,
|
||||||
ProcessId, ProcessInfoElement, ProcessWait, ProgramArgumentInner, Signal, SignalEntryData,
|
ProcessId, ProcessInfoElement, ProcessWait, ProgramArgumentInner, Signal, SignalEntryData,
|
||||||
SpawnFlags, SpawnOption, SpawnOptions, StringArgIter, ThreadId, ThreadSpawnOptions, WaitFlags,
|
SpawnFlags, SpawnOption, SpawnOptions, StringArgIter, ThreadId, ThreadSpawnOptions, WaitFlags,
|
||||||
};
|
};
|
||||||
|
use abi::{
|
||||||
|
error::Error,
|
||||||
|
option::{OptionSizeHint, OptionValue},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::sys;
|
use crate::sys;
|
||||||
|
|
||||||
@ -15,6 +18,8 @@ pub mod signal;
|
|||||||
pub mod thread;
|
pub mod thread;
|
||||||
pub mod thread_local;
|
pub mod thread_local;
|
||||||
|
|
||||||
|
pub use abi::process::options;
|
||||||
|
|
||||||
/// Makes the current thread wait until *at least* the amount of time specified in `duration`
|
/// Makes the current thread wait until *at least* the amount of time specified in `duration`
|
||||||
/// passes.
|
/// 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]) }
|
||||||
|
}
|
||||||
|
0
lib/runtime/src/process/options.rs
Normal file
0
lib/runtime/src/process/options.rs
Normal file
@ -4,10 +4,13 @@ use core::ffi::c_int;
|
|||||||
use abi::{
|
use abi::{
|
||||||
error::Error,
|
error::Error,
|
||||||
mem::{MappingFlags, MappingSource},
|
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
|
/// Describes how a signal should be handled
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[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.
|
/// 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].
|
/// TLDR: just use [setup_signal_stack].
|
||||||
pub unsafe fn set_signal_stack(base: usize, size: usize) -> (usize, usize) {
|
pub unsafe fn set_signal_stack(base: usize, size: usize) {
|
||||||
let mut option = ThreadOption::SignalStack(base, size);
|
process::set_thread_option::<thread::options::SignalStack>(
|
||||||
crate::sys::set_thread_option(&mut option).expect("set_signal_stack() failed");
|
&thread::options::ThreadSignalStack { base, size },
|
||||||
let ThreadOption::SignalStack(base, size) = option else {
|
)
|
||||||
unreachable!()
|
.expect("set_signal_stack() failed")
|
||||||
};
|
|
||||||
(base, size)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the currently set signal stack base:size.
|
/// Returns the currently set signal stack base:size.
|
||||||
pub fn get_signal_stack() -> (usize, usize) {
|
pub fn get_signal_stack() -> (usize, usize) {
|
||||||
let mut option = ThreadOption::SignalStack(0, 0);
|
let stack = process::get_thread_option!(thread::options::SignalStack)
|
||||||
unsafe { crate::sys::get_thread_option(&mut option) }.expect("get_signal_stack() failed");
|
.expect("get_signal_stack() failed");
|
||||||
let ThreadOption::SignalStack(base, size) = option else {
|
(stack.base, stack.size)
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
(base, size)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the program's signal entry function.
|
/// 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.
|
/// 1. It must not return, it must call `exit_thread` instead.
|
||||||
/// 2. It must conform to the kernel's signal entry ABI.
|
/// 2. It must conform to the kernel's signal entry ABI.
|
||||||
pub unsafe fn set_signal_entry(entry: usize) -> usize {
|
pub unsafe fn set_signal_entry(entry: usize) {
|
||||||
let mut option = ProcessOption::SignalEntry(entry);
|
process::set_process_option::<process::options::SignalEntry>(&entry)
|
||||||
crate::sys::set_process_option(&mut option).expect("set_signal_entry() failed");
|
.expect("set_signal_entry() failed");
|
||||||
#[allow(irrefutable_let_patterns)]
|
|
||||||
let ProcessOption::SignalEntry(entry) = option
|
|
||||||
else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
entry
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate_signal_stack(mut size: usize) -> Result<(usize, usize), Error> {
|
fn allocate_signal_stack(mut size: usize) -> Result<(usize, usize), Error> {
|
||||||
|
@ -8,7 +8,7 @@ use core::{
|
|||||||
use abi::{
|
use abi::{
|
||||||
error::Error,
|
error::Error,
|
||||||
mem::{MappingFlags, MappingSource},
|
mem::{MappingFlags, MappingSource},
|
||||||
process::{ThreadOption, ThreadSpawnOptions},
|
process::ThreadSpawnOptions,
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, sync::Arc};
|
use alloc::{boxed::Box, sync::Arc};
|
||||||
|
|
||||||
@ -16,6 +16,11 @@ use crate::{process::thread_local, sync::rwlock::RwLock};
|
|||||||
|
|
||||||
use super::{signal, thread_local::TlsImage};
|
use super::{signal, thread_local::TlsImage};
|
||||||
|
|
||||||
|
pub mod options {
|
||||||
|
//! Thread option definitions
|
||||||
|
pub use abi::process::thread::*;
|
||||||
|
}
|
||||||
|
|
||||||
/// Describes a runtime thread.
|
/// Describes a runtime thread.
|
||||||
///
|
///
|
||||||
/// `R` generic parameter denotes the thread's return type.
|
/// `R` generic parameter denotes the thread's return type.
|
||||||
@ -135,7 +140,8 @@ impl<R> Thread<R> {
|
|||||||
|
|
||||||
/// Sets the current thread name.
|
/// Sets the current thread name.
|
||||||
pub fn set_name(name: &str) {
|
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
|
/// # Safety
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use abi::{error::Error, process::ThreadOption};
|
use abi::error::Error;
|
||||||
|
|
||||||
|
use crate::process::{self, thread};
|
||||||
|
|
||||||
pub fn get_thread_pointer() -> usize {
|
pub fn get_thread_pointer() -> usize {
|
||||||
let tp: 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.
|
/// `value` must hold an address to a structure, first element of which is a pointer to itself.
|
||||||
/// Usual pointer safety requirements apply.
|
/// Usual pointer safety requirements apply.
|
||||||
pub unsafe fn set_thread_pointer(value: usize) -> Result<(), Error> {
|
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
|
// ___tls_get_addr, TLS_index structure address gets passed in the %eax register
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use abi::{error::Error, process::ThreadOption};
|
use abi::{error::Error, process::thread};
|
||||||
|
|
||||||
pub fn get_thread_pointer() -> usize {
|
pub fn get_thread_pointer() -> usize {
|
||||||
let tp: 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.
|
/// `value` must hold an address to a structure, first element of which is a pointer to itself.
|
||||||
/// Usual pointer safety requirements apply.
|
/// Usual pointer safety requirements apply.
|
||||||
pub unsafe fn set_thread_pointer(value: usize) -> Result<(), Error> {
|
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
16
lib/runtime/src/system.rs
Normal 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])
|
||||||
|
}
|
@ -2,18 +2,15 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
fmt::Write,
|
fmt::Write
|
||||||
os::yggdrasil::{get_system_info, SystemInfo, SystemMemoryStats},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use humansize::FormatSize;
|
use humansize::FormatSize;
|
||||||
use libterm::{Clear, Term};
|
use libterm::{Clear, Term};
|
||||||
|
use yggdrasil_rt::system;
|
||||||
|
|
||||||
fn get_memory_stats() -> SystemMemoryStats {
|
fn get_memory_stats() -> system::SystemMemoryStats {
|
||||||
let mut info = SystemInfo::MemoryStats(SystemMemoryStats::default());
|
system::get_system_info!(system::MemoryUsage).unwrap()
|
||||||
get_system_info(&mut info).unwrap();
|
|
||||||
let SystemInfo::MemoryStats(stats) = info;
|
|
||||||
stats
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user