refactor: fix kernel warnings

This commit is contained in:
Mark Poliakov 2024-11-19 17:28:41 +02:00
parent 74be46b29b
commit 49942563ef
17 changed files with 143 additions and 129 deletions

View File

@ -11,7 +11,7 @@ use async_trait::async_trait;
use libk::{ use libk::{
block, block,
error::Error, error::Error,
task::runtime::{run_with_timeout, FutureTimeout}, task::runtime::with_timeout,
vfs::{ConnectionSocket, FileReadiness, ListenerSocket, Socket}, vfs::{ConnectionSocket, FileReadiness, ListenerSocket, Socket},
}; };
use libk_device::monotonic_timestamp; use libk_device::monotonic_timestamp;
@ -64,7 +64,7 @@ impl TcpSocket {
) -> Result<(SocketAddr, Arc<TcpSocket>), Error> { ) -> Result<(SocketAddr, Arc<TcpSocket>), Error> {
let future = Self::connect_async(remote); let future = Self::connect_async(remote);
match timeout { match timeout {
Some(timeout) => run_with_timeout(timeout, future).await.into(), Some(timeout) => with_timeout(future, timeout).await?.into(),
None => future.await, None => future.await,
} }
} }
@ -290,10 +290,7 @@ impl TcpSocket {
connection.poll_established(cx) connection.poll_established(cx)
}); });
match run_with_timeout(timeout, fut).await { with_timeout(fut, timeout).await?
FutureTimeout::Ok(value) => value,
FutureTimeout::Timeout => Err(Error::TimedOut),
}
} }
} }

View File

@ -4,7 +4,7 @@ use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, vec, vec::Vec};
use atomic_enum::atomic_enum; use atomic_enum::atomic_enum;
use device_api::{interrupt::InterruptHandler, Device}; use device_api::{interrupt::InterruptHandler, Device};
use futures_util::task::AtomicWaker; use futures_util::task::AtomicWaker;
use libk::task::runtime::{self, FutureTimeout}; use libk::task::runtime;
use libk_mm::{ use libk_mm::{
address::{AsPhysicalAddress, PhysicalAddress}, address::{AsPhysicalAddress, PhysicalAddress},
PageBox, PageBox,
@ -278,8 +278,7 @@ impl Xhci {
// Wait for port reset // Wait for port reset
// TODO handle disconnect during reset? // TODO handle disconnect during reset?
let result = runtime::run_with_timeout( let result = runtime::with_timeout(
Duration::from_secs(1),
poll_fn(|cx| { poll_fn(|cx| {
let state = &self.port_states[port]; let state = &self.port_states[port];
@ -290,12 +289,13 @@ impl Xhci {
Poll::Pending Poll::Pending
} }
}), }),
Duration::from_secs(1),
) )
.await; .await;
match result { match result {
FutureTimeout::Ok(()) => Ok(()), Ok(()) => Ok(()),
FutureTimeout::Timeout => Err(UsbError::PortResetFailed), Err(_) => Err(UsbError::PortResetFailed),
} }
} }

View File

@ -9,8 +9,6 @@ use core::{
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use kernel_arch_interface::mem::KernelTableManager; use kernel_arch_interface::mem::KernelTableManager;
use crate::table::EntryLevel;
/// Wrapper type to represent a physical memory address /// Wrapper type to represent a physical memory address
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Pod, Zeroable)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Pod, Zeroable)]
#[repr(transparent)] #[repr(transparent)]

View File

