diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 603faef8..c49497ab 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -81,6 +81,11 @@ name = "bitvec" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitvec" +version = "0.11.0" +source = "git+https://github.com/myrrlyn/bitvec.git#f6e1fbed95061955d96617dfed6c112ffba45a7e" + [[package]] name = "bootloader" version = "0.4.0" @@ -308,6 +313,7 @@ dependencies = [ "bit-allocator 0.1.0", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitvec 0.11.0 (git+https://github.com/myrrlyn/bitvec.git)", "bootloader 0.4.0 (git+https://github.com/rcore-os/bootloader)", "buddy_system_allocator 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -594,6 +600,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bcm2837 0.1.0 (git+https://github.com/rcore-os/bcm2837)" = "" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitvec 0.11.0 (git+https://github.com/myrrlyn/bitvec.git)" = "" "checksum bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfadef5c4e2c2e64067b9ecc061179f12ac7ec65ba613b1f60f3972bbada1f5b" "checksum bootloader 0.4.0 (git+https://github.com/rcore-os/bootloader)" = "" "checksum buddy_system_allocator 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2ed828f1e227d6e32b998d6375b67fd63ac5389d50b23f258ce151d22b6cc595" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 1665f776..7aacfe29 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -42,6 +42,7 @@ bitflags = "1.0" bit_field = "0.9" volatile = "0.2" heapless = "0.4" +bitvec = { git = "https://github.com/myrrlyn/bitvec.git", default-features = false, features = ["alloc"] } console-traits = "0.3" buddy_system_allocator = "0.1" pci = { git = "https://github.com/rcore-os/pci-rs" } diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index b16fe736..a2636a24 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -10,6 +10,8 @@ use crate::fs::*; use crate::memory::MemorySet; use crate::sync::Condvar; +use bitvec::{BitSlice, BitVec, LittleEndian}; + use super::*; pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult { @@ -160,30 +162,30 @@ pub fn sys_select( loop { let proc = process(); let mut events = 0; - for (fd, file_like) in proc.files.iter() { - if *fd < nfds { + for (&fd, file_like) in proc.files.iter() { + if fd < nfds { match file_like { FileLike::File(_) => { // FIXME: assume it is stdin for now if STDIN.can_read() { - if read_fds.is_set(*fd) { - read_fds.set(*fd); + if read_fds.contains(fd) { + read_fds.set(fd); events = events + 1; } } } FileLike::Socket(socket) => { let (input, output, err) = socket.poll(); - if err && err_fds.is_set(*fd) { - err_fds.set(*fd); + if err && err_fds.contains(fd) { + err_fds.set(fd); events = events + 1; } - if input && read_fds.is_set(*fd) { - read_fds.set(*fd); + if input && read_fds.contains(fd) { + read_fds.set(fd); events = events + 1; } - if output && write_fds.is_set(*fd) { - write_fds.set(*fd); + if output && write_fds.contains(fd) { + write_fds.set(fd); events = events + 1; } } @@ -1172,54 +1174,51 @@ const FD_PER_ITEM: usize = 8 * size_of::(); const MAX_FDSET_SIZE: usize = 1024 / FD_PER_ITEM; struct FdSet { - addr: *mut u32, - nfds: usize, - saved: [u32; MAX_FDSET_SIZE], + bitset: &'static mut BitSlice, + origin: BitVec, } impl FdSet { /// Initialize a `FdSet` from pointer and number of fds /// Check if the array is large enough fn new(vm: &MemorySet, addr: *mut u32, nfds: usize) -> Result { - let mut saved = [0u32; MAX_FDSET_SIZE]; - if addr as usize != 0 { + if addr.is_null() { + Ok(FdSet { + bitset: BitSlice::empty_mut(), + origin: BitVec::new(), + }) + } else { let len = (nfds + FD_PER_ITEM - 1) / FD_PER_ITEM; vm.check_write_array(addr, len)?; if len > MAX_FDSET_SIZE { return Err(SysError::EINVAL); } let slice = unsafe { slice::from_raw_parts_mut(addr, len) }; + let bitset: &'static mut BitSlice = slice.into(); // save the fdset, and clear it - for i in 0..len { - saved[i] = slice[i]; - slice[i] = 0; - } + use alloc::prelude::ToOwned; + let origin = bitset.to_owned(); + bitset.set_all(false); + Ok(FdSet { bitset, origin }) } - - Ok(FdSet { addr, nfds, saved }) } /// Try to set fd in `FdSet` /// Return true when `FdSet` is valid, and false when `FdSet` is bad (i.e. null pointer) /// Fd should be less than nfds fn set(&mut self, fd: usize) -> bool { - if self.addr as usize != 0 { - assert!(fd < self.nfds); - unsafe { - *self.addr.add(fd / 8 / size_of::()) |= 1 << (fd % (8 * size_of::())); - } - true - } else { - false + if self.bitset.is_empty() { + return false; } + self.bitset.set(fd, true); + true } - /// Check to see fd is see in original `FdSet` + /// Check to see whether `fd` is in original `FdSet` /// Fd should be less than nfds - fn is_set(&mut self, fd: usize) -> bool { - assert!(fd < self.nfds); - self.saved[fd / 8 / size_of::()] & (1 << (fd % (8 * size_of::()))) != 0 + fn contains(&self, fd: usize) -> bool { + self.origin[fd] } }