From 9c3a06b8f97c2d7a332ac58508e1f36427bab90c Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Thu, 20 Oct 2016 12:31:39 -0600
Subject: [PATCH] Add nonblocking root scheme

---
 scheme/debug.rs    |  2 +-
 scheme/event.rs    |  2 +-
 scheme/root.rs     |  4 ++--
 scheme/user.rs     |  8 +++++---
 sync/wait_queue.rs | 35 +++++++++++------------------------
 5 files changed, 20 insertions(+), 31 deletions(-)

diff --git a/scheme/debug.rs b/scheme/debug.rs
index e082ac65..27ab6261 100644
--- a/scheme/debug.rs
+++ b/scheme/debug.rs
@@ -41,7 +41,7 @@ impl Scheme for DebugScheme {
     ///
     /// Returns the number of bytes read
     fn read(&self, _file: usize, buf: &mut [u8]) -> Result<usize> {
-        Ok(INPUT.call_once(init_input).receive_into(buf))
+        Ok(INPUT.call_once(init_input).receive_into(buf, true))
     }
 
     /// Write the `buffer` to the `file`
diff --git a/scheme/event.rs b/scheme/event.rs
index 1634e1b4..cca7420c 100644
--- a/scheme/event.rs
+++ b/scheme/event.rs
@@ -59,7 +59,7 @@ impl Scheme for EventScheme {
         };
 
         let event_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut Event, buf.len()/mem::size_of::<Event>()) };
-        Ok(handle.receive_into(event_buf) * mem::size_of::<Event>())
+        Ok(handle.receive_into(event_buf, true) * mem::size_of::<Event>())
     }
 
     fn fsync(&self, id: usize) -> Result<usize> {
diff --git a/scheme/root.rs b/scheme/root.rs
index 57877bf8..a2531328 100644
--- a/scheme/root.rs
+++ b/scheme/root.rs
@@ -27,7 +27,7 @@ impl RootScheme {
 }
 
 impl Scheme for RootScheme {
-    fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
+    fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
         if uid == 0 {
             let context = {
                 let contexts = context::contexts();
@@ -42,7 +42,7 @@ impl Scheme for RootScheme {
                 if schemes.get_name(path).is_some() {
                     return Err(Error::new(EEXIST));
                 }
-                let inner = Arc::new(UserInner::new(id, context));
+                let inner = Arc::new(UserInner::new(id, flags, context));
                 let scheme_id = schemes.insert(path.to_vec().into_boxed_slice(), Arc::new(Box::new(UserScheme::new(Arc::downgrade(&inner))))).expect("failed to insert user scheme");
                 inner.scheme_id.store(scheme_id, Ordering::SeqCst);
                 inner
diff --git a/scheme/user.rs b/scheme/user.rs
index c2d8650f..8f1c95a7 100644
--- a/scheme/user.rs
+++ b/scheme/user.rs
@@ -12,12 +12,13 @@ use scheme::root::ROOT_SCHEME_ID;
 use sync::{WaitQueue, WaitMap};
 use syscall::data::{Packet, Stat};
 use syscall::error::*;
-use syscall::flag::EVENT_READ;
+use syscall::flag::{EVENT_READ, O_NONBLOCK};
 use syscall::number::*;
 use syscall::scheme::Scheme;
 
 pub struct UserInner {
     handle_id: usize,
+    flags: usize,
     pub scheme_id: AtomicUsize,
     next_id: AtomicU64,
     context: Weak<RwLock<Context>>,
@@ -26,9 +27,10 @@ pub struct UserInner {
 }
 
 impl UserInner {
-    pub fn new(handle_id: usize, context: Weak<RwLock<Context>>) -> UserInner {
+    pub fn new(handle_id: usize, flags: usize, context: Weak<RwLock<Context>>) -> UserInner {
         UserInner {
             handle_id: handle_id,
+            flags: flags,
             scheme_id: AtomicUsize::new(0),
             next_id: AtomicU64::new(1),
             context: context,
@@ -158,7 +160,7 @@ impl UserInner {
 
     pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
         let packet_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut Packet, buf.len()/mem::size_of::<Packet>()) };
-        Ok(self.todo.receive_into(packet_buf) * mem::size_of::<Packet>())
+        Ok(self.todo.receive_into(packet_buf, self.flags & O_NONBLOCK != O_NONBLOCK) * mem::size_of::<Packet>())
     }
 
     pub fn write(&self, buf: &[u8]) -> Result<usize> {
diff --git a/sync/wait_queue.rs b/sync/wait_queue.rs
index 445164c4..fdf81b54 100644
--- a/sync/wait_queue.rs
+++ b/sync/wait_queue.rs
@@ -1,6 +1,4 @@
 use collections::vec_deque::VecDeque;
-use core::mem;
-use core::ops::DerefMut;
 use spin::Mutex;
 
 use sync::WaitCondition;
@@ -39,40 +37,29 @@ impl<T> WaitQueue<T> {
         }
     }
 
-    pub fn receive_into(&self, buf: &mut [T]) -> usize {
+    pub fn receive_into(&self, buf: &mut [T], block: bool) -> usize {
         let mut i = 0;
 
-        if i < buf.len() {
+        if i < buf.len() && block {
             buf[i] = self.receive();
             i += 1;
         }
 
-        while i < buf.len() {
-            if let Some(value) = self.inner.lock().pop_front() {
-                buf[i] = value;
-                i += 1;
-            } else {
-                break;
+        {
+            let mut inner = self.inner.lock();
+            while i < buf.len() {
+                if let Some(value) = inner.pop_front() {
+                    buf[i] = value;
+                    i += 1;
+                } else {
+                    break;
+                }
             }
         }
 
         i
     }
 
-    pub fn receive_all(&self) -> VecDeque<T> {
-        loop {
-            {
-                let mut inner = self.inner.lock();
-                if ! inner.is_empty() {
-                    let mut swap_inner = VecDeque::new();
-                    mem::swap(inner.deref_mut(), &mut swap_inner);
-                    return swap_inner;
-                }
-            }
-            self.condition.wait();
-        }
-    }
-
     pub fn send(&self, value: T) -> usize {
         let len = {
             let mut inner = self.inner.lock();
-- 
GitLab