refactor: fix warnings

This commit is contained in:
Mark Poliakov 2023-12-05 14:55:12 +02:00
parent 15d3e38a2d
commit b6946443b8
28 changed files with 293 additions and 391 deletions

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
kernel-util = { path = "../kernel-util" }
vfs = { path = "../vfs" }
static_assertions = "1.1.0"

View File

@ -19,7 +19,7 @@ pub const ENTRY_COUNT: usize = SIZE / size_of::<usize>();
///
/// This trait is unsafe to implement because it has to provide and accept raw data pointers of
/// exactly [SIZE].
pub unsafe trait BlockAllocator: 'static {
pub unsafe trait BlockAllocator: Send + Sync + 'static {
/// Allocates a contiguous block of size [SIZE]
fn alloc() -> Result<NonNull<u8>, Error>;

View File

@ -1,21 +1,20 @@
use core::{any::Any, cell::RefCell};
use core::any::Any;
use alloc::boxed::Box;
use vfs::{CommonImpl, Node, NodeFlags, NodeRef, RegularImpl};
use kernel_util::sync::IrqSafeSpinlock;
use vfs::{CommonImpl, InstanceData, Node, NodeFlags, NodeRef, RegularImpl};
use yggdrasil_abi::{error::Error, io::OpenOptions};
use crate::{block::BlockAllocator, bvec::BVec};
pub(crate) struct FileNode<A: BlockAllocator> {
// TODO IrqSafeSpinlock
pub(crate) data: RefCell<BVec<'static, A>>,
pub(crate) data: IrqSafeSpinlock<BVec<'static, A>>,
}
impl<A: BlockAllocator> FileNode<A> {
pub fn new() -> NodeRef {
Node::regular(
Self {
data: RefCell::new(BVec::new()),
data: IrqSafeSpinlock::new(BVec::new()),
},
NodeFlags::IN_MEMORY_PROPS,
)
@ -28,7 +27,7 @@ impl<A: BlockAllocator> CommonImpl for FileNode<A> {
}
fn size(&self, _node: &NodeRef) -> Result<u64, Error> {
Ok(self.data.borrow().size() as u64)
Ok(self.data.lock().size() as u64)
}
}
@ -37,10 +36,10 @@ impl<A: BlockAllocator> RegularImpl for FileNode<A> {
&self,
_node: &NodeRef,
opts: OpenOptions,
) -> Result<(u64, Option<Box<dyn Any>>), Error> {
) -> Result<(u64, Option<InstanceData>), Error> {
// TODO provide APPEND by vfs driver instead
if opts.contains(OpenOptions::APPEND) {
Ok((self.data.borrow().size() as u64, None))
Ok((self.data.lock().size() as u64, None))
} else {
Ok((0, None))
}
@ -49,24 +48,24 @@ impl<A: BlockAllocator> RegularImpl for FileNode<A> {
fn read(
&self,
_node: &NodeRef,
_instance: Option<&Box<dyn Any>>,
_instance: Option<&InstanceData>,
pos: u64,
buf: &mut [u8],
) -> Result<usize, Error> {
self.data.borrow().read(pos, buf)
self.data.lock().read(pos, buf)
}
fn write(
&self,
_node: &NodeRef,
_instance: Option<&Box<dyn Any>>,
_instance: Option<&InstanceData>,
pos: u64,
buf: &[u8],
) -> Result<usize, Error> {
self.data.borrow_mut().write(pos, buf)
self.data.lock().write(pos, buf)
}
fn close(&self, _node: &NodeRef, _instance: Option<&Box<dyn Any>>) -> Result<(), Error> {
fn close(&self, _node: &NodeRef, _instance: Option<&InstanceData>) -> Result<(), Error> {
Ok(())
}
}

View File

@ -1,7 +1,7 @@
//! In-memory filesystem driver
#![no_std]
#![deny(missing_docs)]
#![allow(clippy::new_without_default)]
#![allow(clippy::new_without_default, clippy::new_ret_no_self)]
#![feature(
const_mut_refs,
maybe_uninit_uninit_array,
@ -158,7 +158,7 @@ impl<A: BlockAllocator> MemoryFilesystem<A> {
if hdr.node_kind() == FileType::File {
let data = data.unwrap();
let node_data = node.data_as_ref::<FileNode<A>>();
let mut bvec = node_data.data.borrow_mut();
let mut bvec = node_data.data.lock();
bvec.init_with_cow(data)?;
assert_eq!(bvec.size(), data.len());

View File

@ -4,7 +4,7 @@ use crate::node::{CommonImpl, NodeRef};
/// Block device interface
#[allow(unused)]
pub trait BlockDevice {
pub trait BlockDevice: Sync {
/// Reads data frmo the given offset of the device
fn read(&'static self, pos: u64, buf: &mut [u8]) -> Result<usize, Error> {
Err(Error::NotImplemented)
@ -36,7 +36,7 @@ pub trait BlockDevice {
/// Character device interface
#[allow(unused)]
pub trait CharDevice {
pub trait CharDevice: Sync {
/// Reads data from the device
fn read(&'static self, buf: &mut [u8]) -> Result<usize, Error> {
Err(Error::NotImplemented)

View File

@ -1,5 +1,4 @@
use core::cell::Cell;
use kernel_util::sync::IrqSafeSpinlock;
use yggdrasil_abi::{error::Error, io::SeekFrom};
use crate::{
@ -10,7 +9,7 @@ use crate::{
pub struct BlockFile {
pub(super) device: BlockDeviceWrapper,
pub(super) node: NodeRef,
pub(super) position: Cell<u64>,
pub(super) position: IrqSafeSpinlock<u64>,
pub(super) read: bool,
pub(super) write: bool,
}
@ -24,24 +23,25 @@ pub struct CharFile {
impl BlockFile {
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
let pos = self.position.get();
let count = self.device.0.read(pos, buf)?;
self.position.set(pos + count as u64);
let mut position = self.position.lock();
let count = self.device.0.read(*position, buf)?;
*position += count as u64;
Ok(count)
}
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
let pos = self.position.get();
let count = self.device.0.write(pos, buf)?;
self.position.set(pos + count as u64);
let mut position = self.position.lock();
let count = self.device.0.write(*position, buf)?;
*position += count as u64;
Ok(count)
}
pub fn seek(&self, from: SeekFrom) -> Result<u64, Error> {
let pos = self.position.get();
let mut position = self.position.lock();
let newpos = match from {
SeekFrom::Current(off) => {
let newpos = i64::try_from(pos).unwrap() + off;
let newpos = i64::try_from(*position).unwrap() + off;
if newpos < 0 {
return Err(Error::InvalidArgument);
}
@ -60,7 +60,7 @@ impl BlockFile {
}
};
self.position.set(newpos);
*position = newpos;
Ok(newpos)
}
}

View File

@ -1,5 +1,6 @@
use core::{cell::Cell, mem::MaybeUninit, str::FromStr};
use core::{mem::MaybeUninit, str::FromStr};
use kernel_util::sync::IrqSafeSpinlock;
use yggdrasil_abi::{error::Error, io::DirectoryEntry, util::FixedString};
use crate::node::NodeRef;
@ -21,7 +22,7 @@ pub(super) enum DirectoryPosition {
pub struct DirectoryFile {
pub(super) node: NodeRef,
pub(super) position: Cell<DirectoryPosition>,
pub(super) position: IrqSafeSpinlock<DirectoryPosition>,
}
impl DirectoryFile {
@ -79,8 +80,9 @@ impl DirectoryFile {
&self,
entries: &mut [MaybeUninit<DirectoryEntry>],
) -> Result<usize, Error> {
let pos = self.position.get();
let (count, pos) = match pos {
let mut position = self.position.lock();
let (count, pos) = match *position {
DirectoryPosition::Cache(pos) => {
let (count, pos) = DirectoryFile::read_cached(&self.node, pos, entries)?;
(count, DirectoryPosition::Cache(pos))
@ -90,7 +92,7 @@ impl DirectoryFile {
(count, DirectoryPosition::Physical(pos))
}
};
self.position.set(pos);
*position = pos;
Ok(count)
}

View File

@ -1,6 +1,7 @@
use core::{any::Any, cell::Cell, fmt, mem::MaybeUninit};
use core::{any::Any, fmt, mem::MaybeUninit};
use alloc::{boxed::Box, sync::Arc};
use kernel_util::sync::IrqSafeSpinlock;
use yggdrasil_abi::{
error::Error,
io::{DirectoryEntry, OpenOptions, SeekFrom},
@ -22,6 +23,9 @@ mod device;
mod directory;
mod regular;
/// Per-file optional instance data created when a regular file is opened
pub type InstanceData = Box<dyn Any + Send + Sync>;
/// Describes the starting position of the directory
pub enum DirectoryOpenPosition {
/// Contents should be fetched from the directory impl with given offset
@ -45,14 +49,14 @@ pub enum File {
impl File {
pub(crate) fn directory(node: NodeRef, position: DirectoryOpenPosition) -> Arc<Self> {
let position = Cell::new(position.into());
let position = IrqSafeSpinlock::new(position.into());
Arc::new(Self::Directory(DirectoryFile { node, position }))
}
pub(crate) fn regular(
node: NodeRef,
position: u64,
instance_data: Option<Box<dyn Any>>,
instance_data: Option<InstanceData>,
opts: OpenOptions,
) -> Arc<Self> {
let read = opts.contains(OpenOptions::READ);
@ -63,7 +67,7 @@ impl File {
read,
write,
instance_data,
position: Cell::new(position),
position: IrqSafeSpinlock::new(position),
}))
}
@ -85,7 +89,7 @@ impl File {
Ok(Arc::new(Self::Block(BlockFile {
device,
node,
position: Cell::new(0),
position: IrqSafeSpinlock::new(0),
read,
write,
})))
@ -158,8 +162,8 @@ impl Write for File {
impl Seek for File {
fn tell(&self) -> Result<u64, Error> {
match self {
Self::Regular(file) => Ok(file.position.get()),
Self::Block(file) => Ok(file.position.get()),
Self::Regular(file) => Ok(*file.position.lock()),
Self::Block(file) => Ok(*file.position.lock()),
Self::Char(_) => Err(Error::InvalidOperation),
Self::Directory(_) => Err(Error::IsADirectory),
}
@ -180,13 +184,13 @@ impl fmt::Debug for File {
match self {
Self::Regular(file) => f
.debug_struct("RegularFile")
.field("position", &file.position.get())
.field("position", &*file.position.lock())
.field("read", &file.read)
.field("write", &file.write)
.finish_non_exhaustive(),
Self::Block(file) => f
.debug_struct("BlockFile")
.field("position", &file.position.get())
.field("position", &*file.position.lock())
.field("read", &file.read)
.field("write", &file.write)
.finish_non_exhaustive(),
@ -202,8 +206,8 @@ impl fmt::Debug for File {
#[cfg(test)]
mod tests {
use core::{any::Any, cell::RefCell, mem::MaybeUninit, str::FromStr};
use std::sync::Arc;
use core::{mem::MaybeUninit, str::FromStr};
use std::sync::{Arc, Mutex};
use kernel_util::sync::IrqSafeSpinlock;
use yggdrasil_abi::{
@ -215,10 +219,26 @@ mod tests {
use crate::{
device::{BlockDevice, CharDevice},
file::DirectoryOpenPosition,
impls::const_value_node,
node::{AccessToken, CommonImpl, DirectoryImpl, Node, NodeFlags, NodeRef, RegularImpl},
traits::{Read, Seek, Write},
InstanceData,
};
#[test]
fn file_send_sync() {
fn file_send<T: Send>(_f: &T) {}
fn file_sync<T: Sync>(_f: &T) {}
let node = const_value_node("1234");
let file = node
.open(OpenOptions::READ, AccessToken::test_authorized())
.unwrap();
file_send(&file);
file_sync(&file);
}
#[test]
fn physical_dir_read() {
struct D {
@ -350,12 +370,12 @@ mod tests {
#[test]
fn file_read_write() {
struct F {
data: Arc<RefCell<Vec<u8>>>,
data: Arc<Mutex<Vec<u8>>>,
}
impl CommonImpl for F {
fn size(&self, _node: &NodeRef) -> Result<u64, Error> {
Ok(self.data.borrow().len() as _)
Ok(self.data.lock().unwrap().len() as _)
}
}
impl RegularImpl for F {
@ -363,19 +383,19 @@ mod tests {
&self,
_node: &NodeRef,
_opts: OpenOptions,
) -> Result<(u64, Option<Box<dyn Any>>), Error> {
) -> Result<(u64, Option<InstanceData>), Error> {
Ok((0, None))
}
fn read(
&self,
_node: &NodeRef,
_instance: Option<&Box<dyn Any>>,
_instance: Option<&InstanceData>,
pos: u64,
buf: &mut [u8],
) -> Result<usize, Error> {
let pos = pos as usize;
let data = self.data.borrow();
let data = self.data.lock().unwrap();
if pos >= data.len() {
return Ok(0);
}
@ -387,19 +407,19 @@ mod tests {
fn write(
&self,
_node: &NodeRef,
_instance: Option<&Box<dyn Any>>,
_instance: Option<&InstanceData>,
pos: u64,
buf: &[u8],
) -> Result<usize, Error> {
let pos = pos as usize;
let mut data = self.data.borrow_mut();
let mut data = self.data.lock().unwrap();
data.resize(pos + buf.len(), 0);
data[pos..pos + buf.len()].copy_from_slice(buf);
Ok(buf.len())
}
}
let data = Arc::new(RefCell::new(vec![]));
let data = Arc::new(Mutex::new(vec![]));
let node = Node::regular(F { data: data.clone() }, NodeFlags::empty());
let file = node
.open(
@ -409,19 +429,19 @@ mod tests {
.unwrap();
let mut buf = [0; 512];
assert_eq!(&*data.borrow(), &[]);
assert_eq!(&*data.lock().unwrap(), &[]);
assert_eq!(file.tell().unwrap(), 0);
assert_eq!(file.write(b"Hello").unwrap(), 5);
assert_eq!(file.tell().unwrap(), 5);
assert_eq!(&*data.borrow(), b"Hello");
assert_eq!(&*data.lock().unwrap(), b"Hello");
assert_eq!(file.seek(SeekFrom::End(-2)).unwrap(), 3);
assert_eq!(file.tell().unwrap(), 3);
assert_eq!(file.write(b"123456").unwrap(), 6);
assert_eq!(file.tell().unwrap(), 9);
assert_eq!(&*data.borrow(), b"Hel123456");
assert_eq!(&*data.lock().unwrap(), b"Hel123456");
assert_eq!(file.seek(SeekFrom::Start(2)).unwrap(), 2);
assert_eq!(file.read(&mut buf).unwrap(), 7);

View File

@ -1,15 +1,15 @@
use alloc::boxed::Box;
use core::{any::Any, cell::Cell};
use kernel_util::sync::IrqSafeSpinlock;
use yggdrasil_abi::{error::Error, io::SeekFrom};
use super::InstanceData;
use crate::node::NodeRef;
pub struct RegularFile {
pub(super) node: NodeRef,
pub(super) read: bool,
pub(super) write: bool,
pub(super) instance_data: Option<Box<dyn Any>>,
pub(super) position: Cell<u64>,
pub(super) instance_data: Option<InstanceData>,
pub(super) position: IrqSafeSpinlock<u64>,
}
impl RegularFile {
@ -17,10 +17,10 @@ impl RegularFile {
if !self.read {
return Err(Error::InvalidFile);
}
let mut position = self.position.lock();
let reg = self.node.as_regular()?;
let pos = self.position.get();
let count = reg.read(&self.node, self.instance_data.as_ref(), pos, buf)?;
self.position.set(pos + count as u64);
let count = reg.read(&self.node, self.instance_data.as_ref(), *position, buf)?;
*position += count as u64;
Ok(count)
}
@ -28,19 +28,20 @@ impl RegularFile {
if !self.write {
return Err(Error::InvalidFile);
}
let mut position = self.position.lock();
let reg = self.node.as_regular()?;
let pos = self.position.get();
let count = reg.write(&self.node, self.instance_data.as_ref(), pos, buf)?;
self.position.set(pos + count as u64);
let count = reg.write(&self.node, self.instance_data.as_ref(), *position, buf)?;
*position += count as u64;
Ok(count)
}
// TODO should seek beyond the end of a read-only file be allowed?
pub fn seek(&self, from: SeekFrom) -> Result<u64, Error> {
let pos = self.position.get();
let mut position = self.position.lock();
let newpos = match from {
SeekFrom::Current(off) => {
let newpos = i64::try_from(pos).unwrap() + off;
let newpos = i64::try_from(*position).unwrap() + off;
if newpos < 0 {
return Err(Error::InvalidArgument);
}
@ -60,7 +61,7 @@ impl RegularFile {
}
};
self.position.set(newpos);
*position = newpos;
Ok(newpos)
}
}

View File

@ -1,6 +1,7 @@
//! Virtual filesystem interfaces and driver implementation
#![cfg_attr(not(test), no_std)]
#![allow(clippy::new_ret_no_self)]
#![deny(missing_docs)]
#![feature(
trait_upcasting,
@ -23,7 +24,7 @@ pub(crate) mod path;
pub(crate) mod traits;
pub use device::{BlockDevice, CharDevice};
pub use file::{DirectoryOpenPosition, File, FileRef};
pub use file::{DirectoryOpenPosition, File, FileRef, InstanceData};
pub use ioctx::{Action, IoContext};
pub use node::{
impls, AccessToken, CommonImpl, CreateInfo, DirectoryImpl, Metadata, Node, NodeFlags, NodeRef,

View File

@ -1,5 +1,5 @@
//! Various helper node implementations for convenience
use core::{any::Any, cell::RefCell, marker::PhantomData, str::FromStr};
use core::{marker::PhantomData, str::FromStr};
use alloc::{
boxed::Box,
@ -8,9 +8,10 @@ use alloc::{
vec::Vec,
};
use kernel_util::sync::IrqSafeSpinlock;
use yggdrasil_abi::{error::Error, io::OpenOptions};
use crate::DirectoryOpenPosition;
use crate::{DirectoryOpenPosition, InstanceData};
use super::{CommonImpl, DirectoryImpl, Node, NodeFlags, NodeRef, RegularImpl, SymlinkImpl};
@ -22,18 +23,18 @@ trait SliceWrite {
fn write_slice(&mut self, offset: usize, buf: &[u8]) -> usize;
}
trait IntoInstanceData {
fn into_instance_data(&self) -> Vec<u8>;
trait AsInstanceData {
fn as_instance_data(&self) -> Vec<u8>;
}
/// Closure interface for reading a single value
pub trait ValueReadFn<T> = Fn() -> Result<T, Error>;
pub trait ValueReadFn<T> = Fn() -> Result<T, Error> + Send + Sync;
/// Closure interface for writing a single value
pub trait ValueWriteFn<T> = Fn(T) -> Result<(), Error>;
pub trait ValueWriteFn<T> = Fn(T) -> Result<(), Error> + Send + Sync;
/// Closure interface for reading bytes
pub trait ReadFn = Fn(u64, &mut [u8]) -> Result<usize, Error>;
pub trait ReadFn = Fn(u64, &mut [u8]) -> Result<usize, Error> + Send + Sync;
/// Closure interface for writing bytes
pub trait WriteFn = Fn(u64, &[u8]) -> Result<usize, Error>;
pub trait WriteFn = Fn(u64, &[u8]) -> Result<usize, Error> + Send + Sync;
impl<T: AsRef<[u8]>> SliceRead for T {
fn read_slice(&self, pos: usize, buf: &mut [u8]) -> usize {
@ -57,15 +58,15 @@ impl SliceWrite for Vec<u8> {
}
}
impl<T: ToString> IntoInstanceData for T {
fn into_instance_data(&self) -> Vec<u8> {
impl<T: ToString> AsInstanceData for T {
fn as_instance_data(&self) -> Vec<u8> {
self.to_string().as_bytes().to_vec()
}
}
enum FnNodeData {
Read(Vec<u8>),
Write(RefCell<Vec<u8>>),
Write(IrqSafeSpinlock<Vec<u8>>),
}
/// Allows read-only access to a value. The value is converted to a string representation when it's
@ -95,7 +96,11 @@ pub struct FixedSymlink {
target: NodeRef,
}
impl<T: ToString + 'static, R: ValueReadFn<T> + 'static> ReadOnlyFnValueNode<T, R> {
impl<T, R> ReadOnlyFnValueNode<T, R>
where
T: ToString + Send + Sync + 'static,
R: ValueReadFn<T> + 'static,
{
/// Creates a new [ReadOnlyFnValueNode] with given read function
pub fn new(read: R) -> NodeRef {
Node::regular(
@ -112,29 +117,37 @@ impl<T: ToString + 'static, R: ValueReadFn<T> + 'static> ReadOnlyFnValueNode<T,
}
}
impl<T: ToString, R: ValueReadFn<T>> CommonImpl for ReadOnlyFnValueNode<T, R> {
impl<T, R> CommonImpl for ReadOnlyFnValueNode<T, R>
where
T: ToString + Send + Sync,
R: ValueReadFn<T>,
{
fn size(&self, _node: &NodeRef) -> Result<u64, Error> {
Ok(0)
}
}
impl<T: ToString + 'static, R: ValueReadFn<T>> RegularImpl for ReadOnlyFnValueNode<T, R> {
impl<T, R> RegularImpl for ReadOnlyFnValueNode<T, R>
where
T: ToString + Send + Sync,
R: ValueReadFn<T>,
{
fn open(
&self,
_node: &NodeRef,
opts: OpenOptions,
) -> Result<(u64, Option<Box<dyn Any>>), Error> {
) -> Result<(u64, Option<InstanceData>), Error> {
if opts.contains(OpenOptions::WRITE) {
return Err(Error::ReadOnly);
}
let t = (self.read)()?;
Ok((0, Some(Box::new(t.into_instance_data()))))
Ok((0, Some(Box::new(t.as_instance_data()))))
}
fn read(
&self,
_node: &NodeRef,
instance: Option<&Box<dyn Any>>,
instance: Option<&InstanceData>,
pos: u64,
buf: &mut [u8],
) -> Result<usize, Error> {
@ -145,7 +158,7 @@ impl<T: ToString + 'static, R: ValueReadFn<T>> RegularImpl for ReadOnlyFnValueNo
fn write(
&self,
_node: &NodeRef,
_instance: Option<&Box<dyn Any>>,
_instance: Option<&InstanceData>,
_pos: u64,
_buf: &[u8],
) -> Result<usize, Error> {
@ -157,11 +170,11 @@ impl<T: ToString + 'static, R: ValueReadFn<T>> RegularImpl for ReadOnlyFnValueNo
impl FnNodeData {
fn write() -> Self {
Self::Write(RefCell::new(Vec::new()))
Self::Write(IrqSafeSpinlock::new(Vec::new()))
}
fn read<T: IntoInstanceData>(value: T) -> Self {
Self::Read(value.into_instance_data())
fn read<T: AsInstanceData>(value: T) -> Self {
Self::Read(value.as_instance_data())
}
fn as_read(&self) -> Result<&Vec<u8>, Error> {
@ -171,7 +184,7 @@ impl FnNodeData {
}
}
fn as_write(&self) -> Result<&RefCell<Vec<u8>>, Error> {
fn as_write(&self) -> Result<&IrqSafeSpinlock<Vec<u8>>, Error> {
match self {
Self::Write(w) => Ok(w),
Self::Read(_) => Err(Error::InvalidOperation),
@ -181,7 +194,7 @@ impl FnNodeData {
impl<T, R, W> FnValueNode<T, R, W>
where
T: ToString + FromStr + 'static,
T: ToString + FromStr + Send + Sync + 'static,
R: ValueReadFn<T> + 'static,
W: ValueWriteFn<T> + 'static,
{
@ -202,22 +215,28 @@ where
}
}
impl<T: ToString + FromStr, R: ValueReadFn<T>, W: ValueWriteFn<T>> CommonImpl
for FnValueNode<T, R, W>
impl<T, R, W> CommonImpl for FnValueNode<T, R, W>
where
T: ToString + FromStr + Send + Sync,
R: ValueReadFn<T>,
W: ValueWriteFn<T>,
{
fn size(&self, _node: &NodeRef) -> Result<u64, Error> {
Ok(0)
}
}
impl<T: ToString + FromStr, R: ValueReadFn<T>, W: ValueWriteFn<T>> RegularImpl
for FnValueNode<T, R, W>
impl<T, R, W> RegularImpl for FnValueNode<T, R, W>
where
T: ToString + FromStr + Send + Sync,
R: ValueReadFn<T>,
W: ValueWriteFn<T>,
{
fn open(
&self,
_node: &NodeRef,
opts: OpenOptions,
) -> Result<(u64, Option<Box<dyn Any>>), Error> {
) -> Result<(u64, Option<InstanceData>), Error> {
if opts.contains(OpenOptions::READ | OpenOptions::WRITE) {
Err(Error::InvalidOperation)
} else if opts.contains(OpenOptions::WRITE) {
@ -230,14 +249,14 @@ impl<T: ToString + FromStr, R: ValueReadFn<T>, W: ValueWriteFn<T>> RegularImpl
}
}
fn close(&self, _node: &NodeRef, instance: Option<&Box<dyn Any>>) -> Result<(), Error> {
fn close(&self, _node: &NodeRef, instance: Option<&InstanceData>) -> Result<(), Error> {
if let Ok(write) = instance
.unwrap()
.downcast_ref::<FnNodeData>()
.unwrap()
.as_write()
{
let write = write.borrow();
let write = write.lock();
// Flush write
let str = core::str::from_utf8(write.as_ref())
.map_err(|_| Error::InvalidArgument)?
@ -252,7 +271,7 @@ impl<T: ToString + FromStr, R: ValueReadFn<T>, W: ValueWriteFn<T>> RegularImpl
fn read(
&self,
_node: &NodeRef,
instance: Option<&Box<dyn Any>>,
instance: Option<&InstanceData>,
pos: u64,
buf: &mut [u8],
) -> Result<usize, Error> {
@ -263,12 +282,12 @@ impl<T: ToString + FromStr, R: ValueReadFn<T>, W: ValueWriteFn<T>> RegularImpl
fn write(
&self,
_node: &NodeRef,
instance: Option<&Box<dyn Any>>,
instance: Option<&InstanceData>,
pos: u64,
buf: &[u8],
) -> Result<usize, Error> {
let instance = instance.unwrap().downcast_ref::<FnNodeData>().unwrap();
Ok(instance.as_write()?.borrow_mut().write_slice(pos as _, buf))
Ok(instance.as_write()?.lock().write_slice(pos as _, buf))
}
}
@ -301,7 +320,7 @@ where
&self,
_node: &NodeRef,
opts: OpenOptions,
) -> Result<(u64, Option<Box<dyn Any>>), Error> {
) -> Result<(u64, Option<InstanceData>), Error> {
if opts.contains(OpenOptions::WRITE) {
return Err(Error::ReadOnly);
}
@ -311,7 +330,7 @@ where
fn read(
&self,
_node: &NodeRef,
_instance: Option<&Box<dyn Any>>,
_instance: Option<&InstanceData>,
pos: u64,
buf: &mut [u8],
) -> Result<usize, Error> {
@ -348,19 +367,25 @@ impl SymlinkImpl for FixedSymlink {
}
/// Creates a read-only value node with given `value`
pub fn const_value_node<T: ToString + Clone + 'static>(value: T) -> NodeRef {
pub fn const_value_node<T>(value: T) -> NodeRef
where
T: ToString + Clone + Send + Sync + 'static,
{
ReadOnlyFnValueNode::new(move || Ok(value.clone()))
}
/// Creates a read-write value node with given `value`
pub fn value_node<T: ToString + FromStr + Clone + 'static>(value: T) -> NodeRef {
let rd_state = Arc::new(RefCell::new(value));
pub fn value_node<T>(value: T) -> NodeRef
where
T: ToString + FromStr + Clone + Send + Sync + 'static,
{
let rd_state = Arc::new(IrqSafeSpinlock::new(value));
let wr_state = rd_state.clone();
FnValueNode::new(
move || Ok(rd_state.borrow().clone()),
move || Ok(rd_state.lock().clone()),
move |t| {
*wr_state.borrow_mut() = t;
*wr_state.lock() = t;
Ok(())
},
)

View File

@ -295,7 +295,7 @@ mod tests {
use core::any::Any;
use std::sync::Arc;
use crate::node::NodeFlags;
use crate::{node::NodeFlags, NodeRef};
use super::{CommonImpl, DirectoryImpl, Node, RegularImpl};
@ -308,6 +308,15 @@ mod tests {
impl CommonImpl for DummyFile {}
impl RegularImpl for DummyFile {}
#[test]
fn node_sync_send() {
fn node_send<T: Send>(_n: &T) {}
let node = Node::regular(DummyFile, NodeFlags::empty());
node_send(&node);
}
#[test]
fn dir_cache_add() {
let d1 = Node::directory(DummyDirectory, NodeFlags::empty());

View File

@ -6,13 +6,13 @@ use yggdrasil_abi::{
io::{DirectoryEntry, FileType, OpenOptions},
};
use crate::file::DirectoryOpenPosition;
use crate::file::{DirectoryOpenPosition, InstanceData};
use super::{Metadata, NodeRef};
/// Common interface shared by all filesystem nodes
#[allow(unused)]
pub trait CommonImpl {
pub trait CommonImpl: Send + Sync {
/// Returns `&self` as a reference to `dyn Any`
fn as_any(&self) -> &dyn Any {
unimplemented!();
@ -37,12 +37,12 @@ pub trait RegularImpl: CommonImpl {
&self,
node: &NodeRef,
opts: OpenOptions,
) -> Result<(u64, Option<Box<dyn Any>>), Error> {
) -> Result<(u64, Option<InstanceData>), Error> {
Err(Error::NotImplemented)
}
/// Closes a file
fn close(&self, node: &NodeRef, instance: Option<&Box<dyn Any>>) -> Result<(), Error> {
fn close(&self, node: &NodeRef, instance: Option<&InstanceData>) -> Result<(), Error> {
Ok(())
}
@ -50,7 +50,7 @@ pub trait RegularImpl: CommonImpl {
fn read(
&self,
node: &NodeRef,
instance: Option<&Box<dyn Any>>,
instance: Option<&InstanceData>,
pos: u64,
buf: &mut [u8],
) -> Result<usize, Error> {
@ -60,7 +60,7 @@ pub trait RegularImpl: CommonImpl {
fn write(
&self,
node: &NodeRef,
instance: Option<&Box<dyn Any>>,
instance: Option<&InstanceData>,
pos: u64,
buf: &[u8],
) -> Result<usize, Error> {

View File

@ -16,7 +16,7 @@ use abi::{
use tock_registers::interfaces::{Readable, Writeable};
use crate::{
arch::{aarch64::cpu::Cpu, Architecture, ArchitectureImpl},
arch::{Architecture, ArchitectureImpl},
debug::LogLevel,
syscall::raw_syscall_handler,
task::{context::TaskFrame, thread::Thread},
@ -117,7 +117,7 @@ pub fn init_exceptions() {
}
fn dump_irrecoverable_exception(frame: &ExceptionFrame, ec: u64, iss: u64) {
let cpu = Cpu::get_local();
// let cpu = Cpu::get_local();
log_print_raw!(LogLevel::Fatal, "SYNC exception:\n");
log_print_raw!(LogLevel::Fatal, "FAR: {:#x}\n", FAR_EL1.get());

View File

@ -2,17 +2,9 @@
use core::fmt::{self, Arguments};
use abi::error::Error;
use alloc::sync::Arc;
use futures_util::Future;
use kernel_util::{
sync::IrqSafeSpinlock,
util::{OneTimeInit, StaticVector},
};
use kernel_util::{sync::IrqSafeSpinlock, util::StaticVector};
use crate::{
task::{process::Process, runtime::QueueWaker},
util::ring::RingBuffer,
};
use crate::{task::process::Process, util::ring::RingBuffer};
const MAX_DEBUG_SINKS: usize = 4;
const RING_LOGGER_CAPACITY: usize = 65536;
@ -25,7 +17,6 @@ struct RingLoggerInner {
pub struct RingLoggerSink {
inner: IrqSafeSpinlock<RingLoggerInner>,
waker: QueueWaker,
}
/// Defines the severity of the message
@ -175,12 +166,11 @@ impl RingLoggerSink {
inner: IrqSafeSpinlock::new(RingLoggerInner {
data: RingBuffer::new(0),
}),
waker: QueueWaker::new(),
}
}
pub fn read(&self, pos: usize, buffer: &mut [u8]) -> usize {
unsafe { self.inner.lock().data.read_all_static(pos, buffer) }
self.inner.lock().data.read_all_static(pos, buffer)
}
fn write_fmt(&self, args: fmt::Arguments<'_>) -> fmt::Result {
@ -192,9 +182,7 @@ impl RingLoggerSink {
impl fmt::Write for RingLoggerInner {
fn write_str(&mut self, s: &str) -> fmt::Result {
for ch in s.bytes() {
unsafe {
self.data.write_unchecked(ch);
}
self.data.write(ch);
}
Ok(())
}

View File

@ -299,7 +299,7 @@ impl TtyContext {
}
pub fn set_config(&self, config: &TerminalOptions) -> Result<(), Error> {
self.inner.lock().config = config.clone();
self.inner.lock().config = *config;
Ok(())
}

View File

@ -1,18 +1,15 @@
//! Device virtual file system
use core::sync::atomic::{AtomicU32, AtomicU8, AtomicUsize, Ordering};
use core::sync::atomic::{AtomicUsize, Ordering};
use abi::error::Error;
use alloc::{format, string::String, sync::Arc};
use kernel_util::{sync::IrqSafeSpinlock, util::OneTimeInit};
use alloc::{format, string::String};
use kernel_util::util::OneTimeInit;
use vfs::{
impls::{mdir, read_fn_node, MemoryDirectory},
impls::{read_fn_node, MemoryDirectory},
CharDevice, Node, NodeFlags, NodeRef,
};
use crate::{
arch::{Architecture, ARCHITECTURE},
proc::random,
};
use crate::proc::random;
/// Describes the kind of a character device
#[derive(Debug)]

View File

@ -1,13 +1,4 @@
use core::{any::Any, marker::PhantomData};
use abi::{
error::Error,
io::{FileAttr, FileMode, FileType, OpenOptions},
};
use alloc::{
boxed::Box,
string::{String, ToString},
};
use abi::error::Error;
use git_version::git_version;
use kernel_util::util::OneTimeInit;
use vfs::{

View File

@ -8,7 +8,7 @@ use crate::{
arch::{Architecture, ArchitectureImpl, CpuMessage, ARCHITECTURE},
debug::{debug_internal, LogLevel},
device::display::console::flush_consoles,
task::{sched::CpuQueue, Cpu},
task::Cpu,
};
static PANIC_HANDLED_FENCE: SpinFence = SpinFence::new();
@ -49,80 +49,66 @@ fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
static PANIC_HAPPENED: AtomicBool = AtomicBool::new(false);
infoln!("{:?}", pi);
fatalln!("{:?}", pi);
// if PANIC_HAPPENED
// .compare_exchange(false, true, Ordering::Release, Ordering::Acquire)
// .is_ok()
// {
// let id = Cpu::local_id();
// // Let other CPUs know we're screwed
// unsafe {
// ARCHITECTURE
// .send_ipi(IpiDeliveryTarget::OtherCpus, CpuMessage::Panic)
// .ok();
// }
if PANIC_HAPPENED
.compare_exchange(false, true, Ordering::Release, Ordering::Acquire)
.is_ok()
{
let id = Cpu::local_id();
// Let other CPUs know we're screwed
unsafe {
ARCHITECTURE
.send_ipi(IpiDeliveryTarget::OtherCpus, CpuMessage::Panic)
.ok();
}
// let ap_count = ArchitectureImpl::cpu_count() - 1;
// PANIC_HANDLED_FENCE.wait_all(ap_count);
let ap_count = ArchitectureImpl::cpu_count() - 1;
PANIC_HANDLED_FENCE.wait_all(ap_count);
// unsafe {
// hack_locks();
// }
unsafe {
hack_locks();
}
// log_print_raw!(LogLevel::Fatal, "--- BEGIN PANIC ---\n");
// log_print_raw!(LogLevel::Fatal, "In CPU {}\n", Cpu::local_id());
// log_print_raw!(LogLevel::Fatal, "Kernel panic ");
log_print_raw!(LogLevel::Fatal, "--- BEGIN PANIC ---\n");
log_print_raw!(LogLevel::Fatal, "In CPU {}\n", Cpu::local_id());
log_print_raw!(LogLevel::Fatal, "Kernel panic ");
// if let Some(location) = pi.location() {
// log_print_raw!(
// LogLevel::Fatal,
// "at {}:{}:",
// location.file(),
// location.line()
// );
// } else {
// log_print_raw!(LogLevel::Fatal, ":");
// }
if let Some(location) = pi.location() {
log_print_raw!(
LogLevel::Fatal,
"at {}:{}:",
location.file(),
location.line()
);
} else {
log_print_raw!(LogLevel::Fatal, ":");
}
// log_print_raw!(LogLevel::Fatal, "\n");
log_print_raw!(LogLevel::Fatal, "\n");
// if let Some(msg) = pi.message() {
// debug_internal(*msg, LogLevel::Fatal);
// log_print_raw!(LogLevel::Fatal, "\n");
// }
if let Some(msg) = pi.message() {
debug_internal(*msg, LogLevel::Fatal);
log_print_raw!(LogLevel::Fatal, "\n");
}
// for (i, queue) in CpuQueue::all().enumerate() {
// log_print_raw!(LogLevel::Fatal, "queue{}:\n", i);
// let lock = unsafe { queue.grab() };
// for item in lock.iter() {
// log_print_raw!(
// LogLevel::Fatal,
// "* {} {:?} {:?}\n",
// item.id(),
// item.name(),
// item.state()
// );
// }
// }
log_print_raw!(LogLevel::Fatal, "--- END PANIC ---\n");
// log_print_raw!(LogLevel::Fatal, "--- END PANIC ---\n");
PANIC_FINISHED_FENCE.signal();
while PANIC_SEQUENCE.load(Ordering::Acquire) != id {
core::hint::spin_loop();
}
// PANIC_FINISHED_FENCE.signal();
// while PANIC_SEQUENCE.load(Ordering::Acquire) != id {
// core::hint::spin_loop();
// }
log_print_raw!(LogLevel::Fatal, "X");
// log_print_raw!(LogLevel::Fatal, "X");
flush_consoles();
// flush_consoles();
PANIC_SEQUENCE.fetch_add(1, Ordering::Release);
// PANIC_SEQUENCE.fetch_add(1, Ordering::Release);
// unsafe {
// ARCHITECTURE.reset();
// }
// }
unsafe {
ARCHITECTURE.reset();
}
}
loop {
ArchitectureImpl::wait_for_interrupt();

View File

@ -255,7 +255,7 @@ fn tls_segment(
load_bytes(
space,
base_address + data_offset + data_size,
|off, mut dst| {
|_, mut dst| {
dst.fill(0);
Ok(())
},
@ -274,12 +274,6 @@ pub fn load_elf_from_file(
let file = FileReader { file: &file };
let elf = ElfStream::<AnyEndian, _>::open_stream(file).map_err(from_parse_error)?;
struct TlsInfo {
master_address: usize,
offset: usize,
size: usize,
}
let mut tls = None;
for phdr in elf.segments() {

View File

@ -11,10 +11,7 @@ use vfs::FileRef;
use crate::{
mem::{
phys,
pointer::{PhysicalRef, PhysicalRefMut},
process::ProcessAddressSpace,
table::MapAttributes,
phys, pointer::PhysicalRefMut, process::ProcessAddressSpace, table::MapAttributes,
ForeignPointer,
},
proc,

View File

@ -2,7 +2,6 @@
use abi::{error::Error, io::RawFd};
use alloc::collections::{btree_map::Entry, BTreeMap};
use kernel_util::sync::IrqSafeSpinlock;
use vfs::{FileRef, IoContext};
/// I/O context of a process, contains information like root, current directory and file

View File

@ -4,18 +4,13 @@ use core::{mem::MaybeUninit, time::Duration};
use abi::{
error::Error,
io::{DeviceRequest, DirectoryEntry, FileAttr, FileMode, OpenOptions, RawFd, SeekFrom},
path::Path,
process::{ExitCode, MutexOperation, Signal, SpawnOption, SpawnOptions, ThreadSpawnOptions},
syscall::SyscallFunction,
};
use alloc::{rc::Rc, sync::Arc};
use alloc::sync::Arc;
use kernel_util::sync::IrqSafeSpinlockGuard;
use vfs::{CreateInfo, IoContext, NodeRef, Read, Seek, Write};
// use vfs::{IoContext, Read, ReadDirectory, Seek, VnodeKind, VnodeRef, Write};
use yggdrasil_abi::{
error::SyscallResult,
io::{MountOptions, UnmountOptions},
};
use vfs::{IoContext, NodeRef, Read, Seek, Write};
use yggdrasil_abi::{error::SyscallResult, io::MountOptions};
use crate::{
block,
@ -135,7 +130,7 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
let opts = OpenOptions::from(args[3] as u32);
let mode = FileMode::from(args[4] as u32);
run_with_io_at(&process, at, |at, mut io| {
run_with_io_at(process, at, |at, mut io| {
let file = io.ioctx().open(at, path, opts, mode)?;
// TODO NO_CTTY?
@ -153,7 +148,7 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
let at = arg_option_fd(args[0] as u32);
let path = arg_user_str(args[1] as usize, args[2] as usize)?;
run_with_io_at(&process, at, |at, mut io| {
run_with_io_at(process, at, |at, mut io| {
let node = io.ioctx().find(at, path, true, true)?;
let access = io.ioctx().check_access(vfs::Action::Read, &node)?;
let file = node.open_directory(access)?;
@ -166,19 +161,19 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
let fd = RawFd(args[0] as u32);
let data = arg_buffer_mut(args[1] as _, args[2] as _)?;
run_with_io(&process, |io| io.file(fd)?.read(data))
run_with_io(process, |io| io.file(fd)?.read(data))
}
SyscallFunction::Write => {
let fd = RawFd(args[0] as u32);
let data = arg_buffer_ref(args[1] as _, args[2] as _)?;
run_with_io(&process, |io| io.file(fd)?.write(data))
run_with_io(process, |io| io.file(fd)?.write(data))
}
SyscallFunction::Seek => {
let fd = RawFd(args[0] as u32);
let pos = SeekFrom::from(args[1]);
run_with_io(&process, |io| io.file(fd)?.seek(pos).map(|v| v as usize))
run_with_io(process, |io| io.file(fd)?.seek(pos).map(|v| v as usize))
}
SyscallFunction::ReadDirectory => {
let fd = RawFd(args[0] as u32);
@ -187,12 +182,12 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
args[2] as usize,
)?;
run_with_io(&process, |io| io.file(fd)?.read_dir(buffer))
run_with_io(process, |io| io.file(fd)?.read_dir(buffer))
}
SyscallFunction::Close => {
let fd = RawFd(args[0] as u32);
run_with_io(&process, |mut io| {
run_with_io(process, |mut io| {
io.close_file(fd)?;
Ok(0)
})
@ -200,7 +195,7 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
SyscallFunction::Mount => {
let options = arg_user_ref::<MountOptions>(args[0] as usize)?;
run_with_io(&process, |mut io| {
run_with_io(process, |mut io| {
let fs_root = fs::create_filesystem(options)?;
io.ioctx().mount(options.target, fs_root)?;
Ok(0)
@ -213,7 +208,7 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
let fd = RawFd(args[0] as u32);
let req = arg_user_mut::<DeviceRequest>(args[1] as usize)?;
run_with_io(&process, |io| {
run_with_io(process, |io| {
let file = io.file(fd)?;
let node = file.node().ok_or(Error::InvalidFile)?;
node.device_request(req)?;
@ -226,7 +221,7 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
let buffer = arg_user_mut::<MaybeUninit<FileAttr>>(args[3] as usize)?;
let follow = args[4] != 0;
run_with_io_at(&process, at, |at, mut io| {
run_with_io_at(process, at, |at, mut io| {
let node = if path.is_empty() {
at.ok_or(Error::InvalidArgument)?
} else {
@ -250,7 +245,7 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
let path = arg_user_str(args[1] as usize, args[2] as usize)?;
let mode = FileMode::from(args[3] as u32);
run_with_io_at(&process, at, |at, mut io| {
run_with_io_at(process, at, |at, mut io| {
io.ioctx().create_directory(at, path, mode)?;
Ok(0)
})
@ -258,9 +253,8 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
SyscallFunction::Remove => {
let at = arg_option_fd(args[0] as u32);
let path = arg_user_str(args[1] as usize, args[2] as usize)?;
let recurse = args[3] != 0;
run_with_io_at(&process, at, |at, mut io| {
run_with_io_at(process, at, |at, mut io| {
io.ioctx().remove_file(at, path)?;
Ok(0)
})
@ -272,7 +266,7 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
SyscallFunction::SpawnProcess => {
let options = arg_user_ref::<SpawnOptions>(args[0] as usize)?;
run_with_io(&process, |mut io| {
run_with_io(process, |mut io| {
// let node = io.ioctx().find(None, options.program, true, true)?;
// Setup a new process from the file
@ -287,7 +281,7 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
let pid: u32 = child_process.id().into();
// Inherit group and session from the creator
child_process.inherit(&process)?;
child_process.inherit(process)?;
// Inherit root from the creator
// let child_ioctx = IoContext::new(io.ioctx().root().clone());
@ -395,10 +389,10 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
if let Some(ctty) = session_terminal {
// Drop all FDs referring to the old session terminal
run_with_io(&process, |mut io| {
run_with_io(process, |mut io| {
io.retain(|_, f| {
f.node()
.map(|node| !Arc::ptr_eq(&node, &ctty))
.map(|node| !Arc::ptr_eq(node, &ctty))
.unwrap_or(true)
});
});

View File

@ -3,18 +3,15 @@
#![allow(dead_code)]
use abi::error::Error;
use alloc::{string::String, sync::Arc, vec::Vec};
use kernel_util::sync::{IrqSafeSpinlock, SpinFence};
use alloc::{string::String, vec::Vec};
use kernel_util::sync::SpinFence;
use crate::{
arch::{Architecture, ArchitectureImpl},
task::{sched::CpuQueue, thread::Thread},
};
use self::{
context::{TaskContextImpl, Termination},
process::Process,
};
use self::context::{TaskContextImpl, Termination};
pub mod context;
pub mod process;
@ -25,48 +22,6 @@ pub mod thread;
pub use context::{Cpu, TaskContext};
// /// Process identifier alias for clarity
// pub type ProcessId = usize;
// /// Wrapper structure to hold all the system's processes
// pub struct ProcessList {
// data: Vec<(ProcessId, Arc<Process>)>,
// last_process_id: ProcessId,
// }
//
// impl ProcessList {
// /// Constructs an empty process list
// pub const fn new() -> Self {
// Self {
// last_process_id: 0,
// data: Vec::new(),
// }
// }
//
// /// Inserts a new process into the list.
// ///
// /// # Safety
// ///
// /// Only meant to be called from inside the Process impl, as this function does not perform any
// /// accounting information updates.
// pub unsafe fn push(&mut self, process: Arc<Process>) -> ProcessId {
// self.last_process_id += 1;
// debugln!("Insert process with ID {}", self.last_process_id);
// self.data.push((self.last_process_id, process));
// self.last_process_id
// }
//
// /// Looks up a process by its ID
// pub fn get(&self, id: ProcessId) -> Option<&Arc<Process>> {
// self.data
// .iter()
// .find_map(|(i, p)| if *i == id { Some(p) } else { None })
// }
// }
//
// /// Global shared process list
// pub static PROCESSES: IrqSafeSpinlock<ProcessList> = IrqSafeSpinlock::new(ProcessList::new());
/// Creates a new kernel-space process to execute a closure and queues it to some CPU
pub fn spawn_kernel_closure<S: Into<String>, T: Termination, F: Fn() -> T + Send + 'static>(
name: S,

View File

@ -4,7 +4,7 @@ use core::{
fmt,
mem::size_of,
pin::Pin,
sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering},
sync::atomic::{AtomicU64, Ordering},
task::{Context, Poll},
};
@ -12,23 +12,13 @@ use abi::{
error::Error,
process::{ExitCode, Signal, ThreadSpawnOptions},
};
use alloc::{
collections::{BTreeMap, VecDeque},
string::String,
sync::Arc,
vec::Vec,
};
use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
use futures_util::Future;
use kernel_util::{sync::IrqSafeSpinlock, util::OneTimeInit};
use kernel_util::sync::IrqSafeSpinlock;
use vfs::NodeRef;
use crate::{
mem::{
phys,
pointer::{PhysicalRef, PhysicalRefMut},
process::ProcessAddressSpace,
table::MapAttributes,
},
mem::process::ProcessAddressSpace,
proc::{self, io::ProcessIo},
task::context::TaskContextImpl,
};
@ -36,7 +26,7 @@ use crate::{
use super::{
runtime::QueueWaker,
sync::UserspaceMutex,
thread::{Thread, ThreadId, ThreadState},
thread::{Thread, ThreadId},
TaskContext,
};
@ -197,8 +187,7 @@ impl Process {
);
let tls_address = if let Some(image) = self.image.as_ref() {
todo!()
// proc::elf::clone_tls(&self.space, image)?
proc::elf::clone_tls(&self.space, image)?
} else {
0
};
@ -378,8 +367,6 @@ impl Process {
impl fmt::Display for ProcessId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Write;
write!(f, "<Process {}>", self.0)
}
}

View File

@ -2,20 +2,11 @@
use core::sync::atomic::Ordering;
// use aarch64_cpu::registers::CNTPCT_EL0;
use alloc::{
collections::{BTreeMap, VecDeque},
sync::Arc,
vec::Vec,
};
use alloc::{collections::VecDeque, sync::Arc, vec::Vec};
use cfg_if::cfg_if;
use kernel_util::{
sync::{IrqGuard, IrqSafeSpinlock, IrqSafeSpinlockGuard},
util::OneTimeInit,
};
use kernel_util::{sync::IrqSafeSpinlock, util::OneTimeInit};
use crate::{
// arch::aarch64::{context::TaskContext, cpu::Cpu},
arch::{Architecture, ArchitectureImpl},
task::thread::ThreadState,
};
@ -169,11 +160,7 @@ impl CpuQueue {
let mut inner = self.inner.lock();
// let t = CNTPCT_EL0.get();
// let delta = t - inner.stats.measure_time;
// inner.stats.measure_time = t;
let current = inner.current.clone();
let current = inner.current;
let current_t = current.and_then(Thread::get);
if let Some(current_t) = current_t.as_ref() {
@ -192,14 +179,10 @@ impl CpuQueue {
.is_ok()
{
inner.queue.push_back(current_t.id());
// inner.stats.cpu_time += delta;
}
}
// else
// inner.stats.idle_time += delta;
let next_t = inner.next_ready_task();
// let next_t = next.and_then(Thread::get);
inner.current = next_t.as_deref().map(Thread::id);
@ -221,23 +204,6 @@ impl CpuQueue {
assert!(ArchitectureImpl::interrupt_mask());
to.switch(from)
// // log_print_raw!(crate::debug::LogLevel::Info, "{}: ", Cpu::local_id());
// // if let Some(from) = current.as_ref() {
// // log_print_raw!(crate::debug::LogLevel::Info, "{}", from.id(),);
// // } else {
// // log_print_raw!(crate::debug::LogLevel::Info, "{{idle}}");
// // }
// // log_print_raw!(crate::debug::LogLevel::Info, " -> ");
// // if let Some(to) = next.as_ref() {
// // log_print_raw!(crate::debug::LogLevel::Info, "{}", to.id(),);
// // } else {
// // log_print_raw!(crate::debug::LogLevel::Info, "{{idle}}");
// // }
// // log_print_raw!(crate::debug::LogLevel::Info, "\n");
}
/// Pushes the process to the back of the execution queue.

View File

@ -18,10 +18,7 @@ use alloc::{
};
use atomic_enum::atomic_enum;
use futures_util::{task::ArcWake, Future};
use kernel_util::{
sync::{IrqGuard, IrqSafeSpinlock},
util::OneTimeInit,
};
use kernel_util::sync::{IrqGuard, IrqSafeSpinlock};
use crate::{
block,
@ -179,17 +176,17 @@ impl Thread {
.queue()
.current_id()
.and_then(Self::get)
.map(|t| unsafe { CurrentThread(t, guard) })
.map(|t| CurrentThread(t, guard))
}
pub fn enqueue_somewhere(&self) {
pub fn enqueue_somewhere(&self) -> usize {
// Doesn't have to be precise, so even if something changes, we can still be rebalanced
// to another CPU
let (index, queue) = CpuQueue::least_loaded().unwrap();
self.enqueue_to(queue);
// index
index
}
pub fn enqueue_to(&self, queue: &'static CpuQueue) {
@ -264,6 +261,11 @@ impl Thread {
}
}
/// Marks the process as running and sets its "current" CPU index.
///
/// # Safety
///
/// Only meant to be called from within the scheduler.
pub unsafe fn set_running(&self, cpu: u32) {
self.cpu_id.store(cpu, Ordering::Release);
self.state.store(ThreadState::Running, Ordering::Release);
@ -400,9 +402,9 @@ impl CurrentThread {
/// This function is only meant to be called right before returning from an userspace
/// exception handler.
pub unsafe fn handle_pending_signals<F: TaskFrame>(&self, frame: &mut F) {
let ThreadId::User(id) = self.id else {
if !self.id.is_user() {
return;
};
}
let mut inner = self.inner.lock();
@ -443,19 +445,6 @@ impl CurrentThread {
// Pass the frame pointer as an argument to signal handler entry
frame.set_argument(usp as _);
}
// let process = self.process();
// if let Some((entry, signal)) = process.pop_signal() {
// debugln!(
// "{} of {}, enter signal handler from pc={:#x}, sp={:#x}",
// self.id,
// process.id(),
// frame.user_ip(),
// frame.user_sp()
// );
// }
}
}
@ -486,12 +475,14 @@ impl ThreadId {
&Self::User(id) => id,
}
}
pub fn is_user(&self) -> bool {
matches!(self, ThreadId::User(_))
}
}
impl fmt::Display for ThreadId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Write;
match self {
Self::Kernel(id) => write!(f, "#[{id}]"),
Self::User(id) => write!(f, "#{id}"),

View File

@ -44,13 +44,13 @@ impl<T: Copy, const N: usize> RingBuffer<T, N> {
}
#[inline]
unsafe fn read_unchecked(&mut self) -> T {
fn read_single(&mut self) -> T {
let res = self.data[self.rd];
self.rd = (self.rd + 1) % N;
res
}
pub unsafe fn read_all_static(&mut self, pos: usize, buffer: &mut [T]) -> usize {
pub fn read_all_static(&mut self, pos: usize, buffer: &mut [T]) -> usize {
let mut pos = (self.rd + pos) % N;
let mut off = 0;
while off < buffer.len() && self.is_readable_at(pos) {
@ -62,7 +62,7 @@ impl<T: Copy, const N: usize> RingBuffer<T, N> {
}
#[inline]
pub unsafe fn write_unchecked(&mut self, ch: T) {
pub fn write(&mut self, ch: T) {
self.data[self.wr] = ch;
self.wr = (self.wr + 1) % N;
}
@ -77,11 +77,10 @@ impl<T: Copy, const N: usize> AsyncRing<T, N> {
}
pub fn try_write(&self, item: T) -> Result<(), Error> {
let mut lock = self.inner.lock();
unsafe {
lock.write_unchecked(item);
{
let mut lock = self.inner.lock();
lock.write(item);
}
drop(lock);
self.read_waker.wake_one();
Ok(())
@ -102,7 +101,7 @@ impl<T: Copy, const N: usize> AsyncRing<T, N> {
let mut inner = self.inner.lock();
if inner.is_readable() {
self.read_waker.remove(cx.waker());
Poll::Ready(unsafe { inner.read_unchecked() })
Poll::Ready(inner.read_single())
} else {
Poll::Pending
}