strat9_kernel/syscall/
poll.rs1use crate::{
2 memory::{UserSliceRead, UserSliceWrite},
3 process::current_task_clone,
4 syscall::error::SyscallError,
5};
6
7const POLLIN: i16 = 0x0001;
8const POLLOUT: i16 = 0x0004;
9const POLLNVAL: i16 = 0x0020;
10
11const POLLFD_SIZE: usize = 8; fn read_pollfd(buf: &[u8], i: usize) -> (i32, i16) {
15 let off = i * POLLFD_SIZE;
16 let fd = i32::from_le_bytes([buf[off], buf[off + 1], buf[off + 2], buf[off + 3]]);
17 let events = i16::from_le_bytes([buf[off + 4], buf[off + 5]]);
18 (fd, events)
19}
20
21fn write_revents(buf: &mut [u8], i: usize, revents: i16) {
23 let off = i * POLLFD_SIZE + 6;
24 let bytes = revents.to_le_bytes();
25 buf[off] = bytes[0];
26 buf[off + 1] = bytes[1];
27}
28
29pub fn sys_poll(fds_ptr: u64, nfds: u64, _timeout_ms: u64) -> Result<u64, SyscallError> {
31 if nfds == 0 {
32 return Ok(0);
33 }
34 if nfds > 1024 {
35 return Err(SyscallError::InvalidArgument);
36 }
37 let n = nfds as usize;
38 let byte_len = n * POLLFD_SIZE;
39
40 let task = current_task_clone().ok_or(SyscallError::Fault)?;
41 let fd_table = unsafe { &*task.process.fd_table.get() };
42
43 let reader = UserSliceRead::new(fds_ptr, byte_len)?;
44 let mut buf = alloc::vec![0u8; byte_len];
45 reader.copy_to(&mut buf);
46
47 let mut ready_count = 0u64;
48 for i in 0..n {
49 let (fd, events) = read_pollfd(&buf, i);
50 let revents = if fd < 0 {
51 0i16
52 } else {
53 match fd_table.get(fd as u32) {
54 Ok(_) => {
55 let mut r = 0i16;
56 if events & POLLIN != 0 {
57 r |= POLLIN;
58 }
59 if events & POLLOUT != 0 {
60 r |= POLLOUT;
61 }
62 r
63 }
64 Err(_) => POLLNVAL,
65 }
66 };
67 write_revents(&mut buf, i, revents);
68 if revents != 0 {
69 ready_count += 1;
70 }
71 }
72
73 let writer = UserSliceWrite::new(fds_ptr, byte_len)?;
74 writer.copy_from(&buf);
75
76 Ok(ready_count)
77}