From 0a1e422cac1ca7daeedb44a5c76dc5fe92268ea7 Mon Sep 17 00:00:00 2001 From: ssryps <825160150@qq.com> Date: Thu, 7 Nov 2019 22:57:13 +0800 Subject: [PATCH] change code structure --- kernel/src/fs/epoll.rs | 139 +++++++++++++++++++ kernel/src/fs/file_like.rs | 2 +- kernel/src/fs/mod.rs | 1 + kernel/src/sync/condvar.rs | 30 +++-- kernel/src/syscall/fs.rs | 264 +++++-------------------------------- kernel/src/syscall/mod.rs | 2 +- 6 files changed, 194 insertions(+), 244 deletions(-) create mode 100644 kernel/src/fs/epoll.rs diff --git a/kernel/src/fs/epoll.rs b/kernel/src/fs/epoll.rs new file mode 100644 index 00000000..2c0290f7 --- /dev/null +++ b/kernel/src/fs/epoll.rs @@ -0,0 +1,139 @@ +use alloc::{collections::BTreeMap, collections::BTreeSet}; +use crate::syscall::{SysError, SysResult}; +use core::slice; +use crate::sync::{Condvar, SpinNoIrqLock}; +use crate::memory::MemorySet; +use core::mem::size_of; +use crate::process::Process; +use crate::fs::FileLike; + +pub struct EpollInstance { + pub events: BTreeMap, + pub readyList: SpinNoIrqLock>, + pub newCtlList: SpinNoIrqLock>, +} + +impl Clone for EpollInstance { + fn clone(&self) -> Self { + EpollInstance::new(0) + } +} + +impl EpollInstance { + pub fn new(flags: usize) -> Self { + return EpollInstance { + events: BTreeMap::new(), + readyList: Default::default(), + newCtlList: Default::default(), + } + } + + pub fn control(&mut self, op: usize, fd: usize, event: &EpollEvent) -> SysResult { + match (op as i32) { + EPollCtlOp::ADD => { + self.events.insert(fd, event.clone()); + self.newCtlList.lock().insert(fd); + } + + EPollCtlOp::MOD => { + if self.events.get(&fd).is_some() { + self.events.remove(&fd); + self.events.insert(fd, event.clone()); + self.newCtlList.lock().insert(fd); + + } else { + return Err(SysError::EPERM); + } + } + + EPollCtlOp::DEL => { + if self.events.get(&fd).is_some() { + self.events.remove(&fd); + } else { + return Err(SysError::EPERM); + } + + } + _ => { + return Err(SysError::EPERM); + } + } + Ok(0) + } +} + + + + +#[derive(Clone, Copy)] +pub struct EpollData { + ptr: u64, +} + +#[repr(packed)] +#[derive(Clone)] +pub struct EpollEvent { + pub events: u32, /* Epoll events */ + pub data: EpollData, /* User data variable */ +} + + +impl EpollEvent{ + pub const EPOLLIN: u32 = 0x001; + pub const EPOLLOUT: u32 = 0x004; + pub const EPOLLERR: u32 = 0x008; + pub const EPOLLHUP: u32 = 0x010; + + pub const EPOLLPRI: u32 = 0x002; + pub const EPOLLRDNORM: u32 = 0x040; + pub const EPOLLRDBAND: u32 = 0x080; + pub const EPOLLWRNORM: u32 = 0x100; + pub const EPOLLWRBAND: u32 = 0x200; + pub const EPOLLMSG: u32 = 0x400; + pub const EPOLLRDHUP: u32 = 0x2000; + pub const EPOLLEXCLUSIVE: u32 = 1 << 28; + pub const EPOLLWAKEUP: u32 = 1 << 29; + pub const EPOLLONESHOT: u32 = 1 << 30; + pub const EPOLLET: u32 = 1 << 31; + + + pub fn contains(&self, events: u32) -> bool { + if (self.events & events) == 0 { + return false; + } else { + return true; + } + } +} + +pub struct EPollCtlOp; +impl EPollCtlOp{ + const ADD: i32 = 1; /* Add a file descriptor to the interface. */ + const DEL: i32 = 2; /* Remove a file descriptor from the interface. */ + const MOD: i32 = 3; /* Change file descriptor epoll_event structure. */ +} + + +impl Process { + pub fn get_epoll_instance_mut(&mut self, fd: usize) -> Result<&mut EpollInstance, SysError> { + match self.get_file_like(fd)? { + FileLike::EpollInstance(instance) => Ok(instance), + _ => Err(SysError::EPERM), + } + } + + pub fn get_epoll_instance(&self, fd: usize) -> Result<&EpollInstance, SysError> { + match self.files.get(&fd) { + Some(file_like) => { + match file_like { + FileLike::EpollInstance(instance) => Ok(&instance), + _ => Err(SysError::EPERM), + } + } + None => { + return Err(SysError::EPERM); + } + } + } + +} \ No newline at end of file diff --git a/kernel/src/fs/file_like.rs b/kernel/src/fs/file_like.rs index 149b8bd0..52d94483 100644 --- a/kernel/src/fs/file_like.rs +++ b/kernel/src/fs/file_like.rs @@ -2,7 +2,7 @@ use core::fmt; use super::ioctl::*; use super::FileHandle; -use crate::syscall::EpollInstance; +use crate::fs::epoll::EpollInstance; use crate::net::Socket; use crate::syscall::{SysError, SysResult}; use alloc::boxed::Box; diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index 707f6479..75e812b9 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -18,6 +18,7 @@ pub use self::stdio::{STDIN, STDOUT}; pub use self::vga::*; mod device; +pub mod epoll; mod file; mod file_like; mod ioctl; diff --git a/kernel/src/sync/condvar.rs b/kernel/src/sync/condvar.rs index b9b4de81..a65d97ab 100644 --- a/kernel/src/sync/condvar.rs +++ b/kernel/src/sync/condvar.rs @@ -7,11 +7,17 @@ use alloc::vec::Vec; use crate::process::Process; use rcore_thread::std_thread::Thread; +pub struct RegisteredProcess { + proc: Arc>, + tid: usize, + epfd: usize, + fd: usize, +} #[derive(Default)] pub struct Condvar { wait_queue: SpinNoIrqLock>>, - pub epoll_queue: SpinNoIrqLock< VecDeque<(Arc>, usize, usize, usize)> >, + pub epoll_queue: SpinNoIrqLock>, } impl Condvar { @@ -125,13 +131,19 @@ impl Condvar { } pub fn register_epoll_list(&self, proc: Arc>, tid :usize, epfd: usize, fd: usize){ - self.epoll_queue.lock().push_back((proc, tid, epfd, fd)); + self.epoll_queue.lock().push_back(RegisteredProcess{ + proc: proc, + tid: tid, + epfd: epfd, + fd: fd, + } + ); } pub fn unregister_epoll_list(&self, tid :usize, epfd: usize, fd: usize) -> bool{ let mut epoll_list = self.epoll_queue.lock(); for idx in 0..epoll_list.len(){ - if epoll_list[idx].1 == tid && epoll_list[idx].2 == epfd && epoll_list[idx].3 == fd{ + if epoll_list[idx].tid == tid && epoll_list[idx].epfd == epfd && epoll_list[idx].fd == fd{ epoll_list.remove(idx); return true; } @@ -141,15 +153,13 @@ impl Condvar { fn epoll_callback(&self, thread: &Arc) { let epoll_list = self.epoll_queue.lock(); - for (proc, tid, epfd, fd) in epoll_list.iter() { - if thread.id() == *tid { - let mut proc = proc.lock(); - match proc.get_epoll_instance(*epfd) { + for ist in epoll_list.iter() { + if thread.id() == ist.tid { + let mut proc = ist.proc.lock(); + match proc.get_epoll_instance(ist.epfd) { Ok(instacne) => { let mut readylist = instacne.readyList.lock(); - if !readylist.contains(fd) { - readylist.push_back(*fd); - } + readylist.insert(ist.fd); } Err(r) => { panic!("epoll instance not exist"); diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 3c9e76ea..7f16261a 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -10,7 +10,7 @@ use crate::trap::TICK_ACTIVITY; use crate::fs::*; use crate::memory::MemorySet; use crate::sync::{Condvar, SpinNoIrqLock}; -use alloc::{collections::BTreeMap}; +use alloc::{collections::BTreeMap, collections::BTreeSet}; use bitvec::prelude::{BitSlice, BitVec, LittleEndian}; @@ -20,6 +20,7 @@ use alloc::collections::VecDeque; use rcore_fs::vfs::PollStatus; use crate::net::server; use crate::process::Process; +use crate::fs::epoll::EpollInstance; impl Syscall<'_> { pub fn sys_read(&mut self, fd: usize, base: *mut u8, len: usize) -> SysResult { @@ -108,16 +109,7 @@ impl Syscall<'_> { let mut condvars = alloc::vec![&(*TICK_ACTIVITY), &STDIN.pushed, &(*SOCKET_ACTIVITY)]; let polls = unsafe { self.vm().check_write_array(ufds, nfds)? }; - for poll in polls.iter() { - match proc.files.get(&(poll.fd as usize)){ - None => { - return Err(SysError::EINVAL); - }, - Some(file_like) => { -// file_like.poll_condvar(&mut condvars); - } - } - } + drop(proc); let begin_time_ms = crate::trap::uptime_msec(); @@ -206,10 +198,7 @@ impl Syscall<'_> { 1 << 31 }; - let mut condvars = Vec::new(); - condvars.push(&(*TICK_ACTIVITY)); - condvars.push(&STDIN.pushed); - condvars.push(&(*SOCKET_ACTIVITY)); + let mut condvars = alloc::vec![&(*TICK_ACTIVITY), &STDIN.pushed, &(*SOCKET_ACTIVITY)]; // for debugging if cfg!(debug_assertions) { @@ -277,7 +266,7 @@ impl Syscall<'_> { return Err(SysError::EINVAL); } - return self.sys_epoll_create1(0); + self.sys_epoll_create1(0) } @@ -306,20 +295,20 @@ impl Syscall<'_> { info!("sys_epoll_ctl: epfd: {}, op: {:?}, fd: {:#x}", epfd, op, fd); } - let slice = unsafe { self.vm().check_read_array(event, 1)? }; + let _event = unsafe { self.vm().check_read_ptr(event)? }; if proc.files.get(&fd).is_none(){ return Err(SysError::EPERM); } - let epollInstance = match proc.get_epoll_instance(epfd) { + let epollInstance = match proc.get_epoll_instance_mut(epfd) { Ok(ins) => ins, Err(err) => { return Err(err); } }; - let ret = epollInstance.epoll_ctl(&self.vm(),op, fd, event)?; + let ret = epollInstance.control(op, fd, & _event)?; return Ok(ret); } @@ -344,8 +333,8 @@ impl Syscall<'_> { info!("epoll_pwait: epfd: {}, timeout: {:?}", epfd, timeout_msecs); let mut proc = self.process(); - let writeslice = unsafe { self.vm().check_write_array(events, maxevents)? }; - let epollInstance = proc.get_unmut_epoll_instance(epfd)?; + let events = unsafe { self.vm().check_write_array(events, maxevents)? }; + let epollInstance = proc.get_epoll_instance(epfd)?; // add new fds which are registered by epoll_ctl after latest epoll_pwait epollInstance.readyList.lock().clear(); @@ -365,9 +354,7 @@ impl Syscall<'_> { let status = file_like.poll()?; if status.write || status.read || status.error { let mut readylist = epollInstance.readyList.lock(); - if !readylist.contains(k) { - readylist.push_back(*k); - } + readylist.insert(*k); } } } @@ -380,9 +367,6 @@ impl Syscall<'_> { for fd in &keys { let mut proc = self.process(); match proc.files.get(&fd){ - None => { - //return Err(SysError::EINVAL); - }, Some(file_like) => { match file_like{ FileLike::File(file) => { @@ -399,23 +383,20 @@ impl Syscall<'_> { return Err(SysError::EINVAL); } }; - } + }, + None => {}, } drop(proc); } - let mut condvars = Vec::new(); - condvars.push(&(*TICK_ACTIVITY)); - condvars.push(&STDIN.pushed); - condvars.push(&(*SOCKET_ACTIVITY)); - + let mut condvars = alloc::vec![&(*TICK_ACTIVITY), &STDIN.pushed, &(*SOCKET_ACTIVITY)]; let begin_time_ms = crate::trap::uptime_msec(); let condition = move || { use PollEvents as PE; let mut proc = self.process(); - let epollInstance = match proc.get_epoll_instance(epfd) { + let epollInstance = match proc.get_epoll_instance_mut(epfd) { Ok(ins) => ins, Err(err) => { return Some(Err(err)); @@ -427,8 +408,7 @@ impl Syscall<'_> { for infd in readylist.iter() { let mut status: PollStatus = Default::default(); { - if proc.files.get(&infd).is_some() { - let file_like = proc.files.get(&infd).unwrap(); + if let Some(file_like) = proc.files.get(&infd) { let _status = match file_like.poll() { Ok(ret) => ret, Err(err) => return Some(Err(err)), @@ -440,7 +420,7 @@ impl Syscall<'_> { } { - let epollInstance = match proc.get_epoll_instance(epfd) { + let epollInstance = match proc.get_epoll_instance_mut(epfd) { Ok(ins) => ins, Err(err) => { return Some(Err(err)); @@ -449,41 +429,33 @@ impl Syscall<'_> { let epollevent = epollInstance.events.get_mut(&infd)?; if status.error { - unsafe { - let _ = epollevent.copy_result_to(EpollEvent::EPOLLERR, &self.vm(), events, events_num); - } + events[events_num].events = EpollEvent::EPOLLERR; + events[events_num].data = epollevent.data; + events_num += 1; } if status.read && epollevent.contains(EpollEvent::EPOLLIN) { - unsafe { - let _ = epollevent.copy_result_to(EpollEvent::EPOLLIN, &self.vm(), events, events_num); - } + events[events_num].events = EpollEvent::EPOLLIN; + events[events_num].data = epollevent.data; events_num += 1; } if status.write && epollevent.contains(EpollEvent::EPOLLOUT) { - unsafe { - let _ = epollevent.copy_result_to(EpollEvent::EPOLLOUT, &self.vm(), events, events_num); - } + events[events_num].events = EpollEvent::EPOLLOUT; + events[events_num].data = epollevent.data; + events_num += 1; } } -// } else { -// unsafe { -// epollevent.copy_result_to(EpollEvent::EPOLLERR, &self.vm(), events, events_num); -// } -// events_num += 1; -// } } { - let epollInstance = match proc.get_epoll_instance(epfd) { + let epollInstance = match proc.get_epoll_instance_mut(epfd) { Ok(ins) => ins, Err(err) => { return Some(Err(err)); } }; - let mut lock = epollInstance.readyList.lock(); - lock.retain(|x| false); + epollInstance.readyList.lock().clear(); } drop(proc); @@ -504,12 +476,11 @@ impl Syscall<'_> { let num = Condvar::wait_events(condvars.as_slice(), condition).unwrap(); for cb in callbacks.iter(){ - if cb.0 == 0 { - &crate::fs::STDIN.pushed.unregister_epoll_list(cb.1, cb.2, cb.3); - } - if cb.0 == 1 { - &(*crate::drivers::SOCKET_ACTIVITY).unregister_epoll_list(cb.1, cb.2, cb.3); - } + match cb.0 { + 0 => &crate::fs::STDIN.pushed.unregister_epoll_list(cb.1, cb.2, cb.3), + 1 => &(*crate::drivers::SOCKET_ACTIVITY).unregister_epoll_list(cb.1, cb.2, cb.3), + _ => panic!("cb error"), + }; } Ok(num) } @@ -1805,178 +1776,7 @@ impl FdSet { } -//#[derive(Clone)] -pub struct EpollInstance { - pub events: BTreeMap, - pub readyList: SpinNoIrqLock>, - pub newCtlList: SpinNoIrqLock>, -} -impl Clone for EpollInstance { - fn clone(&self) -> Self { - EpollInstance::new(0) - } -} - -impl EpollInstance { - pub fn new(flags: usize) -> Self { - return EpollInstance { - events: BTreeMap::new(), - readyList: Default::default(), - newCtlList: Default::default(), - } - } - - pub fn epoll_ctl(&mut self, vm: &MemorySet, op: usize, fd: usize, event: *mut EpollEvent) -> SysResult { - match (op as i32) { - EPollCtlOp::EPOLLCTLADD => { - //if self.events.get(&fd).is_none() { - let evs = unsafe { vm.check_read_array(event, 1)? }; - for ev in evs.iter() { - self.events.insert(fd, ev.clone()); - let mut l = self.newCtlList.lock(); - if !l.contains(&fd) { - l.push_back(fd); - } - - } -// } else { -// return Err(SysError::EPERM); -// } - - } - EPollCtlOp::EPOLLCTLMOD => { - if self.events.get(&fd).is_some() { - let evs = unsafe { vm.check_read_array(event, 1)? }; - for ev in evs.iter() { - self.events.remove(&fd); - self.events.insert(fd, ev.clone()); - let mut l = self.newCtlList.lock(); - if !l.contains(&fd) { - l.push_back(fd); - } - - } - } else { - return Err(SysError::EPERM); - } - } - EPollCtlOp::EPOLLCTLDEL => { - if self.events.get(&fd).is_some() { - let evs = unsafe { vm.check_read_array(event, 1)? }; - for ev in evs.iter() { - self.events.remove(&fd); - } - } else { - return Err(SysError::EPERM); - } - - } - _ => { - return Err(SysError::EPERM); - } - } - Ok(0) - } -} - - -//#[derive(Clone)] -//union EpollData { -// ptr: u64, -// fd: i32, -// v32: u32, -// v64: u64, -//} - -#[derive(Clone)] -pub struct EpollData { - ptr: u64, -} - -#[repr(packed)] -#[derive(Clone)] -pub struct EpollEvent { - events: u32, /* Epoll events */ - data: EpollData, /* User data variable */ -} - -impl EpollEvent{ - unsafe fn copy_result_to(&mut self, events: u32, vm: &MemorySet, - baseAddr: *mut EpollEvent, idx: usize) -> SysResult{ - let tmp = self.events; - self.events = events; - - let addr = baseAddr as usize + idx * size_of::(); - let written_len = size_of::(); - let target = vm.check_write_array(addr as *mut u8, written_len)?; - let source = slice::from_raw_parts(self as *mut EpollEvent as *const u8, written_len); - target.copy_from_slice(source); - self.events = tmp; - - Ok(0) - } - - fn contains(&self, events: u32) -> bool { - if (self.events & events) == 0 { - return false; - } else { - return true; - } - } -} - -pub struct EPollCtlOp; -impl EPollCtlOp{ - const EPOLLCTLADD: i32 = 1; /* Add a file descriptor to the interface. */ - const EPOLLCTLDEL: i32 = 2; /* Remove a file descriptor from the interface. */ - const EPOLLCTLMOD: i32 = 3; /* Change file descriptor epoll_event structure. */ -} - - -impl EpollEvent { - const EPOLLIN: u32 = 0x001; - const EPOLLOUT: u32 = 0x004; - const EPOLLERR: u32 = 0x008; - const EPOLLHUP: u32 = 0x010; - - const EPOLLPRI: u32 = 0x002; - const EPOLLRDNORM: u32 = 0x040; - const EPOLLRDBAND: u32 = 0x080; - const EPOLLWRNORM: u32 = 0x100; - const EPOLLWRBAND: u32 = 0x200; - const EPOLLMSG: u32 = 0x400; - const EPOLLRDHUP: u32 = 0x2000; - const EPOLLEXCLUSIVE: u32 = 1 << 28; - const EPOLLWAKEUP: u32 = 1 << 29; - const EPOLLONESHOT: u32 = 1 << 30; - const EPOLLET: u32 = 1 << 31; -} - - -impl Process { - pub fn get_epoll_instance(&mut self, fd: usize) -> Result<&mut EpollInstance, SysError> { - match self.get_file_like(fd)? { - FileLike::EpollInstance(instance) => Ok(instance), - _ => Err(SysError::EPERM), - } - } - - pub fn get_unmut_epoll_instance(&self, fd: usize) -> Result<&EpollInstance, SysError> { - match self.files.get(&fd) { - Some(file_like) => { - match file_like { - FileLike::EpollInstance(instance) => Ok(&instance), - _ => Err(SysError::EPERM), - } - } - None => { - return Err(SysError::EPERM); - } - } - } - -} /// Pathname is interpreted relative to the current working directory(CWD) const AT_FDCWD: usize = -100isize as usize; diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 11e21c0e..4e8bd658 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -15,7 +15,7 @@ use crate::process::*; use crate::sync::{Condvar, MutexGuard, SpinNoIrq}; use crate::thread; use crate::util; -use crate::syscall::{EpollEvent}; +use crate::fs::epoll::EpollEvent; pub use self::custom::*; pub use self::fs::*;