From 8b9aecca1cbc6caaa9a66f55bce8ccf0d1b2e21e Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Thu, 7 Mar 2019 07:46:11 +0800 Subject: [PATCH] Fix a potential racing in park() and unpark(), fix sys_poll for a running telnet --- crate/thread/src/thread_pool.rs | 37 ++++++++++++++------------- kernel/src/backtrace.rs | 3 ++- kernel/src/syscall/fs.rs | 45 +++++++++++++++++++++++---------- kernel/src/syscall/net.rs | 1 + 4 files changed, 53 insertions(+), 33 deletions(-) diff --git a/crate/thread/src/thread_pool.rs b/crate/thread/src/thread_pool.rs index 60c6bdc..715ad35 100644 --- a/crate/thread/src/thread_pool.rs +++ b/crate/thread/src/thread_pool.rs @@ -131,24 +131,25 @@ impl ThreadPool { /// Insert/Remove it to/from scheduler if necessary. fn set_status(&self, tid: Tid, status: Status) { let mut proc_lock = self.threads[tid].lock(); - let mut proc = proc_lock.as_mut().expect("process not exist"); - trace!("process {} {:?} -> {:?}", tid, proc.status, status); - match (&proc.status, &status) { - (Status::Ready, Status::Ready) => return, - (Status::Ready, _) => panic!("can not remove a process from ready queue"), - (Status::Exited(_), _) => panic!("can not set status for a exited process"), - (Status::Sleeping, Status::Exited(_)) => self.timer.lock().stop(Event::Wakeup(tid)), - (Status::Running(_), Status::Ready) => {} // to stop a thread, use stop() intead - (_, Status::Ready) => self.scheduler.push(tid), - _ => {} - } - match proc.status { - Status::Running(_) => proc.status_after_stop = status, - _ => proc.status = status, - } - match proc.status { - Status::Exited(_) => self.exit_handler(tid, proc), - _ => {} + if let Some(mut proc) = proc_lock.as_mut() { + trace!("process {} {:?} -> {:?}", tid, proc.status, status); + match (&proc.status, &status) { + (Status::Ready, Status::Ready) => return, + (Status::Ready, _) => panic!("can not remove a process from ready queue"), + (Status::Exited(_), _) => panic!("can not set status for a exited process"), + (Status::Sleeping, Status::Exited(_)) => self.timer.lock().stop(Event::Wakeup(tid)), + (Status::Running(_), Status::Ready) => {} // process will be added to scheduler in stop() + (_, Status::Ready) => self.scheduler.push(tid), + _ => {} + } + match proc.status { + Status::Running(_) => proc.status_after_stop = status, + _ => proc.status = status, + } + match proc.status { + Status::Exited(_) => self.exit_handler(tid, proc), + _ => {} + } } } diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index a10c070..631d9ea 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -72,7 +72,8 @@ pub fn backtrace() { // Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate) // size = 512 pages current_fp = *(current_fp as *const usize).offset(0); - if current_fp >= 0x0000_57ac_0000_0000 + 512 * PAGE_SIZE - size_of::() { + if current_fp >= 0x0000_57ac_0000_0000 + 512 * PAGE_SIZE - size_of::() && + current_fp <= 0xffff_ff00_0000_0000 { break; } current_pc = *(current_fp as *const usize).offset(1); diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 79e813c..15b3301 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -62,13 +62,15 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu loop { use PollEvents as PE; let mut proc = process(); + let mut events = 0; for poll in polls.iter_mut() { + poll.revents = PE::NONE; match proc.files.get(&(poll.fd as usize)) { Some(FileLike::File(_)) => { // FIXME: assume it is stdin for now if poll.events.contains(PE::IN) && STDIN.can_read() { - poll.revents = PE::IN; - return Ok(0); + poll.revents = poll.revents | PE::IN; + events = events + 1; } }, Some(FileLike::Socket(wrapper)) => { @@ -78,29 +80,42 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu let mut socket = sockets.get::(wrapper.handle); if !socket.is_open() { - poll.revents = PE::HUP; - return Ok(0); - } else if socket.can_recv() && poll.events.contains(PE::IN) { - poll.revents = PE::IN; - return Ok(0); - } else if socket.can_send() && poll.events.contains(PE::OUT) { - poll.revents = PE::OUT; - return Ok(0); - } + poll.revents = poll.revents | PE::HUP; + events = events + 1; + } else { + if socket.can_recv() && poll.events.contains(PE::IN) { + poll.revents = poll.revents | PE::IN; + events = events + 1; + } + + if socket.can_send() && poll.events.contains(PE::OUT) { + poll.revents = poll.revents | PE::OUT; + events = events + 1; + } + } } else { unimplemented!() } } None => { - poll.revents = PE::ERR; - return Ok(0); + poll.revents = poll.revents | PE::ERR; + events = events + 1; } } } drop(proc); + + if events > 0 { + return Ok(events as isize); + } + + let current_time_ms = unsafe {crate::trap::TICK / crate::consts::USEC_PER_TICK / 1000}; + if timeout_msecs < (1 << 31) && current_time_ms - begin_time_ms > timeout_msecs { + return Ok(0); + } + Condvar::wait_any(&[&STDIN.pushed, &(*SOCKET_ACTIVITY)]); } - Ok(nfds as isize) } pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult { @@ -704,6 +719,8 @@ pub struct PollFd { bitflags! { pub struct PollEvents: u16 { + /// Nothing Happens + const NONE = 0x0000; /// There is data to read. const IN = 0x0001; /// Writing is now possible. diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 3f14930..4cf4ea4 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -294,6 +294,7 @@ pub fn sys_read_socket(proc: &mut Process, fd: usize, base: *mut u8, len: usize) // avoid deadlock drop(socket); + drop(sockets); SOCKET_ACTIVITY._wait() } } else if let SocketType::Udp = wrapper.socket_type {