kernel/object/capability/
selectable.rs

1//! Selectable capability for readiness and blocking waits used by select/pselect.
2//!
3//! This capability provides a minimal, ABI-agnostic interface that kernel objects
4//! can implement to participate in select-like syscalls. It is intentionally
5//! simple: callers provide an interest (read/write/except), can query the
6//! current readiness, and can block the current task until the interest
7//! becomes ready or an optional timeout expires.
8//!
9//! Timeout semantics use kernel ticks to avoid coupling to any specific time
10//! unit representation at the ABI layer. See `crate::timer` for conversion
11//! helpers (e.g., `ns_to_ticks`).
12
13use crate::arch::Trapframe;
14
15/// Interest mask for readiness queries and waits.
16#[derive(Clone, Copy, Debug, Default)]
17pub struct ReadyInterest {
18    pub read: bool,
19    pub write: bool,
20    pub except: bool,
21}
22
23impl ReadyInterest {
24    pub const fn read() -> Self {
25        Self {
26            read: true,
27            write: false,
28            except: false,
29        }
30    }
31    pub const fn write() -> Self {
32        Self {
33            read: false,
34            write: true,
35            except: false,
36        }
37    }
38    pub const fn rw() -> Self {
39        Self {
40            read: true,
41            write: true,
42            except: false,
43        }
44    }
45}
46
47/// Result mask for readiness queries.
48#[derive(Clone, Copy, Debug, Default)]
49pub struct ReadySet {
50    pub read: bool,
51    pub write: bool,
52    pub except: bool,
53}
54
55impl ReadySet {
56    pub const fn none() -> Self {
57        Self {
58            read: false,
59            write: false,
60            except: false,
61        }
62    }
63}
64
65/// Outcome of a wait operation.
66#[derive(Clone, Copy, Debug, PartialEq, Eq)]
67pub enum SelectWaitOutcome {
68    Ready,
69    TimedOut,
70}
71
72/// Objects that can be waited on by select/pselect.
73pub trait Selectable {
74    /// Return current readiness for the given interest set.
75    fn current_ready(&self, interest: ReadyInterest) -> ReadySet {
76        // Default: treat as always-ready for read/write interests, except is false
77        let mut set = ReadySet::none();
78        if interest.read {
79            set.read = true;
80        }
81        if interest.write {
82            set.write = true;
83        }
84        if interest.except {
85            set.except = false;
86        }
87        set
88    }
89
90    /// Block the current task using the provided trapframe until the interest
91    /// becomes ready or the optional timeout (in ticks) expires.
92    ///
93    /// Return `SelectWaitOutcome::TimedOut` if the timeout elapsed before
94    /// readiness, otherwise `SelectWaitOutcome::Ready`.
95    fn wait_until_ready(
96        &self,
97        interest: ReadyInterest,
98        trapframe: &mut Trapframe,
99        timeout_ticks: Option<u64>,
100    ) -> SelectWaitOutcome;
101
102    /// Enable or disable non-blocking I/O semantics on this object.
103    ///
104    /// When enabled, operations that would otherwise block (e.g., reads with
105    /// no data available, writes to a full buffer) should avoid internal waits
106    /// and instead report a WouldBlock condition to the caller.
107    fn set_nonblocking(&self, _enabled: bool) {}
108
109    /// Query whether non-blocking I/O semantics are enabled on this object.
110    fn is_nonblocking(&self) -> bool {
111        true
112    }
113}