From 83dea72a5068eb0f3f984f5df07584c3f590fa38 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jeremy@system76.com>
Date: Sat, 13 Feb 2021 12:57:53 -0700
Subject: [PATCH] Switch Context::files to RwLock

---
 src/context/context.rs   | 14 +++++++-------
 src/event.rs             |  2 +-
 src/scheme/sys/iostat.rs |  2 +-
 src/scheme/user.rs       |  4 ++--
 src/syscall/fs.rs        |  2 +-
 src/syscall/process.rs   | 10 +++++-----
 6 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/context/context.rs b/src/context/context.rs
index 2068d399..fccd6b0e 100644
--- a/src/context/context.rs
+++ b/src/context/context.rs
@@ -127,7 +127,7 @@ impl ContextSnapshot {
     pub fn new(context: &Context) -> Self {
         let name = context.name.read().clone();
         let mut files = Vec::new();
-        for descriptor_opt in context.files.lock().iter() {
+        for descriptor_opt in context.files.read().iter() {
             let description = if let Some(descriptor) = descriptor_opt {
                 let description = descriptor.description.read();
                 Some(FileDescription {
@@ -239,7 +239,7 @@ pub struct Context {
     /// The current working directory
     pub cwd: Arc<RwLock<Vec<u8>>>,
     /// The open files in the scheme
-    pub files: Arc<Mutex<Vec<Option<FileDescriptor>>>>,
+    pub files: Arc<RwLock<Vec<Option<FileDescriptor>>>>,
     /// Signal actions
     pub actions: Arc<Mutex<Vec<(SigAction, usize)>>>,
     /// The pointer to the user-space registers, saved after certain
@@ -294,7 +294,7 @@ impl Context {
             grants: Arc::new(Mutex::new(UserGrants::default())),
             name: Arc::new(RwLock::new(String::new().into_boxed_str())),
             cwd: Arc::new(RwLock::new(Vec::new())),
-            files: Arc::new(Mutex::new(Vec::new())),
+            files: Arc::new(RwLock::new(Vec::new())),
             actions: Arc::new(Mutex::new(vec![(
                 SigAction {
                     sa_handler: unsafe { mem::transmute(SIG_DFL) },
@@ -416,7 +416,7 @@ impl Context {
     /// Add a file to the lowest available slot greater than or equal to min.
     /// Return the file descriptor number or None if no slot was found
     pub fn add_file_min(&self, file: FileDescriptor, min: usize) -> Option<FileHandle> {
-        let mut files = self.files.lock();
+        let mut files = self.files.write();
         for (i, file_option) in files.iter_mut().enumerate() {
             if file_option.is_none() && i >= min {
                 *file_option = Some(file);
@@ -439,7 +439,7 @@ impl Context {
 
     /// Get a file
     pub fn get_file(&self, i: FileHandle) -> Option<FileDescriptor> {
-        let files = self.files.lock();
+        let files = self.files.read();
         if i.into() < files.len() {
             files[i.into()].clone()
         } else {
@@ -450,7 +450,7 @@ impl Context {
     /// Insert a file with a specific handle number. This is used by dup2
     /// Return the file descriptor number or None if the slot was not empty, or i was invalid
     pub fn insert_file(&self, i: FileHandle, file: FileDescriptor) -> Option<FileHandle> {
-        let mut files = self.files.lock();
+        let mut files = self.files.write();
         if i.into() < super::CONTEXT_MAX_FILES {
             while i.into() >= files.len() {
                 files.push(None);
@@ -469,7 +469,7 @@ impl Context {
     /// Remove a file
     // TODO: adjust files vector to smaller size if possible
     pub fn remove_file(&self, i: FileHandle) -> Option<FileDescriptor> {
-        let mut files = self.files.lock();
+        let mut files = self.files.write();
         if i.into() < files.len() {
             files[i.into()].take()
         } else {
diff --git a/src/event.rs b/src/event.rs
index f221bc20..73e2de1f 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -35,7 +35,7 @@ impl EventQueue {
                 let contexts = context::contexts();
                 let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
                 let context = context_lock.read();
-                let files = context.files.lock();
+                let files = context.files.read();
                 match files.get(event.id).ok_or(Error::new(EBADF))? {
                     Some(file) => file.clone(),
                     None => return Err(Error::new(EBADF))
diff --git a/src/scheme/sys/iostat.rs b/src/scheme/sys/iostat.rs
index 6a732279..fe0d65fa 100644
--- a/src/scheme/sys/iostat.rs
+++ b/src/scheme/sys/iostat.rs
@@ -16,7 +16,7 @@ pub fn resource() -> Result<Vec<u8>> {
             let contexts = context::contexts();
             for (id, context_lock) in contexts.iter() {
                 let context = context_lock.read();
-                rows.push((*id, context.name.read().clone(), context.files.lock().clone()));
+                rows.push((*id, context.name.read().clone(), context.files.read().clone()));
             }
         }
 
diff --git a/src/scheme/user.rs b/src/scheme/user.rs
index 8ba07864..c28b8a4f 100644
--- a/src/scheme/user.rs
+++ b/src/scheme/user.rs
@@ -349,7 +349,7 @@ impl Scheme for UserScheme {
             // TODO: Faster, cleaner mechanism to get descriptor
             let scheme = inner.scheme_id.load(Ordering::SeqCst);
             let mut desc_res = Err(Error::new(EBADF));
-            for context_file_opt in context.files.lock().iter() {
+            for context_file_opt in context.files.read().iter() {
                 if let Some(context_file) = context_file_opt {
                     let (context_scheme, context_number) = {
                         let desc = context_file.description.read();
@@ -402,7 +402,7 @@ impl Scheme for UserScheme {
             // TODO: Faster, cleaner mechanism to get descriptor
             let scheme = inner.scheme_id.load(Ordering::SeqCst);
             let mut desc_res = Err(Error::new(EBADF));
-            for context_file_opt in context.files.lock().iter() {
+            for context_file_opt in context.files.read().iter() {
                 if let Some(context_file) = context_file_opt {
                     let (context_scheme, context_number) = {
                         let desc = context_file.description.read();
diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs
index 780f869c..dd19ea42 100644
--- a/src/syscall/fs.rs
+++ b/src/syscall/fs.rs
@@ -377,7 +377,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
 
-        let mut files = context.files.lock();
+        let mut files = context.files.write();
         match *files.get_mut(fd.into()).ok_or(Error::new(EBADF))? {
             Some(ref mut file) => match cmd {
                 F_GETFD => {
diff --git a/src/syscall/process.rs b/src/syscall/process.rs
index 4f0cbacf..262ffff9 100644
--- a/src/syscall/process.rs
+++ b/src/syscall/process.rs
@@ -259,7 +259,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
             if flags.contains(CLONE_FILES) {
                 files = Arc::clone(&context.files);
             } else {
-                files = Arc::new(Mutex::new(context.files.lock().clone()));
+                files = Arc::new(RwLock::new(context.files.read().clone()));
             }
 
             if flags.contains(CLONE_SIGHAND) {
@@ -272,7 +272,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
         // If not cloning files, dup to get a new number from scheme
         // This has to be done outside the context lock to prevent deadlocks
         if !flags.contains(CLONE_FILES) {
-            for (_fd, file_opt) in files.lock().iter_mut().enumerate() {
+            for (_fd, file_opt) in files.write().iter_mut().enumerate() {
                 let new_file_opt = if let Some(ref file) = *file_opt {
                     Some(FileDescriptor {
                         description: Arc::clone(&file.description),
@@ -866,7 +866,7 @@ fn fexec_noreturn(
             (vfork, context.ppid, files)
         };
 
-        for (_fd, file_opt) in files.lock().iter_mut().enumerate() {
+        for (_fd, file_opt) in files.write().iter_mut().enumerate() {
             let mut cloexec = false;
             if let Some(ref file) = *file_opt {
                 if file.cloexec {
@@ -1108,12 +1108,12 @@ pub fn exit(status: usize) -> ! {
         let pid = {
             let mut context = context_lock.write();
             {
-                let mut lock = context.files.lock();
+                let mut lock = context.files.write();
                 if Arc::strong_count(&context.files) == 1 {
                     mem::swap(lock.deref_mut(), &mut close_files);
                 }
             }
-            context.files = Arc::new(Mutex::new(Vec::new()));
+            context.files = Arc::new(RwLock::new(Vec::new()));
             context.id
         };
 
-- 
GitLab