scheme-utils: Remove the need for RefCell wrappers around schemes for ReadinessBased

This commit is contained in:
bjorn3
2026-04-15 20:21:39 +02:00
parent ca281c9395
commit 4ef2c7ad6f
7 changed files with 76 additions and 123 deletions
+2 -2
View File
@@ -74,8 +74,8 @@ fn daemon(daemon: SchemeDaemon) -> anyhow::Result<()> {
if !readiness.read_requests()? {
break;
}
readiness.process_requests(|| scheme.lock().unwrap());
readiness.poll_all_requests(|| scheme.lock().unwrap())?;
readiness.process_requests(&mut *scheme.lock().unwrap());
readiness.poll_all_requests(&mut *scheme.lock().unwrap())?;
if !readiness.write_responses()? {
break;
};
+6 -8
View File
@@ -7,7 +7,6 @@ use pcid_interface::PciFunctionHandle;
use redox_scheme::scheme::register_sync_scheme;
use redox_scheme::Socket;
use scheme_utils::ReadinessBased;
use std::cell::RefCell;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod device;
@@ -46,9 +45,8 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
let mut irq_file = irq.irq_handle("ac97d");
let socket = Socket::nonblock().expect("ac97d: failed to create socket");
let device = RefCell::new(unsafe {
device::Ac97::new(bar0, bar1).expect("ac97d: failed to allocate device")
});
let mut device =
unsafe { device::Ac97::new(bar0, bar1).expect("ac97d: failed to allocate device") };
let mut readiness_based = ReadinessBased::new(&socket, 16);
user_data! {
@@ -74,7 +72,7 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
)
.unwrap();
register_sync_scheme(&socket, "audiohw", &mut *device.borrow_mut())
register_sync_scheme(&socket, "audiohw", &mut device)
.expect("ac97d: failed to register audiohw scheme to namespace");
daemon.ready();
@@ -90,13 +88,13 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if !device.borrow_mut().irq() {
if !device.irq() {
continue;
}
irq_file.write(&mut irq).unwrap();
readiness_based
.poll_all_requests(|| device.borrow_mut())
.poll_all_requests(&mut device)
.expect("ac97d: failed to poll requests");
if !readiness_based
.write_responses()
@@ -119,7 +117,7 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
readiness_based.process_requests(&mut device);
if !readiness_based
.write_responses()
.expect("ac97d: failed to write to socket")
+6 -7
View File
@@ -1,7 +1,6 @@
use redox_scheme::scheme::register_sync_scheme;
use redox_scheme::Socket;
use scheme_utils::ReadinessBased;
use std::cell::RefCell;
use std::io::{Read, Write};
use std::os::unix::io::AsRawFd;
use std::usize;
@@ -57,12 +56,12 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
let event_queue =
EventQueue::<Source>::new().expect("ihdad: Could not create event queue.");
let socket = Socket::nonblock().expect("ihdad: failed to create socket");
let device = RefCell::new(unsafe {
let mut device = unsafe {
hda::IntelHDA::new(address, vend_prod).expect("ihdad: failed to allocate device")
});
};
let mut readiness_based = ReadinessBased::new(&socket, 16);
register_sync_scheme(&socket, "audiohw", &mut *device.borrow_mut())
register_sync_scheme(&socket, "audiohw", &mut device)
.expect("ihdad: failed to register audiohw scheme to namespace");
daemon.ready();
@@ -94,13 +93,13 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
let mut irq = [0; 8];
irq_file.irq_handle().read(&mut irq).unwrap();
if !device.borrow_mut().irq() {
if !device.irq() {
continue;
}
irq_file.irq_handle().write(&mut irq).unwrap();
readiness_based
.poll_all_requests(|| device.borrow_mut())
.poll_all_requests(&mut device)
.expect("ihdad: failed to poll requests");
if !readiness_based
.write_responses()
@@ -123,7 +122,7 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
readiness_based.process_requests(&mut device);
if !readiness_based
.write_responses()
.expect("ihdad: failed to write to socket")
+6 -8
View File
@@ -2,7 +2,6 @@ use libredox::{flag, Fd};
use redox_scheme::scheme::register_sync_scheme;
use redox_scheme::Socket;
use scheme_utils::ReadinessBased;
use std::cell::RefCell;
use std::{env, usize};
use event::{user_data, EventQueue};
@@ -34,12 +33,11 @@ fn daemon(daemon: daemon::Daemon) -> ! {
common::acquire_port_io_rights().expect("sb16d: failed to acquire port IO rights");
let socket = Socket::nonblock().expect("sb16d: failed to create socket");
let device =
RefCell::new(unsafe { device::Sb16::new(addr).expect("sb16d: failed to allocate device") });
let mut device = unsafe { device::Sb16::new(addr).expect("sb16d: failed to allocate device") };
let mut readiness_based = ReadinessBased::new(&socket, 16);
//TODO: error on multiple IRQs?
let irq_file = match device.borrow().irqs.first() {
let irq_file = match device.irqs.first() {
Some(irq) => Fd::open(&format!("/scheme/irq/{}", irq), flag::O_RDWR, 0)
.expect("sb16d: failed to open IRQ file"),
None => panic!("sb16d: no IRQs found"),
@@ -63,7 +61,7 @@ fn daemon(daemon: daemon::Daemon) -> ! {
)
.unwrap();
register_sync_scheme(&socket, "sb16d", &mut *device.borrow_mut())
register_sync_scheme(&socket, "sb16d", &mut device)
.expect("sb16d: failed to register audiohw scheme to namespace");
daemon.ready();
@@ -81,13 +79,13 @@ fn daemon(daemon: daemon::Daemon) -> ! {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if !device.borrow_mut().irq() {
if !device.irq() {
continue;
}
irq_file.write(&mut irq).unwrap();
readiness_based
.poll_all_requests(|| device.borrow_mut())
.poll_all_requests(&mut device)
.expect("sb16d: failed to poll requests");
if !readiness_based
.write_responses()
@@ -110,7 +108,7 @@ fn daemon(daemon: daemon::Daemon) -> ! {
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
readiness_based.process_requests(&mut device);
if !readiness_based
.write_responses()
.expect("sb16d: failed to write to socket")
+21 -39
View File
@@ -2,7 +2,6 @@ use event::{EventFlags, EventQueue};
use redox_scheme::scheme::register_sync_scheme;
use redox_scheme::Socket;
use scheme_utils::ReadinessBased;
use std::sync::Mutex;
mod chan;
mod shm;
@@ -41,54 +40,37 @@ fn inner(daemon: daemon::Daemon) -> anyhow::Result<()> {
// Prepare chan scheme
let chan_socket =
Socket::nonblock().map_err(|e| anyhow::anyhow!("failed to create chan scheme: {e}"))?;
let chan = Mutex::new(ChanScheme::new(&chan_socket));
let mut chan = ChanScheme::new(&chan_socket);
let mut chan_handler = ReadinessBased::new(&chan_socket, 16);
// Prepare shm scheme
let shm_socket =
Socket::nonblock().map_err(|e| anyhow::anyhow!("failed to create shm socket: {e}"))?;
let shm = Mutex::new(ShmScheme::new());
let mut shm = ShmScheme::new();
let mut shm_handler = ReadinessBased::new(&shm_socket, 16);
// Prepare uds stream scheme
let uds_stream_socket = Socket::nonblock()
.map_err(|e| anyhow::anyhow!("failed to create uds stream scheme: {e}"))?;
let uds_stream = Mutex::new(
UdsStreamScheme::new(&uds_stream_socket)
.map_err(|e| anyhow::anyhow!("failed to create uds stream scheme: {e}"))?,
);
let mut uds_stream = UdsStreamScheme::new(&uds_stream_socket)
.map_err(|e| anyhow::anyhow!("failed to create uds stream scheme: {e}"))?;
let mut uds_stream_handler = ReadinessBased::new(&uds_stream_socket, 16);
// Prepare uds dgram scheme
let uds_dgram_socket = Socket::nonblock()
.map_err(|e| anyhow::anyhow!("failed to create uds dgram scheme: {e}"))?;
let uds_dgram = Mutex::new(
UdsDgramScheme::new(&uds_dgram_socket)
.map_err(|e| anyhow::anyhow!("failed to create uds dgram scheme: {e}"))?,
);
let mut uds_dgram = UdsDgramScheme::new(&uds_dgram_socket)
.map_err(|e| anyhow::anyhow!("failed to create uds dgram scheme: {e}"))?;
let mut uds_dgram_handler = ReadinessBased::new(&uds_dgram_socket, 16);
{
let mut chan_guard = chan.lock().unwrap();
register_sync_scheme(&chan_socket, "chan", &mut *chan_guard)
.map_err(|e| anyhow::anyhow!("failed to register chan scheme: {e}"))?;
}
{
let mut shm_guard = shm.lock().unwrap();
register_sync_scheme(&shm_socket, "shm", &mut *shm_guard)
.map_err(|e| anyhow::anyhow!("failed to register shm scheme: {e}"))?;
}
{
let mut uds_stream_guard = uds_stream.lock().unwrap();
register_sync_scheme(&uds_stream_socket, "uds_stream", &mut *uds_stream_guard)
.map_err(|e| anyhow::anyhow!("failed to register uds stream scheme: {e}"))?;
}
{
let mut uds_dgram_guard = uds_dgram.lock().unwrap();
// Register schemes to namespace
register_sync_scheme(&uds_dgram_socket, "uds_dgram", &mut *uds_dgram_guard)
.map_err(|e| anyhow::anyhow!("failed to register uds dgram scheme: {e}"))?;
}
register_sync_scheme(&chan_socket, "chan", &mut chan)
.map_err(|e| anyhow::anyhow!("failed to register chan scheme: {e}"))?;
register_sync_scheme(&shm_socket, "shm", &mut shm)
.map_err(|e| anyhow::anyhow!("failed to register shm scheme: {e}"))?;
register_sync_scheme(&uds_stream_socket, "uds_stream", &mut uds_stream)
.map_err(|e| anyhow::anyhow!("failed to register uds stream scheme: {e}"))?;
register_sync_scheme(&uds_dgram_socket, "uds_dgram", &mut uds_dgram)
.map_err(|e| anyhow::anyhow!("failed to register uds dgram scheme: {e}"))?;
daemon.ready();
@@ -153,11 +135,11 @@ fn inner(daemon: daemon::Daemon) -> anyhow::Result<()> {
}
// 2. Process requests
chan_handler.process_requests(|| chan.lock().unwrap());
chan_handler.process_requests(&mut chan);
// 3.Poll all blocking requests
chan_handler
.poll_all_requests(|| chan.lock().unwrap())
.poll_all_requests(&mut chan)
.map_err(|e| anyhow::anyhow!("error occured in poll_all_requests: {e}"))?;
// 3. Write responses
@@ -186,7 +168,7 @@ fn inner(daemon: daemon::Daemon) -> anyhow::Result<()> {
}
// 2. Process requests
shm_handler.process_requests(|| shm.lock().unwrap());
shm_handler.process_requests(&mut shm);
// shm is not a blocking scheme
@@ -216,11 +198,11 @@ fn inner(daemon: daemon::Daemon) -> anyhow::Result<()> {
}
// 2. Process requests
uds_stream_handler.process_requests(|| uds_stream.lock().unwrap());
uds_stream_handler.process_requests(&mut uds_stream);
// 3.Poll all blocking requests
uds_stream_handler
.poll_all_requests(|| uds_stream.lock().unwrap())
.poll_all_requests(&mut uds_stream)
.map_err(|e| anyhow::anyhow!("error occured in poll_all_requests: {e}"))?;
// 3. Write responses
@@ -249,11 +231,11 @@ fn inner(daemon: daemon::Daemon) -> anyhow::Result<()> {
}
// 2. Process requests
uds_dgram_handler.process_requests(|| uds_dgram.lock().unwrap());
uds_dgram_handler.process_requests(&mut uds_dgram);
// 3.Poll all blocking requests
uds_dgram_handler
.poll_all_requests(|| uds_dgram.lock().unwrap())
.poll_all_requests(&mut uds_dgram)
.map_err(|e| anyhow::anyhow!("error occured in poll_all_requests: {e}"))?;
// 3. Write responses
+11 -13
View File
@@ -1,5 +1,3 @@
use std::cell::RefCell;
use event::{user_data, EventFlags, EventQueue};
use libredox::{flag, Fd};
@@ -39,8 +37,8 @@ fn daemon(daemon: daemon::Daemon) -> ! {
let socket = redox_scheme::Socket::nonblock().expect("pty: failed to create pty scheme");
let mut handler = ReadinessBased::new(&socket, 16);
let scheme = RefCell::new(PtyScheme::new());
register_sync_scheme(&socket, "pty", &mut *scheme.borrow_mut())
let mut scheme = PtyScheme::new();
register_sync_scheme(&socket, "pty", &mut scheme)
.expect("ptyd: failed to register scheme to namespace");
daemon.ready();
@@ -58,15 +56,15 @@ fn daemon(daemon: daemon::Daemon) -> ! {
let mut timeout_count = 0u64;
scan_requests(&mut handler, &scheme).expect("pty: could not scan requests");
issue_events(&socket, &mut scheme.borrow_mut());
scan_requests(&mut handler, &mut scheme).expect("pty: could not scan requests");
issue_events(&socket, &mut scheme);
for event_res in event_queue {
let event = event_res.expect("pty: failed to read from event queue");
match event.user_data {
EventSource::Socket => {
if scan_requests(&mut handler, &scheme).is_err() {
if scan_requests(&mut handler, &mut scheme).is_err() {
break;
}
}
@@ -75,19 +73,19 @@ fn daemon(daemon: daemon::Daemon) -> ! {
timeout_count = timeout_count.wrapping_add(1);
for (_id, handle) in scheme.borrow_mut().handles.iter_mut() {
for (_id, handle) in scheme.handles.iter_mut() {
if let Handle::Resource(res) = handle {
res.timeout(timeout_count);
}
}
handler
.poll_all_requests(|| scheme.borrow_mut())
.poll_all_requests(&mut scheme)
.expect("ihdad: failed to poll requests");
}
}
issue_events(&socket, &mut scheme.borrow_mut());
issue_events(&socket, &mut scheme);
}
std::process::exit(0);
@@ -95,7 +93,7 @@ fn daemon(daemon: daemon::Daemon) -> ! {
fn scan_requests(
handler: &mut ReadinessBased<'_>,
scheme: &RefCell<PtyScheme>,
scheme: &mut PtyScheme,
) -> libredox::error::Result<()> {
// 1. Read requests
match handler
@@ -109,11 +107,11 @@ fn scan_requests(
}
// 2. Process requests
handler.process_requests(|| scheme.borrow_mut());
handler.process_requests(scheme);
// 3. Poll all blocking requests
handler
.poll_all_requests(|| scheme.borrow_mut())
.poll_all_requests(scheme)
.expect("pty: error occured in poll_all_requests");
// 4. Write responses
+24 -46
View File
@@ -1,4 +1,3 @@
use core::ops::{Deref, DerefMut};
use std::collections::{HashMap, VecDeque};
use std::ops::ControlFlow;
@@ -48,13 +47,7 @@ impl<'sock> ReadinessBased<'sock> {
Err(err) => return Err(err),
}
}
pub fn process_requests<Guard, S: SchemeSync>(
&mut self,
// TODO: Maybe change this to &mut SchemeSync, requires converting e.g. audiod
mut acquire_scheme: impl FnMut() -> Guard,
) where
Guard: Deref<Target = S> + DerefMut,
{
pub fn process_requests(&mut self, scheme: &mut impl SchemeSync) {
for request in self.requests_read.drain(..) {
let req = match request.kind() {
RequestKind::Call(c) => c,
@@ -67,17 +60,17 @@ impl<'sock> ReadinessBased<'sock> {
}
RequestKind::OnClose { id } => {
// TODO: state.on_close()
acquire_scheme().on_close(id);
scheme.on_close(id);
continue;
}
RequestKind::SendFd(sendfd_request) => {
let result = acquire_scheme().on_sendfd(&sendfd_request);
let result = scheme.on_sendfd(&sendfd_request);
let response = Response::new(result, sendfd_request);
self.responses_to_write.push_back(response);
continue;
}
RequestKind::RecvFd(recvfd_request) => {
let result = acquire_scheme().on_recvfd(&recvfd_request);
let result = scheme.on_recvfd(&recvfd_request);
let caller = recvfd_request.caller();
if let Err(Error {
@@ -102,24 +95,22 @@ impl<'sock> ReadinessBased<'sock> {
continue;
}
};
let resp =
match op.handle_sync_dont_consume(&caller, &mut *acquire_scheme(), &mut self.state)
{
SchemeResponse::Opened(Err(Error {
errno: errno::EWOULDBLOCK,
}))
| SchemeResponse::Regular(Err(Error {
errno: errno::EWOULDBLOCK,
})) if !op.is_explicitly_nonblock() => {
self.states.insert(caller.id, (caller, op));
continue;
}
SchemeResponse::Regular(r) => Response::new(r, op),
SchemeResponse::RegularAndNotifyOnDetach(status) => {
Response::new_notify_on_detach(status, op)
}
SchemeResponse::Opened(o) => Response::open_dup_like(o, op),
};
let resp = match op.handle_sync_dont_consume(&caller, scheme, &mut self.state) {
SchemeResponse::Opened(Err(Error {
errno: errno::EWOULDBLOCK,
}))
| SchemeResponse::Regular(Err(Error {
errno: errno::EWOULDBLOCK,
})) if !op.is_explicitly_nonblock() => {
self.states.insert(caller.id, (caller, op));
continue;
}
SchemeResponse::Regular(r) => Response::new(r, op),
SchemeResponse::RegularAndNotifyOnDetach(status) => {
Response::new_notify_on_detach(status, op)
}
SchemeResponse::Opened(o) => Response::open_dup_like(o, op),
};
self.responses_to_write.push_back(resp);
}
}
@@ -164,18 +155,9 @@ impl<'sock> ReadinessBased<'sock> {
};
Ok(ControlFlow::Break(resp))
}
pub fn poll_ready_requests<S, G>(&mut self, mut acquire_scheme: impl FnMut() -> G) -> Result<()>
where
S: SchemeSync,
G: Deref<Target = S> + DerefMut,
{
pub fn poll_ready_requests(&mut self, scheme: &mut impl SchemeSync) -> Result<()> {
for id in self.ready_queue.drain(..) {
match Self::poll_request_inner(
id,
&mut *acquire_scheme(),
&mut self.state,
&mut self.states,
)? {
match Self::poll_request_inner(id, scheme, &mut self.state, &mut self.states)? {
ControlFlow::Break(resp) => {
self.responses_to_write.push_back(resp);
}
@@ -186,15 +168,11 @@ impl<'sock> ReadinessBased<'sock> {
}
Ok(())
}
pub fn poll_all_requests<S, G>(&mut self, acquire_scheme: impl FnMut() -> G) -> Result<()>
where
S: SchemeSync,
G: Deref<Target = S> + DerefMut,
{
pub fn poll_all_requests(&mut self, scheme: &mut impl SchemeSync) -> Result<()> {
// TODO: implement waker-like API
self.ready_queue.clear();
self.ready_queue.extend(self.states.keys().copied());
self.poll_ready_requests(acquire_scheme)
self.poll_ready_requests(scheme)
}
pub fn write_responses(&mut self) -> Result<bool> {
match self