Merge branch 'readiness_based' into 'main'

Implement cancellation, reduce boilerplate, and update redox-scheme

See merge request redox-os/base!8
This commit is contained in:
Jeremy Soller
2025-04-07 18:42:28 +00:00
4 changed files with 127 additions and 160 deletions
Generated
+34 -62
View File
@@ -91,11 +91,13 @@ source = "git+https://gitlab.redox-os.org/redox-os/arg-parser.git#1c434b55f3e1a0
name = "audiod"
version = "0.1.0"
dependencies = [
"anyhow",
"ioslice",
"libc",
"libredox 0.0.3",
"libredox",
"redox-daemon",
"redox-scheme 0.1.0",
"redox_syscall 0.4.1",
"redox-scheme 0.5.0 (git+https://gitlab.redox-os.org/redox-os/redox-scheme.git)",
"redox_syscall",
]
[[package]]
@@ -405,7 +407,7 @@ dependencies = [
name = "init"
version = "0.1.0"
dependencies = [
"libredox 0.1.3",
"libredox",
]
[[package]]
@@ -422,11 +424,11 @@ dependencies = [
name = "ipcd"
version = "0.1.0"
dependencies = [
"libredox 0.1.3",
"libredox",
"redox-daemon",
"redox-scheme 0.2.4",
"redox_event",
"redox_syscall 0.5.11",
"redox_syscall",
]
[[package]]
@@ -451,17 +453,6 @@ version = "0.2.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
[[package]]
name = "libredox"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "962b650e6b934f95cec493e1464e0f5cba98dd9ba9ef2b1c42cdfdb7864cab5a"
dependencies = [
"bitflags 2.9.0",
"libc",
"redox_syscall 0.4.1",
]
[[package]]
name = "libredox"
version = "0.1.3"
@@ -471,7 +462,7 @@ dependencies = [
"bitflags 2.9.0",
"ioslice",
"libc",
"redox_syscall 0.5.11",
"redox_syscall",
]
[[package]]
@@ -484,10 +475,10 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
name = "logd"
version = "0.1.0"
dependencies = [
"libredox 0.1.3",
"libredox",
"redox-daemon",
"redox-scheme 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.5.11",
"redox_syscall",
]
[[package]]
@@ -527,7 +518,7 @@ dependencies = [
"arg_parser",
"clap",
"libc",
"libredox 0.1.3",
"libredox",
"net2",
"ntpclient",
"pbr",
@@ -636,11 +627,11 @@ dependencies = [
name = "ptyd"
version = "0.1.0"
dependencies = [
"libredox 0.1.3",
"libredox",
"redox-daemon",
"redox-scheme 0.3.0",
"redox_event",
"redox_syscall 0.5.11",
"redox_syscall",
"redox_termios",
]
@@ -664,10 +655,10 @@ name = "ramfs"
version = "0.1.0"
dependencies = [
"indexmap",
"libredox 0.1.3",
"libredox",
"redox-daemon",
"redox-scheme 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.5.11",
"redox_syscall",
"slab",
]
@@ -691,13 +682,13 @@ checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
name = "randd"
version = "0.1.0"
dependencies = [
"libredox 0.1.3",
"libredox",
"rand_chacha",
"rand_core",
"raw-cpuid",
"redox-daemon",
"redox-scheme 0.2.4",
"redox_syscall 0.5.11",
"redox_syscall",
"sha2",
]
@@ -717,7 +708,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbdeffdb03cf2961b211a2023e683d71f2c225ea93404da5dc34b0dc94f0341"
dependencies = [
"libc",
"libredox 0.1.3",
"libredox",
]
[[package]]
@@ -732,24 +723,14 @@ dependencies = [
"termion",
]
[[package]]
name = "redox-scheme"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "425289b64797f9b7d98971e61d4838c67041c2ca13511e5a62539936873ae1a8"
dependencies = [
"libredox 0.0.3",
"redox_syscall 0.4.1",
]
[[package]]
name = "redox-scheme"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6143c4d307e1c99ac14f60b5b07b2dccaf9d17137f7cee4e4e29977dd8014a1b"
dependencies = [
"libredox 0.1.3",
"redox_syscall 0.5.11",
"libredox",
"redox_syscall",
]
[[package]]
@@ -758,8 +739,8 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e7f06e1b19d8143043e959fbd7b76a37e759e3e9c6bbfc9c91c496b0b44d20"
dependencies = [
"libredox 0.1.3",
"redox_syscall 0.5.11",
"libredox",
"redox_syscall",
]
[[package]]
@@ -768,17 +749,17 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a96b9cfb034251dfb0aaa66a67059a7f0ea344039904d1d70cd36266af9c8a2f"
dependencies = [
"libredox 0.1.3",
"redox_syscall 0.5.11",
"libredox",
"redox_syscall",
]
[[package]]
name = "redox-scheme"
version = "0.5.0"
source = "git+https://gitlab.redox-os.org/redox-os/redox-scheme.git#ce4eead6798c2d1d1d5a6d57b45481a4909ec62e"
source = "git+https://gitlab.redox-os.org/redox-os/redox-scheme.git#ef9f1512f54758be20960717dfad193d6cd70dc7"
dependencies = [
"libredox 0.1.3",
"redox_syscall 0.5.11",
"libredox",
"redox_syscall",
]
[[package]]
@@ -788,7 +769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69609faa5d5992247a4ef379917bb3e39be281405d6a0ccd4f942429400b956f"
dependencies = [
"bitflags 2.9.0",
"libredox 0.1.3",
"libredox",
]
[[package]]
@@ -798,26 +779,17 @@ dependencies = [
"anyhow",
"dns-parser",
"ioslice",
"libredox 0.1.3",
"libredox",
"log",
"netutils",
"redox-daemon",
"redox-log",
"redox-scheme 0.5.0 (git+https://gitlab.redox-os.org/redox-os/redox-scheme.git)",
"redox_event",
"redox_syscall 0.5.11",
"redox_syscall",
"smoltcp",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.5.11"
@@ -946,7 +918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3669a69de26799d6321a5aa713f55f7e2cd37bd47be044b50f2acafc42c122bb"
dependencies = [
"libc",
"libredox 0.1.3",
"libredox",
"numtoa",
"redox_termios",
]
@@ -1283,8 +1255,8 @@ dependencies = [
name = "zerod"
version = "0.1.0"
dependencies = [
"libredox 0.1.3",
"libredox",
"redox-daemon",
"redox-scheme 0.2.4",
"redox_syscall 0.5.11",
"redox_syscall",
]
+6 -4
View File
@@ -2,11 +2,13 @@
name = "audiod"
version = "0.1.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
edition = "2018"
edition = "2021"
[dependencies]
redox-daemon = "0.1.2"
redox_syscall = "0.4.1"
redox_syscall = { version = "0.5", features = ["std"] }
libc = "0.2"
libredox = "0.0.3"
redox-scheme = "0.1.0"
libredox = { version = "0.1", features = ["mkns"] }
redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" }
anyhow = "1.0.97"
ioslice = "0.6.0"
+30 -41
View File
@@ -1,13 +1,15 @@
extern crate syscall;
use std::mem::MaybeUninit;
use std::ptr::addr_of_mut;
use std::sync::{Arc, Mutex};
use std::{mem, process, slice, thread};
use anyhow::Context;
use ioslice::IoSlice;
use libredox::flag;
use libredox::{error::Result, Fd};
use redox_scheme::{SignalBehavior, Socket};
use redox_scheme::wrappers::ReadinessBased;
use redox_scheme::Socket;
use redox_daemon::Daemon;
@@ -18,9 +20,6 @@ mod scheme;
extern "C" fn sigusr_handler(_sig: usize) {}
fn thread(scheme: Arc<Mutex<AudioScheme>>, pid: usize, hw_file: Fd) -> Result<()> {
// Enter null namespace
libredox::call::setrens(0, 0)?;
loop {
let buffer = scheme.lock().unwrap().buffer();
let buffer_u8 = unsafe {
@@ -34,7 +33,7 @@ fn thread(scheme: Arc<Mutex<AudioScheme>>, pid: usize, hw_file: Fd) -> Result<()
}
}
fn daemon(daemon: Daemon) -> Result<()> {
fn daemon(daemon: Daemon) -> anyhow::Result<()> {
// Handle signals from the hw thread
let new_sigaction = unsafe {
@@ -50,55 +49,45 @@ fn daemon(daemon: Daemon) -> Result<()> {
let hw_file = Fd::open("/scheme/audiohw", flag::O_WRONLY | flag::O_CLOEXEC, 0)?;
let socket = Socket::create("audio")?;
let socket = Socket::create("audio").context("failed to create scheme")?;
let scheme = Arc::new(Mutex::new(AudioScheme::new()));
// Enter a constrained namespace
let ns = libredox::call::mkns(&[
//IoSlice::new(b"memory"), TODO: already included, uncommenting gives EEXIST
IoSlice::new(b"rand"), // for HashMap
IoSlice::new(b"thisproc"), // for thread::spawn
]).context("failed to make namespace")?;
libredox::call::setrens(ns, ns).context("failed to set namespace")?;
// Spawn a thread to mix and send audio data
let scheme_thread = scheme.clone();
let _thread = thread::spawn(move || thread(scheme_thread, pid, hw_file));
// Enter the null namespace - done after thread is created so
// memory: can be accessed for stack allocation
libredox::call::setrens(0, 0)?;
let _thread = thread::spawn(move || {
libredox::call::setrens(ns, ns).unwrap();
thread(scheme_thread, pid, hw_file)
});
// The scheme is now ready to accept requests, notify the original process
daemon.ready().unwrap();
let mut pending = Vec::new();
let mut readiness = ReadinessBased::new(&socket, 16);
loop {
match socket.next_request(SignalBehavior::Interrupt) {
Ok(Some(request)) => {
match request.handle_scheme_block_mut(&mut *scheme.lock().unwrap()) {
Ok(response) => {
socket.write_responses(&[response], SignalBehavior::Restart)?;
}
Err(request) => pending.push(request),
}
}
Ok(None) => {}
Err(err) => match err.errno {
libredox::errno::EINTR => {}
_ => return Err(err),
},
}
let mut i = 0;
while i < pending.len() {
let request = pending[i];
match request.handle_scheme_block_mut(&mut *scheme.lock().unwrap()) {
Ok(response) => {
pending.remove(i);
socket.write_responses(&[response], SignalBehavior::Restart)?;
}
Err(_) => i += 1,
}
if !readiness.read_requests()? {
break;
}
readiness.process_requests(|| scheme.lock().unwrap());
readiness.poll_all_requests(|| scheme.lock().unwrap())?;
if !readiness.write_responses()? {
break;
};
}
Ok(())
}
fn main() {
fn main() -> anyhow::Result<()> {
let Err(err) = Daemon::new(|x| match daemon(x) {
Ok(()) => {
process::exit(0);
+57 -53
View File
@@ -1,9 +1,10 @@
use redox_scheme::{CallerCtx, OpenResult};
use std::collections::{BTreeMap, VecDeque};
use std::str;
use syscall::error::{EBADF, EINVAL, ENOENT, EWOULDBLOCK, Error, Result};
use syscall::flag::O_NONBLOCK;
use syscall::error::{Error, Result, EBADF, EINVAL, ENOENT, EWOULDBLOCK};
use redox_scheme::SchemeBlockMut;
use redox_scheme::scheme::SchemeSync;
use syscall::schemev2::NewFdFlags;
// The strict buffer size of the audiohw: driver
const HW_BUFFER_SIZE: usize = 512;
@@ -11,14 +12,10 @@ const HW_BUFFER_SIZE: usize = 512;
const HANDLE_BUFFER_SIZE: usize = 4096;
enum Handle {
Audio {
flags: usize,
buffer: VecDeque<(i16, i16)>,
},
//TODO: move volume to audiohw:?
Volume {
offset: usize,
}
Audio { buffer: VecDeque<(i16, i16)> },
// TODO: move volume to audiohw:?
// TODO: Use SYS_CALL to handle this better?
Volume,
}
pub struct AudioScheme {
@@ -44,7 +41,7 @@ impl AudioScheme {
let volume_factor = ((self.volume as f32) / 100.0).powi(3);
for (_id, handle) in self.handles.iter_mut() {
match handle {
Handle::Audio { flags: _, ref mut buffer } => {
Handle::Audio { ref mut buffer } => {
let mut i = 0;
while i < mix_buffer.len() {
if let Some(sample) = buffer.pop_front() {
@@ -57,7 +54,7 @@ impl AudioScheme {
}
i += 1;
}
},
}
_ => (),
}
}
@@ -66,16 +63,16 @@ impl AudioScheme {
}
}
impl SchemeBlockMut for AudioScheme {
fn open(&mut self, path: &str, flags: usize, _uid: u32, _gid: u32) -> Result<Option<usize>> {
let handle = match path.trim_matches('/') {
"" => Handle::Audio {
flags,
buffer: VecDeque::new()
},
"volume" => Handle::Volume {
offset: 0,
},
impl SchemeSync for AudioScheme {
fn open(&mut self, path: &str, _flags: usize, _ctx: &CallerCtx) -> Result<OpenResult> {
let (handle, flags) = match path.trim_matches('/') {
"" => (
Handle::Audio {
buffer: VecDeque::new(),
},
NewFdFlags::empty(),
),
"volume" => (Handle::Volume, NewFdFlags::POSITIONED),
_ => return Err(Error::new(ENOENT)),
};
@@ -83,60 +80,68 @@ impl SchemeBlockMut for AudioScheme {
self.next_id += 1;
self.handles.insert(id, handle);
Ok(Some(id))
Ok(OpenResult::ThisScheme { number: id, flags })
}
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
fn read(
&mut self,
id: usize,
buf: &mut [u8],
off: u64,
_flags: u32,
_ctx: &CallerCtx,
) -> Result<usize> {
//TODO: check flags for readable
match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::Audio { flags: _, buffer: _ } => {
Handle::Audio { buffer: _ } => {
//TODO: audio input?
Err(Error::new(EBADF))
},
Handle::Volume { ref mut offset } => {
}
Handle::Volume => {
let Ok(off) = usize::try_from(off) else {
return Ok(0);
};
//TODO: should we allocate every time?
let string = format!("{}", self.volume);
let bytes = string.as_bytes();
let bytes = format!("{}", self.volume).into_bytes();
let src = bytes.get(off..).unwrap_or(&[]);
let len = src.len().min(buf.len());
buf[..len].copy_from_slice(&src[..len]);
let mut i = 0;
while i < buf.len() && *offset + i < bytes.len() {
buf[i] = bytes[*offset + i];
i += 1;
}
*offset += i;
Ok(Some(i))
Ok(len)
}
}
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
fn write(
&mut self,
id: usize,
buf: &[u8],
offset: u64,
_flags: u32,
_ctx: &CallerCtx,
) -> Result<usize> {
//TODO: check flags for writable
match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::Audio { ref flags, ref mut buffer } => {
Handle::Audio { ref mut buffer } => {
if buffer.len() >= HANDLE_BUFFER_SIZE {
if flags & O_NONBLOCK > 0 {
Err(Error::new(EWOULDBLOCK))
} else {
Ok(None)
}
Err(Error::new(EWOULDBLOCK))
} else {
let mut i = 0;
while i + 4 <= buf.len() {
buffer.push_back((
(buf[i] as i16) | ((buf[i + 1] as i16) << 8),
(buf[i + 2] as i16) | ((buf[i + 3] as i16) << 8)
(buf[i + 2] as i16) | ((buf[i + 3] as i16) << 8),
));
i += 4;
}
Ok(Some(i))
Ok(i)
}
},
Handle::Volume { ref mut offset } => {
}
Handle::Volume => {
//TODO: support other offsets?
if *offset == 0 {
if offset == 0 {
let value = str::from_utf8(buf)
.map_err(|_| Error::new(EINVAL))?
.trim()
@@ -144,14 +149,13 @@ impl SchemeBlockMut for AudioScheme {
.map_err(|_| Error::new(EINVAL))?;
if value >= 0 && value <= 100 {
self.volume = value;
*offset += buf.len();
Ok(Some(buf.len()))
Ok(buf.len())
} else {
Err(Error::new(EINVAL))
}
} else {
// EOF
Ok(Some(0))
Ok(0)
}
}
}