@ -1,4 +1,4 @@
use core::ops::Range; use core::ops::{Deref, Range};
use alloc::sync::Arc; use alloc::sync::Arc;
use kernel_arch::ProcessAddressSpaceImpl; use kernel_arch::ProcessAddressSpaceImpl;
@ -7,7 +7,7 @@ use libk_mm_interface::{
process::ProcessAddressSpaceManager, process::ProcessAddressSpaceManager,
table::{MapAttributes, TableAllocator}, table::{MapAttributes, TableAllocator},
}; };
use libk_util::sync::IrqSafeSpinlock; use libk_util::sync::{IrqSafeSpinlock, IrqSafeSpinlockGuard};
use vmalloc::{RangeData, VirtualMemoryAllocator}; use vmalloc::{RangeData, VirtualMemoryAllocator};
use yggdrasil_abi::error::Error; use yggdrasil_abi::error::Error;
@ -26,6 +26,13 @@ pub enum VirtualRangeBacking {
File(FileBacking), File(FileBacking),
} }
/// Wrapper type for ensuring the translation table cannot be modified while performing accesses
/// to the inner [PhysicalAddress].
pub struct TranslateGuard<'a, TA: TableAllocator> {
address: PhysicalAddress,
_guard: IrqSafeSpinlockGuard<'a, Inner<TA>>,
}
/// Describes a file-backed memory range provider /// Describes a file-backed memory range provider
#[derive(Clone)] #[derive(Clone)]
pub struct FileBacking { pub struct FileBacking {
@ -415,6 +422,17 @@ impl<TA: TableAllocator> ProcessAddressSpace<TA> {
self.inner.lock().table.translate(address).map(|e| e.0) self.inner.lock().table.translate(address).map(|e| e.0)
} }
/// Same as [ProcessAddressSpace::translate], except the lock on the address space is held
/// until the resulting [TranslateGuard] is dropped.
pub fn translate_lock(&self, address: usize) -> Result<TranslateGuard<TA>, Error> {
let guard = self.inner.lock();
let address = guard.table.translate(address).map(|e| e.0)?;
Ok(TranslateGuard {
address,
_guard: guard,
})
}
/// Removes a single PAGE_SIZE mapping from the address space. /// Removes a single PAGE_SIZE mapping from the address space.
/// ///
/// See [ProcessAddressSpaceManager::unmap]. /// See [ProcessAddressSpaceManager::unmap].
@ -449,3 +467,11 @@ impl<TA: TableAllocator> Drop for ProcessAddressSpace<TA> {
self.clear().ok(); self.clear().ok();
} }
} }
impl<TA: TableAllocator> Deref for TranslateGuard<'_, TA> {
type Target = PhysicalAddress;
fn deref(&self) -> &Self::Target {
&self.address
}
}

View File

@ -20,7 +20,8 @@
trait_upcasting, trait_upcasting,
arbitrary_self_types, arbitrary_self_types,
slice_split_once, slice_split_once,
arbitrary_self_types_pointers arbitrary_self_types_pointers,
result_flattening
)] )]
extern crate alloc; extern crate alloc;

View File

