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}