diff --git a/kernel/aster-nix/src/fs/ramfs/fs.rs b/kernel/aster-nix/src/fs/ramfs/fs.rs index cb85b9bfc..1c81442f4 100644 --- a/kernel/aster-nix/src/fs/ramfs/fs.rs +++ b/kernel/aster-nix/src/fs/ramfs/fs.rs @@ -1093,12 +1093,18 @@ impl Inode for RamInode { } fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents { - if let Some(device) = self.node.read().inner.as_device() { - device.poll(mask, poller) - } else { - let events = IoEvents::IN | IoEvents::OUT; - events & mask + if !self.typ.is_device() { + // Fast path: bypassing the read lock on `self.node` + // results in a 5x speed improvement for lmbench-select-file. + return (IoEvents::IN | IoEvents::OUT) & mask; } + + let node = self.node.read(); + let device = node + .inner + .as_device() + .expect("[Internal error] self.typ is device, while self.node is not"); + device.poll(mask, poller) } fn fs(&self) -> Arc { diff --git a/kernel/aster-nix/src/fs/utils/inode.rs b/kernel/aster-nix/src/fs/utils/inode.rs index 3f3f8c902..935b7daac 100644 --- a/kernel/aster-nix/src/fs/utils/inode.rs +++ b/kernel/aster-nix/src/fs/utils/inode.rs @@ -51,6 +51,10 @@ impl InodeType { pub fn is_directory(&self) -> bool { *self == InodeType::Dir } + + pub fn is_device(&self) -> bool { + *self == InodeType::BlockDevice || *self == InodeType::CharDevice + } } impl From for InodeType { diff --git a/kernel/aster-nix/src/syscall/poll.rs b/kernel/aster-nix/src/syscall/poll.rs index a1166e76f..ebe1e9e01 100644 --- a/kernel/aster-nix/src/syscall/poll.rs +++ b/kernel/aster-nix/src/syscall/poll.rs @@ -51,6 +51,7 @@ pub fn do_poll(poll_fds: &[PollFd], timeout: Option, ctx: &Context) -> loop { let mut num_revents = 0; + let file_table = ctx.process.file_table().lock(); for poll_fd in poll_fds { // Skip poll_fd if it is not given a fd let fd = match poll_fd.fd() { @@ -59,10 +60,7 @@ pub fn do_poll(poll_fds: &[PollFd], timeout: Option, ctx: &Context) -> }; // Poll the file - let file = { - let file_table = ctx.process.file_table().lock(); - file_table.get_file(fd)?.clone() - }; + let file = file_table.get_file(fd)?; let need_poller = if num_revents == 0 { Some(&mut poller) } else { @@ -75,6 +73,8 @@ pub fn do_poll(poll_fds: &[PollFd], timeout: Option, ctx: &Context) -> } } + drop(file_table); + if num_revents > 0 { return Ok(num_revents); } diff --git a/kernel/aster-nix/src/syscall/select.rs b/kernel/aster-nix/src/syscall/select.rs index db2d84f1c..a2cc92eb4 100644 --- a/kernel/aster-nix/src/syscall/select.rs +++ b/kernel/aster-nix/src/syscall/select.rs @@ -102,7 +102,7 @@ fn do_select( ) -> Result { // Convert the FdSet to an array of PollFd let poll_fds = { - let mut poll_fds = Vec::new(); + let mut poll_fds = Vec::with_capacity(nfds as usize); for fd in 0..nfds { let events = { let readable = readfds.as_ref().map_or(false, |fds| fds.is_set(fd)); diff --git a/kernel/libs/aster-util/src/slot_vec.rs b/kernel/libs/aster-util/src/slot_vec.rs index 51bdf7085..787d238aa 100644 --- a/kernel/libs/aster-util/src/slot_vec.rs +++ b/kernel/libs/aster-util/src/slot_vec.rs @@ -49,10 +49,7 @@ impl SlotVec { /// /// Return `None` if `idx` is out of bounds or the item is not exist. pub fn get(&self, idx: usize) -> Option<&T> { - if idx >= self.slots.len() { - return None; - } - self.slots[idx].as_ref() + self.slots.get(idx)?.as_ref() } /// Put an item into the vector.