feature: Stdin/Stdout/Stderr structs
This commit is contained in:
parent
1f204e1d4c
commit
6bb4f38edc
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -97,6 +97,15 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
dependencies = [
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsys"
|
name = "libsys"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -108,6 +117,7 @@ dependencies = [
|
|||||||
name = "libusr"
|
name = "libusr"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
"libsys",
|
"libsys",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -195,6 +205,12 @@ version = "0.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -7,3 +7,4 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libsys = { path = "../libsys", features = ["user"] }
|
libsys = { path = "../libsys", features = ["user"] }
|
||||||
|
lazy_static = { version = "^1.4.0", features = ["spin_no_std"] }
|
||||||
|
@ -1,12 +1,26 @@
|
|||||||
|
use crate::io::{AsRawFd, Error};
|
||||||
|
use crate::os;
|
||||||
|
use crate::trace;
|
||||||
use libsys::stat::FileDescriptor;
|
use libsys::stat::FileDescriptor;
|
||||||
use crate::io;
|
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
fd: FileDescriptor
|
fd: FileDescriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl File {
|
impl File {
|
||||||
pub fn open(path: &str) -> Result<File, io::Error> {
|
pub fn open(path: &str) -> Result<File, Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRawFd for File {
|
||||||
|
fn as_raw_fd(&self) -> FileDescriptor {
|
||||||
|
self.fd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for File {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
use core::fmt;
|
|
||||||
use libsys::{
|
|
||||||
calls::{sys_fstatat, sys_write},
|
|
||||||
stat::{Stat, FileDescriptor},
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO populate this type
|
|
||||||
pub struct Error;
|
|
||||||
|
|
||||||
pub fn stat(pathname: &str) -> Result<Stat, Error> {
|
|
||||||
let mut buf = Stat::default();
|
|
||||||
// TODO error handling
|
|
||||||
let res = unsafe { sys_fstatat(None, pathname, &mut buf, 0).unwrap() };
|
|
||||||
Ok(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// print!/println! group
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! print {
|
|
||||||
($($args:tt)+) => ($crate::io::_print($crate::sys::FileDescriptor::STDOUT, format_args!($($args)+)))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! println {
|
|
||||||
($($args:tt)+) => (print!("{}\n", format_args!($($args)+)))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! eprint {
|
|
||||||
($($args:tt)+) => ($crate::io::_print($crate::sys::FileDescriptor::STDERR, format_args!($($args)+)))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! eprintln {
|
|
||||||
($($args:tt)+) => (eprint!("{}\n", format_args!($($args)+)))
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BufferWriter<'a> {
|
|
||||||
buf: &'a mut [u8],
|
|
||||||
pos: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Write for BufferWriter<'_> {
|
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
||||||
for byte in s.bytes() {
|
|
||||||
self.buf[self.pos] = byte;
|
|
||||||
self.pos += 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _print(fd: FileDescriptor, args: fmt::Arguments) {
|
|
||||||
use core::fmt::Write;
|
|
||||||
static mut BUFFER: [u8; 4096] = [0; 4096];
|
|
||||||
let mut writer = BufferWriter {
|
|
||||||
buf: unsafe { &mut BUFFER },
|
|
||||||
pos: 0,
|
|
||||||
};
|
|
||||||
writer.write_fmt(args).ok();
|
|
||||||
unsafe {
|
|
||||||
sys_write(fd, &BUFFER[..writer.pos]);
|
|
||||||
}
|
|
||||||
}
|
|
35
libusr/src/io/error.rs
Normal file
35
libusr/src/io/error.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use libsys::error::Errno;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Error {
|
||||||
|
repr: Repr,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
|
pub enum ErrorKind {
|
||||||
|
NotFound,
|
||||||
|
PermissionDenied,
|
||||||
|
InvalidData,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Repr {
|
||||||
|
Os(Errno),
|
||||||
|
Simple(ErrorKind),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub const fn new(kind: ErrorKind) -> Self {
|
||||||
|
Self {
|
||||||
|
repr: Repr::Simple(kind),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Errno> for Error {
|
||||||
|
fn from(e: Errno) -> Self {
|
||||||
|
Self {
|
||||||
|
repr: Repr::Os(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
libusr/src/io/mod.rs
Normal file
32
libusr/src/io/mod.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use libsys::{
|
||||||
|
calls::sys_fstatat,
|
||||||
|
stat::{FileDescriptor, Stat},
|
||||||
|
};
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
mod error;
|
||||||
|
pub use error::{Error, ErrorKind};
|
||||||
|
mod writer;
|
||||||
|
pub use writer::{_print};
|
||||||
|
mod stdio;
|
||||||
|
pub use stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
|
||||||
|
|
||||||
|
pub trait Read {
|
||||||
|
fn read(&mut self, bytes: &mut [u8]) -> Result<usize, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Write {
|
||||||
|
fn write(&mut self, bytes: &[u8]) -> Result<usize, Error>;
|
||||||
|
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AsRawFd {
|
||||||
|
fn as_raw_fd(&self) -> FileDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stat(pathname: &str) -> Result<Stat, Error> {
|
||||||
|
let mut buf = Stat::default();
|
||||||
|
// TODO error handling
|
||||||
|
let res = sys_fstatat(None, pathname, &mut buf, 0).unwrap();
|
||||||
|
Ok(buf)
|
||||||
|
}
|
130
libusr/src/io/stdio.rs
Normal file
130
libusr/src/io/stdio.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
use libsys::{
|
||||||
|
stat::FileDescriptor,
|
||||||
|
calls::{sys_read, sys_write}
|
||||||
|
};
|
||||||
|
use crate::io::{Read, Write, Error};
|
||||||
|
use crate::sync::{Mutex, MutexGuard};
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
struct InputInner {
|
||||||
|
fd: FileDescriptor
|
||||||
|
}
|
||||||
|
struct OutputInner {
|
||||||
|
fd: FileDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StdinLock<'a> {
|
||||||
|
lock: MutexGuard<'a, InputInner>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StdoutLock<'a> {
|
||||||
|
lock: MutexGuard<'a, OutputInner>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StderrLock<'a> {
|
||||||
|
lock: MutexGuard<'a, OutputInner>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stdin {
|
||||||
|
inner: &'static Mutex<InputInner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stdout {
|
||||||
|
inner: &'static Mutex<OutputInner>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stderr {
|
||||||
|
inner: &'static Mutex<OutputInner>
|
||||||
|
}
|
||||||
|
|
||||||
|
// STDIN
|
||||||
|
|
||||||
|
impl Read for InputInner {
|
||||||
|
fn read(&mut self, bytes: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
sys_read(self.fd, bytes).map_err(Error::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for Stdin {
|
||||||
|
fn read(&mut self, bytes: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
self.inner.lock().read(bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STDOUT/STDERR
|
||||||
|
|
||||||
|
impl fmt::Write for OutputInner {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
self.write(s.as_bytes()).map(|_| ()).map_err(|_| todo!())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for OutputInner {
|
||||||
|
fn write(&mut self, bytes: &[u8]) -> Result<usize, Error> {
|
||||||
|
sys_write(self.fd, bytes).map_err(Error::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), Error> {
|
||||||
|
fmt::Write::write_fmt(self, args).map_err(|_| todo!())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for Stdout {
|
||||||
|
fn write(&mut self, bytes: &[u8]) -> Result<usize, Error> {
|
||||||
|
self.inner.lock().write(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), Error> {
|
||||||
|
self.inner.lock().write_fmt(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for Stderr {
|
||||||
|
fn write(&mut self, bytes: &[u8]) -> Result<usize, Error> {
|
||||||
|
self.inner.lock().write(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), Error> {
|
||||||
|
self.inner.lock().write_fmt(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stdout {
|
||||||
|
pub fn lock(&self) -> StdoutLock {
|
||||||
|
StdoutLock {
|
||||||
|
lock: self.inner.lock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stderr {
|
||||||
|
pub fn lock(&self) -> StderrLock {
|
||||||
|
StderrLock {
|
||||||
|
lock: self.inner.lock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref STDIN: Mutex<InputInner> = Mutex::new(InputInner {
|
||||||
|
fd: FileDescriptor::STDIN
|
||||||
|
});
|
||||||
|
static ref STDOUT: Mutex<OutputInner> = Mutex::new(OutputInner {
|
||||||
|
fd: FileDescriptor::STDOUT
|
||||||
|
});
|
||||||
|
static ref STDERR: Mutex<OutputInner> = Mutex::new(OutputInner {
|
||||||
|
fd: FileDescriptor::STDOUT
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stdin() -> Stdin {
|
||||||
|
Stdin { inner: &STDIN }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stdout() -> Stdout {
|
||||||
|
Stdout { inner: &STDOUT }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stderr() -> Stderr {
|
||||||
|
Stderr { inner: &STDERR }
|
||||||
|
}
|
26
libusr/src/io/writer.rs
Normal file
26
libusr/src/io/writer.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use crate::io::{self, Write};
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! print {
|
||||||
|
($($args:tt)+) => ($crate::io::_print($crate::io::stdout, format_args!($($args)+)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! println {
|
||||||
|
($($args:tt)+) => (print!("{}\n", format_args!($($args)+)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! eprint {
|
||||||
|
($($args:tt)+) => ($crate::io::_print($crate::io::stderr, format_args!($($args)+)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! eprintln {
|
||||||
|
($($args:tt)+) => (eprint!("{}\n", format_args!($($args)+)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _print<T: Write>(out: fn() -> T, args: fmt::Arguments) {
|
||||||
|
out().write_fmt(args).expect("stdout/stderr write failed");
|
||||||
|
}
|
@ -4,23 +4,19 @@
|
|||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use libsys::proc::ExitCode;
|
use libsys::proc::ExitCode;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
|
||||||
|
pub mod file;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
pub mod file;
|
pub mod sys;
|
||||||
|
pub mod sync;
|
||||||
pub mod sys {
|
|
||||||
pub use libsys::signal::{Signal, SignalDestination};
|
|
||||||
pub use libsys::termios;
|
|
||||||
pub use libsys::calls::*;
|
|
||||||
pub use libsys::stat::{self, FileDescriptor};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
extern "C" fn _signal_handler(arg: sys::Signal) -> ! {
|
extern "C" fn _signal_handler(arg: sys::Signal) -> ! {
|
||||||
trace!("Entered signal handler: arg={:?}", arg);
|
trace!("Entered signal handler: arg={:?}", arg);
|
||||||
unsafe {
|
sys::sys_ex_sigreturn();
|
||||||
sys::sys_ex_sigreturn();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut SIGNAL_STACK: [u8; 4096] = [0; 4096];
|
static mut SIGNAL_STACK: [u8; 4096] = [0; 4096];
|
||||||
@ -31,17 +27,22 @@ extern "C" fn _start(_arg: usize) -> ! {
|
|||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn main() -> i32;
|
fn main() -> i32;
|
||||||
}
|
}
|
||||||
unsafe {
|
|
||||||
SIGNAL_STACK[0] = 1;
|
|
||||||
sys::sys_ex_signal(_signal_handler as usize, SIGNAL_STACK.as_ptr() as usize + 4096);
|
|
||||||
|
|
||||||
sys::sys_exit(ExitCode::from(main()));
|
unsafe {
|
||||||
|
sys::sys_ex_signal(
|
||||||
|
_signal_handler as usize,
|
||||||
|
SIGNAL_STACK.as_ptr() as usize + 4096,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let res = unsafe { main() };
|
||||||
|
sys::sys_exit(ExitCode::from(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic_handler(pi: &PanicInfo) -> ! {
|
fn panic_handler(pi: &PanicInfo) -> ! {
|
||||||
// TODO formatted messages
|
// TODO print to stdout/stderr (if available)
|
||||||
trace!("Panic ocurred: {}", pi);
|
trace!("Panic ocurred: {}", pi);
|
||||||
sys::sys_exit(ExitCode::from(-1));
|
sys::sys_exit(ExitCode::from(-1));
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,6 @@ use core::fmt;
|
|||||||
use core::mem::{size_of, MaybeUninit};
|
use core::mem::{size_of, MaybeUninit};
|
||||||
use libsys::{ioctl::IoctlCmd, stat::FileDescriptor, termios::Termios};
|
use libsys::{ioctl::IoctlCmd, stat::FileDescriptor, termios::Termios};
|
||||||
|
|
||||||
pub fn get_tty_attrs(fd: FileDescriptor) -> Result<Termios, &'static str> {
|
|
||||||
let mut termios = MaybeUninit::<Termios>::uninit();
|
|
||||||
let res = sys::sys_ioctl(
|
|
||||||
fd,
|
|
||||||
IoctlCmd::TtyGetAttributes,
|
|
||||||
termios.as_mut_ptr() as usize,
|
|
||||||
size_of::<Termios>(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
if res != size_of::<Termios>() {
|
|
||||||
return Err("Failed");
|
|
||||||
}
|
|
||||||
Ok(unsafe { termios.assume_init() })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_tty_attrs(fd: FileDescriptor, attrs: &Termios) -> Result<(), &'static str> {
|
|
||||||
let res = sys::sys_ioctl(
|
|
||||||
fd,
|
|
||||||
IoctlCmd::TtySetAttributes,
|
|
||||||
attrs as *const _ as usize,
|
|
||||||
size_of::<Termios>(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
if res != size_of::<Termios>() {
|
|
||||||
return Err("Failed");
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! trace {
|
macro_rules! trace {
|
||||||
($($args:tt)+) => ($crate::os::_trace(format_args!($($args)+)))
|
($($args:tt)+) => ($crate::os::_trace(format_args!($($args)+)))
|
||||||
@ -60,7 +31,5 @@ pub fn _trace(args: fmt::Arguments) {
|
|||||||
pos: 0,
|
pos: 0,
|
||||||
};
|
};
|
||||||
writer.write_fmt(args).ok();
|
writer.write_fmt(args).ok();
|
||||||
unsafe {
|
sys::sys_ex_debug_trace(unsafe { &BUFFER[..writer.pos] }).ok();
|
||||||
sys::sys_ex_debug_trace(&BUFFER[..writer.pos]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
54
libusr/src/sync.rs
Normal file
54
libusr/src/sync.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use core::cell::UnsafeCell;
|
||||||
|
use core::ops::{Deref, DerefMut};
|
||||||
|
use crate::sys::RawMutex;
|
||||||
|
|
||||||
|
pub struct Mutex<T> {
|
||||||
|
inner: RawMutex,
|
||||||
|
data: UnsafeCell<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MutexGuard<'a, T> {
|
||||||
|
data: &'a mut T,
|
||||||
|
lock: &'a RawMutex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Mutex<T> {
|
||||||
|
pub fn new(t: T) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: RawMutex::new(),
|
||||||
|
data: UnsafeCell::new(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lock(&self) -> MutexGuard<'_, T> {
|
||||||
|
unsafe {
|
||||||
|
self.inner.lock();
|
||||||
|
MutexGuard {
|
||||||
|
data: (&mut *self.data.get()),
|
||||||
|
lock: &self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Drop for MutexGuard<'a, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { self.lock.release(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Deref for MutexGuard<'a, T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
self.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> DerefMut for MutexGuard<'a, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
self.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T> Sync for Mutex<T> {}
|
39
libusr/src/sys/mod.rs
Normal file
39
libusr/src/sys/mod.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
pub use libsys::signal::{Signal, SignalDestination};
|
||||||
|
pub use libsys::termios;
|
||||||
|
pub use libsys::calls::*;
|
||||||
|
pub use libsys::stat::{self, FileDescriptor};
|
||||||
|
|
||||||
|
use core::sync::atomic::{Ordering, AtomicBool};
|
||||||
|
|
||||||
|
// TODO replace with a proper mutex impl
|
||||||
|
pub(crate) struct RawMutex {
|
||||||
|
inner: AtomicBool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawMutex {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self { inner: AtomicBool::new(false) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn try_lock(&self) -> bool {
|
||||||
|
self.inner.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn is_locked(&self) -> bool {
|
||||||
|
self.inner.load(Ordering::Acquire)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lock(&self) {
|
||||||
|
while !self.try_lock() {
|
||||||
|
asm!("nop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn release(&self) {
|
||||||
|
self.inner.store(false, Ordering::Release);
|
||||||
|
}
|
||||||
|
}
|
@ -4,54 +4,22 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate libusr;
|
extern crate libusr;
|
||||||
|
|
||||||
use libusr::sys::stat::{FdSet, FileDescriptor};
|
use libusr::io::{self, Read};
|
||||||
use libusr::sys::{Signal, SignalDestination};
|
|
||||||
|
|
||||||
fn readline(fd: FileDescriptor, buf: &mut [u8]) -> Result<&str, ()> {
|
|
||||||
// select() just for test
|
|
||||||
loop {
|
|
||||||
let mut rfds = FdSet::empty();
|
|
||||||
rfds.set(fd);
|
|
||||||
let res = unsafe {
|
|
||||||
libusr::sys::sys_select(Some(&mut rfds), None, 1_000_000_000).unwrap()
|
|
||||||
};
|
|
||||||
if res == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if !rfds.is_set(fd) {
|
|
||||||
panic!();
|
|
||||||
}
|
|
||||||
|
|
||||||
let count = unsafe { libusr::sys::sys_read(fd, buf).unwrap() };
|
|
||||||
return core::str::from_utf8(&buf[..count as usize]).map_err(|_| ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn main() -> i32 {
|
fn main() -> i32 {
|
||||||
let mut buf = [0; 512];
|
let mut buf = [0; 512];
|
||||||
|
let mut stdin = io::stdin();
|
||||||
|
|
||||||
|
eprintln!("stderr test");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
print!("> ");
|
let count = stdin.read(&mut buf).unwrap();
|
||||||
let line = readline(FileDescriptor::STDIN, &mut buf).unwrap();
|
if count == 0 {
|
||||||
if line.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let line = line.trim_end_matches('\n');
|
|
||||||
|
|
||||||
println!(":: {:?}", line);
|
|
||||||
|
|
||||||
if line == "test" {
|
|
||||||
unsafe {
|
|
||||||
libusr::sys::sys_ex_kill(SignalDestination::This, Signal::Interrupt);
|
|
||||||
}
|
|
||||||
trace!("Returned from signal");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if line == "quit" || line == "exit" {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
let line = core::str::from_utf8(&buf[..count]).unwrap();
|
||||||
|
println!("{:?}", line);
|
||||||
}
|
}
|
||||||
|
|
||||||
0
|
0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user