1extern crate alloc;
15
16use alloc::collections::BTreeMap;
17
18use spin::Mutex;
19
20use crate::error::KernelError;
21
22const MAX_EPOLL_INSTANCES: usize = 256;
24
25const MAX_EPOLL_FDS: usize = 1024;
27
28pub const EPOLLIN: u32 = 0x001;
34pub const EPOLLOUT: u32 = 0x004;
36pub const EPOLLERR: u32 = 0x008;
38pub const EPOLLHUP: u32 = 0x010;
40pub const EPOLLET: u32 = 1 << 31;
42pub const EPOLLONESHOT: u32 = 1 << 30;
44
45pub const EPOLL_CTL_ADD: u32 = 1;
51pub const EPOLL_CTL_DEL: u32 = 2;
53pub const EPOLL_CTL_MOD: u32 = 3;
55
56#[repr(C)]
63#[derive(Debug, Clone, Copy)]
64pub struct EpollEvent {
65 pub events: u32,
67 pub data: u64,
69}
70
71#[derive(Debug, Clone)]
73struct InterestEntry {
74 fd: i32,
76 events: u32,
78 data: u64,
80 edge_triggered: bool,
82 one_shot: bool,
84 disabled: bool,
86}
87
88struct EpollInstance {
90 interest: BTreeMap<i32, InterestEntry>,
92 _id: u32,
94 _owner_pid: u64,
96}
97
98impl EpollInstance {
99 fn new(id: u32, owner_pid: u64) -> Self {
100 Self {
101 interest: BTreeMap::new(),
102 _id: id,
103 _owner_pid: owner_pid,
104 }
105 }
106
107 fn ctl_add(&mut self, fd: i32, event: &EpollEvent) -> Result<(), KernelError> {
109 if self.interest.contains_key(&fd) {
110 return Err(KernelError::AlreadyExists {
111 resource: "epoll fd entry",
112 id: fd as u64,
113 });
114 }
115 if self.interest.len() >= MAX_EPOLL_FDS {
116 return Err(KernelError::ResourceExhausted {
117 resource: "epoll interest list",
118 });
119 }
120
121 let entry = InterestEntry {
122 fd,
123 events: event.events & !(EPOLLET | EPOLLONESHOT),
124 data: event.data,
125 edge_triggered: event.events & EPOLLET != 0,
126 one_shot: event.events & EPOLLONESHOT != 0,
127 disabled: false,
128 };
129 self.interest.insert(fd, entry);
130 Ok(())
131 }
132
133 fn ctl_del(&mut self, fd: i32) -> Result<(), KernelError> {
135 self.interest.remove(&fd).ok_or(KernelError::NotFound {
136 resource: "epoll fd entry",
137 id: fd as u64,
138 })?;
139 Ok(())
140 }
141
142 fn ctl_mod(&mut self, fd: i32, event: &EpollEvent) -> Result<(), KernelError> {
144 let entry = self.interest.get_mut(&fd).ok_or(KernelError::NotFound {
145 resource: "epoll fd entry",
146 id: fd as u64,
147 })?;
148
149 entry.events = event.events & !(EPOLLET | EPOLLONESHOT);
150 entry.data = event.data;
151 entry.edge_triggered = event.events & EPOLLET != 0;
152 entry.one_shot = event.events & EPOLLONESHOT != 0;
153 entry.disabled = false;
154 Ok(())
155 }
156
157 fn poll_events(&mut self, events: &mut [EpollEvent]) -> usize {
165 let max_events = events.len();
166 let mut count = 0;
167
168 for entry in self.interest.values_mut() {
169 if count >= max_events {
170 break;
171 }
172 if entry.disabled {
173 continue;
174 }
175
176 let ready = poll_fd_readiness(entry.fd);
177 let matched = ready & entry.events;
178
179 if matched != 0 {
180 events[count] = EpollEvent {
181 events: matched,
182 data: entry.data,
183 };
184 count += 1;
185
186 if entry.one_shot {
187 entry.disabled = true;
188 }
189 }
190 }
191
192 count
193 }
194}
195
196static EPOLL_REGISTRY: Mutex<Option<EpollRegistry>> = Mutex::new(None);
202
203struct EpollRegistry {
204 instances: BTreeMap<u32, EpollInstance>,
205 next_id: u32,
206}
207
208impl EpollRegistry {
209 fn new() -> Self {
210 Self {
211 instances: BTreeMap::new(),
212 next_id: 1,
213 }
214 }
215}
216
217pub fn init() -> Result<(), KernelError> {
219 let mut reg = EPOLL_REGISTRY.lock();
220 if reg.is_some() {
221 return Ok(());
222 }
223 *reg = Some(EpollRegistry::new());
224 Ok(())
225}
226
227pub fn epoll_create(owner_pid: u64) -> Result<u32, KernelError> {
233 let mut reg_guard = EPOLL_REGISTRY.lock();
234 let reg = reg_guard
235 .as_mut()
236 .ok_or(KernelError::NotInitialized { subsystem: "epoll" })?;
237
238 if reg.instances.len() >= MAX_EPOLL_INSTANCES {
239 return Err(KernelError::ResourceExhausted {
240 resource: "epoll instances",
241 });
242 }
243
244 let id = reg.next_id;
245 reg.next_id += 1;
246 reg.instances.insert(id, EpollInstance::new(id, owner_pid));
247 Ok(id)
248}
249
250pub fn epoll_ctl(
252 epoll_id: u32,
253 op: u32,
254 fd: i32,
255 event: Option<&EpollEvent>,
256) -> Result<(), KernelError> {
257 let mut reg_guard = EPOLL_REGISTRY.lock();
258 let reg = reg_guard
259 .as_mut()
260 .ok_or(KernelError::NotInitialized { subsystem: "epoll" })?;
261
262 let instance = reg
263 .instances
264 .get_mut(&epoll_id)
265 .ok_or(KernelError::NotFound {
266 resource: "epoll instance",
267 id: epoll_id as u64,
268 })?;
269
270 match op {
271 EPOLL_CTL_ADD => {
272 let ev = event.ok_or(KernelError::InvalidArgument {
273 name: "event",
274 value: "required for EPOLL_CTL_ADD",
275 })?;
276 instance.ctl_add(fd, ev)
277 }
278 EPOLL_CTL_DEL => instance.ctl_del(fd),
279 EPOLL_CTL_MOD => {
280 let ev = event.ok_or(KernelError::InvalidArgument {
281 name: "event",
282 value: "required for EPOLL_CTL_MOD",
283 })?;
284 instance.ctl_mod(fd, ev)
285 }
286 _ => Err(KernelError::InvalidArgument {
287 name: "op",
288 value: "invalid epoll_ctl operation",
289 }),
290 }
291}
292
293pub fn epoll_wait(
300 epoll_id: u32,
301 events: &mut [EpollEvent],
302 timeout_ms: i32,
303) -> Result<usize, KernelError> {
304 let start = crate::timer::get_uptime_ms();
305 let max_wait_ms: u64 = if timeout_ms < 0 {
307 30_000
308 } else {
309 timeout_ms as u64
310 };
311
312 loop {
313 let count = {
314 let mut reg_guard = EPOLL_REGISTRY.lock();
315 let reg = reg_guard
316 .as_mut()
317 .ok_or(KernelError::NotInitialized { subsystem: "epoll" })?;
318
319 let instance = reg
320 .instances
321 .get_mut(&epoll_id)
322 .ok_or(KernelError::NotFound {
323 resource: "epoll instance",
324 id: epoll_id as u64,
325 })?;
326
327 instance.poll_events(events)
328 }; if count > 0 || timeout_ms == 0 {
331 return Ok(count);
332 }
333
334 if crate::timer::get_uptime_ms() - start >= max_wait_ms {
335 return Ok(0);
336 }
337
338 crate::sched::yield_cpu();
339 }
340}
341
342pub fn epoll_destroy(epoll_id: u32) -> Result<(), KernelError> {
344 let mut reg_guard = EPOLL_REGISTRY.lock();
345 let reg = reg_guard
346 .as_mut()
347 .ok_or(KernelError::NotInitialized { subsystem: "epoll" })?;
348
349 reg.instances
350 .remove(&epoll_id)
351 .ok_or(KernelError::NotFound {
352 resource: "epoll instance",
353 id: epoll_id as u64,
354 })?;
355 Ok(())
356}
357
358fn poll_fd_readiness(fd: i32) -> u32 {
369 let proc = match crate::process::current_process() {
373 Some(p) => p,
374 None => return EPOLLERR,
375 };
376
377 let file_table = proc.file_table.lock();
378 let file = match file_table.get(fd as usize) {
379 Some(f) => f,
380 None => return EPOLLERR | EPOLLHUP,
381 };
382
383 let readiness = file.node.poll_readiness() as u32;
386 let mut ready = 0u32;
387 if readiness & 0x0001 != 0 {
388 ready |= EPOLLIN;
389 }
390 if readiness & 0x0004 != 0 {
391 ready |= EPOLLOUT;
392 }
393 if readiness & 0x0008 != 0 {
394 ready |= EPOLLERR;
395 }
396 if readiness & 0x0010 != 0 {
397 ready |= EPOLLHUP;
398 }
399
400 ready
401}
402
403use alloc::{sync::Arc, vec::Vec};
408
409use crate::fs::{DirEntry, Metadata, NodeType, Permissions, VfsNode};
410
411pub struct EpollNode {
416 epoll_id: u32,
417}
418
419impl EpollNode {
420 pub fn new(epoll_id: u32) -> Self {
421 Self { epoll_id }
422 }
423
424 pub fn epoll_id(&self) -> u32 {
426 self.epoll_id
427 }
428}
429
430impl VfsNode for EpollNode {
431 fn node_type(&self) -> NodeType {
432 NodeType::CharDevice
433 }
434
435 fn read(&self, _offset: usize, _buffer: &mut [u8]) -> Result<usize, KernelError> {
436 Err(KernelError::PermissionDenied {
437 operation: "read epoll",
438 })
439 }
440
441 fn write(&self, _offset: usize, _data: &[u8]) -> Result<usize, KernelError> {
442 Err(KernelError::PermissionDenied {
443 operation: "write epoll",
444 })
445 }
446
447 fn as_any(&self) -> Option<&dyn core::any::Any> {
448 Some(self)
449 }
450
451 fn metadata(&self) -> Result<Metadata, KernelError> {
452 Ok(Metadata {
453 size: 0,
454 node_type: NodeType::CharDevice,
455 permissions: Permissions::from_mode(0o666),
456 uid: 0,
457 gid: 0,
458 created: 0,
459 modified: 0,
460 accessed: 0,
461 inode: 0,
462 })
463 }
464
465 fn readdir(&self) -> Result<Vec<DirEntry>, KernelError> {
466 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
467 }
468
469 fn lookup(&self, _name: &str) -> Result<Arc<dyn VfsNode>, KernelError> {
470 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
471 }
472
473 fn create(
474 &self,
475 _name: &str,
476 _permissions: Permissions,
477 ) -> Result<Arc<dyn VfsNode>, KernelError> {
478 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
479 }
480
481 fn mkdir(
482 &self,
483 _name: &str,
484 _permissions: Permissions,
485 ) -> Result<Arc<dyn VfsNode>, KernelError> {
486 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
487 }
488
489 fn unlink(&self, _name: &str) -> Result<(), KernelError> {
490 Err(KernelError::FsError(crate::error::FsError::NotADirectory))
491 }
492
493 fn truncate(&self, _size: usize) -> Result<(), KernelError> {
494 Err(KernelError::PermissionDenied {
495 operation: "truncate epoll",
496 })
497 }
498}
499
500impl Drop for EpollNode {
501 fn drop(&mut self) {
502 let _ = epoll_destroy(self.epoll_id);
503 }
504}