@ -5,7 +5,6 @@ use alloc::sync::Arc;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use elf::{ use elf::{
endian::AnyEndian, endian::AnyEndian,
io_traits::InputStream,
relocation::{Rel, Rela}, relocation::{Rel, Rela},
segment::ProgramHeader, segment::ProgramHeader,
ElfStream, ParseError, ElfStream, ParseError,
@ -14,14 +13,14 @@ use libk_mm::{
pointer::PhysicalRefMut, pointer::PhysicalRefMut,
process::{ProcessAddressSpace, VirtualRangeBacking}, process::{ProcessAddressSpace, VirtualRangeBacking},
table::MapAttributes, table::MapAttributes,
PageBox, L3_PAGE_SIZE, L3_PAGE_SIZE,
}; };
use libk_util::io::{Read, Seek}; use libk_util::io::{Read, Seek};
use yggdrasil_abi::{error::Error, io::SeekFrom, path::PathBuf}; use yggdrasil_abi::{error::Error, io::SeekFrom, path::PathBuf};
use crate::{ use crate::{
random, random,
task::{mem::ForeignPointer, process::ProcessImage, types::TlsImage}, task::{process::ProcessImage, types::TlsImage},
}; };
cfg_if! { cfg_if! {

View File

@ -1,5 +1,3 @@
use core::{alloc::Layout, ptr::NonNull};
use alloc::{ use alloc::{
borrow::ToOwned, borrow::ToOwned,
string::String, string::String,
@ -18,7 +16,6 @@ use libk_util::io::{Read, Seek};
use yggdrasil_abi::{ use yggdrasil_abi::{
error::Error, error::Error,
io::SeekFrom, io::SeekFrom,
pass::{Place, Placer},
path::Path, path::Path,
process::{auxv, AuxValue, ProcessGroupId}, process::{auxv, AuxValue, ProcessGroupId},
}; };

View File

@ -1,27 +1,22 @@
use core::{ use core::{
future::poll_fn, future::poll_fn,
pin::Pin, ptr,
sync::atomic::{AtomicU32, Ordering}, sync::atomic::{AtomicU32, Ordering},
task::{Context, Poll}, task::Poll,
}; };
use alloc::sync::Arc; use alloc::sync::Arc;
use futures_util::Future; use libk_mm::process::ProcessAddressSpace;
use libk_mm::{
address::{AsPhysicalAddress, PhysicalAddress},
pointer::PhysicalRef,
process::ProcessAddressSpace,
};
use libk_util::waker::QueueWaker; use libk_util::waker::QueueWaker;
use yggdrasil_abi::error::Error; use yggdrasil_abi::error::Error;
use crate::task::thread::Thread; use crate::task::mem::ForeignAtomic;
/// User-space mutex (like BSD/Linux's futex) data structure /// User-space mutex (like BSD/Linux's futex) data structure
pub struct UserspaceMutex { pub struct UserspaceMutex {
queue: QueueWaker, queue: QueueWaker,
space: Arc<ProcessAddressSpace>, space: Arc<ProcessAddressSpace>,
address: usize, atomic: *const AtomicU32,
} }
impl UserspaceMutex { impl UserspaceMutex {
@ -30,35 +25,42 @@ impl UserspaceMutex {
Ok(Self { Ok(Self {
queue: QueueWaker::new(), queue: QueueWaker::new(),
space: space.clone(), space: space.clone(),
address, atomic: ptr::with_exposed_provenance(address),
}) })
} }
fn load(&self) -> u32 { fn load(&self) -> Result<u32, Error> {
// TODO: this is slow, but this prevents the kernel from reading from unmapped memory self.atomic
let phys = self.space.translate(self.address).unwrap(); .atomic_load_foreign(&self.space, Ordering::Acquire)
unsafe { PhysicalRef::<AtomicU32>::map(phys).load(Ordering::Acquire) }
} }
async fn wait_predicate<P: Fn(u32) -> bool>(&self, predicate: P) { async fn wait_predicate<P: Fn(u32) -> bool>(&self, predicate: P) -> Result<(), Error> {
poll_fn(|cx| { poll_fn(|cx| {
if predicate(self.load()) { let result = self.load();
self.queue.remove(cx.waker()); match result {
Poll::Ready(()) Err(err) => {
} else { self.queue.remove(cx.waker());
self.queue.register(cx.waker()); Poll::Ready(Err(err))
Poll::Pending }
Ok(val) if predicate(val) => {
self.queue.remove(cx.waker());
Poll::Ready(Ok(()))
}
Ok(_) => {
self.queue.register(cx.waker());
Poll::Pending
}
} }
}) })
.await .await
} }
pub async fn wait_until(self: Arc<Self>, compare_value: u32) { pub async fn wait_until(self: Arc<Self>, compare_value: u32) -> Result<(), Error> {
self.wait_predicate(|value| value == compare_value).await self.wait_predicate(|value| value == compare_value).await
} }
/// Blocks until the value at the mutex's address becomes different from `compare_value` /// Blocks until the value at the mutex's address becomes different from `compare_value`
pub async fn wait(self: Arc<Self>, compare_value: u32) { pub async fn wait(self: Arc<Self>, compare_value: u32) -> Result<(), Error> {
self.wait_predicate(|value| value != compare_value).await self.wait_predicate(|value| value != compare_value).await
} }

View File

@ -1,4 +1,9 @@
use core::{alloc::Layout, mem::size_of}; use core::{
alloc::Layout,
mem::size_of,
ptr,
sync::atomic::{AtomicU32, Ordering},
};
use libk_mm::{address::Virtualize, process::ProcessAddressSpace}; use libk_mm::{address::Virtualize, process::ProcessAddressSpace};
use yggdrasil_abi::error::Error; use yggdrasil_abi::error::Error;
@ -96,6 +101,14 @@ pub trait ForeignPointer: Sized {
) -> Result<&'a mut [Self], Error>; ) -> Result<&'a mut [Self], Error>;
} }
pub trait ForeignAtomic<T> {
fn atomic_load_foreign(
self: *const Self,
space: &ProcessAddressSpace,
ordering: Ordering,
) -> Result<T, Error>;
}
impl<T> ForeignPointer for T { impl<T> ForeignPointer for T {
unsafe fn write_foreign_volatile(self: *mut Self, space: &ProcessAddressSpace, value: T) { unsafe fn write_foreign_volatile(self: *mut Self, space: &ProcessAddressSpace, value: T) {
self.try_write_foreign_volatile(space, value) self.try_write_foreign_volatile(space, value)
@ -203,6 +216,23 @@ impl<T> ForeignPointer for T {
} }
} }
impl ForeignAtomic<u32> for AtomicU32 {
fn atomic_load_foreign(
self: *const Self,
space: &ProcessAddressSpace,
ordering: Ordering,
) -> Result<u32, Error> {
let virt = self.addr();
if virt % size_of::<u32>() != 0 {
// Misaligned atomic
return Err(Error::InvalidMemoryOperation);
}
let phys = space.translate_lock(virt)?;
let phys_virt: *const Self = ptr::with_exposed_provenance(phys.virtualize());
Ok(unsafe { &*phys_virt }.load(ordering))
}
}
fn validate_user_align_size(addr: usize, layout: &Layout) -> Result<(), Error> { fn validate_user_align_size(addr: usize, layout: &Layout) -> Result<(), Error> {
// Explicitly disallow NULL // Explicitly disallow NULL
if addr == 0 { if addr == 0 {

View File

@ -29,8 +29,7 @@ use yggdrasil_abi::{
use crate::{ use crate::{
task::{ task::{
binary, futex::UserspaceMutex, thread::Thread, types::AllocateProcessId, TaskContextImpl, futex::UserspaceMutex, thread::Thread, types::AllocateProcessId, TaskContextImpl, ThreadId,
ThreadId,
}, },
vfs::{FileReadiness, FileSet, IoContext, NodeRef}, vfs::{FileReadiness, FileSet, IoContext, NodeRef},
}; };

View File

@ -8,4 +8,4 @@ mod timer;
pub use executor::{run_to_completion, spawn, spawn_async_worker}; pub use executor::{run_to_completion, spawn, spawn_async_worker};
pub use task_queue::init_task_queue; pub use task_queue::init_task_queue;
pub use timer::{run_with_timeout, sleep, tick, FutureTimeout, SleepFuture}; pub use timer::{maybe_timeout, sleep, tick, with_timeout, SleepFuture};

View File

@ -1,11 +1,12 @@
use core::{ use core::{
future::poll_fn,
pin::Pin, pin::Pin,
task::{Context, Poll, Waker}, task::{Context, Poll, Waker},
time::Duration, time::Duration,
}; };
use alloc::vec::Vec; use alloc::vec::Vec;
use futures_util::{future::BoxFuture, Future, FutureExt}; use futures_util::{Future, FutureExt};
use libk_util::sync::IrqSafeSpinlock; use libk_util::sync::IrqSafeSpinlock;
use yggdrasil_abi::error::Error; use yggdrasil_abi::error::Error;
@ -70,11 +71,6 @@ fn register_timeout(duration: Duration, waker: &Waker) {
} }
} }
pub enum FutureTimeout<T> {
Ok(T),
Timeout,
}
pub struct SleepFuture { pub struct SleepFuture {
deadline: Duration, deadline: Duration,
} }
@ -113,42 +109,33 @@ pub fn sleep(duration: Duration) -> SleepFuture {
SleepFuture { deadline } SleepFuture { deadline }
} }
pub fn run_with_timeout<'a, T: 'a, F: Future<Output = T> + Send + 'a>( pub fn with_timeout<'a, T: 'a, F: Future<Output = T> + Send + 'a>(
duration: Duration,
fut: F, fut: F,
) -> impl Future<Output = FutureTimeout<T>> + 'a { timeout: Duration,
struct TimeoutFuture<'f, T> { ) -> impl Future<Output = Result<T, Error>> + Send + 'a {
fut: BoxFuture<'f, T>, let mut fut = fut.boxed();
sleep_fut: BoxFuture<'f, ()>, let mut sleep_fut = sleep(timeout).boxed();
}
impl<'f, T> Future for TimeoutFuture<'f, T> { poll_fn(move |cx| {
type Output = FutureTimeout<T>; let (timeout, output) = (sleep_fut.poll_unpin(cx), fut.poll_unpin(cx));
if let Poll::Ready(output) = output {
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { Poll::Ready(Ok(output))
let (timeout, result) = (self.sleep_fut.as_mut().poll(cx), self.fut.as_mut().poll(cx)); } else if timeout.is_ready() {
Poll::Ready(Err(Error::TimedOut))
if let Poll::Ready(result) = result { } else {
Poll::Ready(FutureTimeout::Ok(result)) Poll::Pending
} else if timeout.is_ready() {
Poll::Ready(FutureTimeout::Timeout)
} else {
Poll::Pending
}
} }
} })
TimeoutFuture {
fut: fut.boxed(),
sleep_fut: sleep(duration).boxed(),
}
} }
impl<T> From<FutureTimeout<Result<T, Error>>> for Result<T, Error> { pub fn maybe_timeout<'a, T: 'a, F: Future<Output = T> + Send + 'a>(
fn from(value: FutureTimeout<Result<T, Error>>) -> Self { fut: F,
match value { timeout: Option<Duration>,
FutureTimeout::Ok(res) => res, ) -> impl Future<Output = Result<T, Error>> + Send + 'a {
FutureTimeout::Timeout => Err(Error::TimedOut), async move {
match timeout {
Some(timeout) => with_timeout(fut, timeout).await,
None => Ok(fut.await),
} }
} }
} }

View File

@ -59,11 +59,6 @@ pub struct ThreadDebuggingInfo {
pub breakpoints: BTreeMap<usize, BreakpointType>, pub breakpoints: BTreeMap<usize, BreakpointType>,
} }
struct SignalEntry {
entry: usize,
stack: usize,
}
/// Describes a single thread within the system /// Describes a single thread within the system
pub struct Thread { pub struct Thread {
/// Unique thread ID /// Unique thread ID

View File

@ -1,11 +1,9 @@
use alloc::sync::Arc;
use core::{ use core::{
fmt, fmt,
sync::atomic::{AtomicU32, AtomicU64, Ordering}, sync::atomic::{AtomicU32, AtomicU64, Ordering},
}; };
use atomic_enum::atomic_enum; use atomic_enum::atomic_enum;
use libk_mm::PageBox;
use yggdrasil_abi::process::ProcessId; use yggdrasil_abi::process::ProcessId;
pub trait AllocateProcessId { pub trait AllocateProcessId {

View File

@ -1,6 +1,5 @@
use core::{ use core::{
fmt, fmt,
future::Future,
task::{Context, Poll}, task::{Context, Poll},
time::Duration, time::Duration,
}; };
@ -13,10 +12,7 @@ use yggdrasil_abi::{
net::{SocketAddr, SocketOption}, net::{SocketAddr, SocketOption},
}; };
use crate::{ use crate::{task::runtime::maybe_timeout, vfs::FileReadiness};
task::runtime::{run_with_timeout, FutureTimeout},
vfs::FileReadiness,
};
enum SocketInner { enum SocketInner {
Connection(Arc<dyn ConnectionSocket + Send + 'static>), Connection(Arc<dyn ConnectionSocket + Send + 'static>),
@ -130,7 +126,7 @@ impl SocketWrapper {
let (remote, remote_socket) = match (options.non_blocking, options.recv_timeout) { let (remote, remote_socket) = match (options.non_blocking, options.recv_timeout) {
(false, timeout) => { (false, timeout) => {
let fut = socket.accept(); let fut = socket.accept();
block!(maybe_timeout(timeout, fut).await)?? block!(maybe_timeout(fut, timeout).await)???
} }
(true, _) => socket.accept_nonblocking()?, (true, _) => socket.accept_nonblocking()?,
}; };
@ -157,11 +153,11 @@ impl SocketWrapper {
) -> Result<(usize, SocketAddr), Error> { ) -> Result<(usize, SocketAddr), Error> {
match &self.inner { match &self.inner {
SocketInner::Packet(socket) => { SocketInner::Packet(socket) => {
maybe_timeout(timeout, socket.receive_from(buffer)).await maybe_timeout(socket.receive_from(buffer), timeout).await?
} }
SocketInner::Connection(socket) => { SocketInner::Connection(socket) => {
let remote = socket.remote_address().ok_or(Error::NotConnected)?; let remote = socket.remote_address().ok_or(Error::NotConnected)?;
let len = maybe_timeout(timeout, socket.receive(buffer)).await?; let len = maybe_timeout(socket.receive(buffer), timeout).await??;
Ok((len, remote)) Ok((len, remote))
} }
SocketInner::Listener(_) => Err(Error::InvalidOperation), SocketInner::Listener(_) => Err(Error::InvalidOperation),
@ -184,9 +180,9 @@ impl SocketWrapper {
) -> Result<usize, Error> { ) -> Result<usize, Error> {
match &self.inner { match &self.inner {
SocketInner::Packet(socket) => { SocketInner::Packet(socket) => {
maybe_timeout(timeout, socket.send_to(remote, buffer)).await maybe_timeout(socket.send_to(remote, buffer), timeout).await?
} }
SocketInner::Connection(socket) => maybe_timeout(timeout, socket.send(buffer)).await, SocketInner::Connection(socket) => maybe_timeout(socket.send(buffer), timeout).await?,
SocketInner::Listener(_) => Err(Error::InvalidOperation), SocketInner::Listener(_) => Err(Error::InvalidOperation),
} }
} }
@ -325,20 +321,6 @@ impl Default for InnerOptions {
} }
} }
async fn maybe_timeout<R, F: Future<Output = Result<R, Error>> + Send>(
timeout: Option<Duration>,
fut: F,
) -> Result<R, Error> {
if let Some(timeout) = timeout {
match run_with_timeout(timeout, fut).await {
FutureTimeout::Ok(value) => value,
FutureTimeout::Timeout => Err(Error::TimedOut),
}
} else {
fut.await
}
}
// impl From<Arc<dyn ConnectionSocket + 'static>> for SocketWrapper { // impl From<Arc<dyn ConnectionSocket + 'static>> for SocketWrapper {
// fn from(value: Arc<dyn ConnectionSocket + 'static>) -> Self { // fn from(value: Arc<dyn ConnectionSocket + 'static>) -> Self {
// Self::Connection(value) // Self::Connection(value)

View File

@ -6,7 +6,7 @@ pub(crate) use abi::{
}, },
mem::{MappingFlags, MappingSource}, mem::{MappingFlags, MappingSource},
net::SocketType, net::SocketType,
process::{Signal, SignalEntryData, SpawnOptions, ThreadOption}, process::{Signal, SignalEntryData, SpawnOptions},
system::SystemInfo, system::SystemInfo,
}; };
use abi::{ use abi::{

View File

@ -48,14 +48,12 @@ pub(crate) fn map_memory(
} }
}; };
let result = space.allocate( let mut attrs = MapAttributes::NON_GLOBAL | MapAttributes::USER_READ;
None, if flags.contains(MappingFlags::WRITE) {
len, attrs |= MapAttributes::USER_WRITE;
backing, }
MapAttributes::USER_WRITE | MapAttributes::USER_READ | MapAttributes::NON_GLOBAL,
);
result space.allocate(None, len, backing, attrs)
}) })
} }
@ -218,6 +216,8 @@ pub(crate) fn send_signal(pid: ProcessId, signal: Signal) -> Result<(), Error> {
Ok(()) Ok(())
} }
// TODO this would've been much simpler if physical pages behaved like Rc<...>'s and kernel could
// keep a copy of it, guaranteeing it cannot be freed and remapped into another process.
pub(crate) fn mutex(mutex: &AtomicU32, op: &MutexOperation) -> Result<(), Error> { pub(crate) fn mutex(mutex: &AtomicU32, op: &MutexOperation) -> Result<(), Error> {
let thread = Thread::current(); let thread = Thread::current();
let process = thread.process(); let process = thread.process();
@ -225,8 +225,8 @@ pub(crate) fn mutex(mutex: &AtomicU32, op: &MutexOperation) -> Result<(), Error>
let mutex = process.get_or_insert_mutex((mutex as *const AtomicU32).addr())?; let mutex = process.get_or_insert_mutex((mutex as *const AtomicU32).addr())?;
match op { match op {
&MutexOperation::Wait(value, _timeout) => block! { mutex.wait(value).await }, &MutexOperation::Wait(value, _timeout) => block! { mutex.wait(value).await }?,
&MutexOperation::WaitUntil(value, _timeout) => block! { mutex.wait_until(value).await }, &MutexOperation::WaitUntil(value, _timeout) => block! { mutex.wait_until(value).await }?,
MutexOperation::Wake => { MutexOperation::Wake => {
mutex.wake(); mutex.wake();
Ok(()) Ok(())
@ -291,7 +291,10 @@ pub(crate) fn wait_thread(id: u32) -> Result<(), Error> {
} }
pub(crate) fn get_thread_option(option: &mut ThreadOption) -> Result<(), Error> { pub(crate) fn get_thread_option(option: &mut ThreadOption) -> Result<(), Error> {
todo!() match option {
// There're better ways to do this, don't ask the kernel
ThreadOption::ThreadPointer(_) => Err(Error::InvalidOperation),
}
} }
pub(crate) fn set_thread_option(option: &ThreadOption) -> Result<(), Error> { pub(crate) fn set_thread_option(option: &ThreadOption) -> Result<(), Error> {