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::{
|
||||
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()
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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},
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
]);
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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<()>;
|
||||
|
||||
|
@ -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
|
||||
]);
|
||||
|
@ -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
|
||||
]);
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
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
|
||||
#[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]);
|
||||
|
@ -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]
|
||||
);
|
||||
|
@ -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> {
|
||||
|
@ -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 {
|
||||
|
@ -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::*;
|
||||
}
|
||||
|
@ -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]) }
|
||||
}
|
||||
|
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::{
|
||||
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> {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
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::{
|
||||
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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user