]> git.lizzy.rs Git - rust.git/commitdiff
also combine re-locking into the dequeue-and-unblock operation
authorRalf Jung <post@ralfj.de>
Sat, 30 May 2020 20:35:58 +0000 (22:35 +0200)
committerRalf Jung <post@ralfj.de>
Sat, 30 May 2020 20:35:58 +0000 (22:35 +0200)
src/shims/sync.rs
src/sync.rs

index 01c7b4a1eb4fa158eff8e111df4690c84e58dd7b..2669776db5bad860af1a8f0acb0549ebbd8acf2c 100644 (file)
@@ -606,9 +606,7 @@ fn pthread_rwlock_unlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<
             if this.rwlock_is_locked(id) {
                 // No more readers owning the lock. Give it to a writer if there
                 // is any.
-                if let Some(writer) = this.rwlock_dequeue_and_unblock_writer(id) {
-                    this.rwlock_writer_lock(id, writer);
-                }
+                this.rwlock_dequeue_and_lock_writer(id);
             }
             Ok(0)
         } else if Some(active_thread) == this.rwlock_writer_unlock(id) {
@@ -617,13 +615,12 @@ fn pthread_rwlock_unlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<
             // We are prioritizing writers here against the readers. As a
             // result, not only readers can starve writers, but also writers can
             // starve readers.
-            if let Some(writer) = this.rwlock_dequeue_and_unblock_writer(id) {
-                // Give the lock to another writer.
-                this.rwlock_writer_lock(id, writer);
+            if this.rwlock_dequeue_and_lock_writer(id) {
+                // Someone got the write lock, nice.
             } else {
                 // Give the lock to all readers.
-                while let Some(reader) = this.rwlock_dequeue_and_unblock_reader(id) {
-                    this.rwlock_reader_lock(id, reader);
+                while this.rwlock_dequeue_and_lock_reader(id) {
+                    // Rinse and repeat.
                 }
             }
             Ok(0)
index 8418bd429515ef320a55a8e7c6e587ae5ac4ed73..723815dbf226ec8b9ff08ebfdebe86a16bbde265 100644 (file)
@@ -170,9 +170,7 @@ fn mutex_unlock(
                 mutex.owner = None;
                 // The mutex is completely unlocked. Try transfering ownership
                 // to another thread.
-                if let Some(new_owner) = this.mutex_dequeue_and_unblock(id) {
-                    this.mutex_lock(id, new_owner);
-                }
+                this.mutex_dequeue_and_lock(id);
             }
             Ok(Some(old_lock_count))
         } else {
@@ -182,7 +180,7 @@ fn mutex_unlock(
     }
 
     #[inline]
-    /// Put the thread into the queue waiting for the lock.
+    /// Put the thread into the queue waiting for the mutex.
     fn mutex_enqueue_and_block(&mut self, id: MutexId, thread: ThreadId) {
         let this = self.eval_context_mut();
         assert!(this.mutex_is_locked(id), "queing on unlocked mutex");
@@ -191,14 +189,16 @@ fn mutex_enqueue_and_block(&mut self, id: MutexId, thread: ThreadId) {
     }
 
     #[inline]
-    /// Take a thread out of the queue waiting for the lock.
-    fn mutex_dequeue_and_unblock(&mut self, id: MutexId) -> Option<ThreadId> {
+    /// Take a thread out of the queue waiting for the mutex, and lock
+    /// the mutex for it. Returns `true` if some thread has the mutex now.
+    fn mutex_dequeue_and_lock(&mut self, id: MutexId) -> bool {
         let this = self.eval_context_mut();
         if let Some(thread) = this.machine.threads.sync.mutexes[id].queue.pop_front() {
             this.unblock_thread(thread);
-            Some(thread)
+            this.mutex_lock(id, thread);
+            true
         } else {
-            None
+            false
         }
     }
 
@@ -266,13 +266,15 @@ fn rwlock_enqueue_and_block_reader(
 
     #[inline]
     /// Take a reader out the queue waiting for the lock.
-    fn rwlock_dequeue_and_unblock_reader(&mut self, id: RwLockId) -> Option<ThreadId> {
+    /// Returns `true` if some thread got the rwlock.
+    fn rwlock_dequeue_and_lock_reader(&mut self, id: RwLockId) -> bool {
         let this = self.eval_context_mut();
         if let Some(reader) = this.machine.threads.sync.rwlocks[id].reader_queue.pop_front() {
             this.unblock_thread(reader);
-            Some(reader)
+            this.rwlock_reader_lock(id, reader);
+            true
         } else {
-            None
+            false
         }
     }
 
@@ -306,13 +308,15 @@ fn rwlock_enqueue_and_block_writer(
 
     #[inline]
     /// Take the writer out the queue waiting for the lock.
-    fn rwlock_dequeue_and_unblock_writer(&mut self, id: RwLockId) -> Option<ThreadId> {
+    /// Returns `true` if some thread got the rwlock.
+    fn rwlock_dequeue_and_lock_writer(&mut self, id: RwLockId) -> bool {
         let this = self.eval_context_mut();
         if let Some(writer) = this.machine.threads.sync.rwlocks[id].writer_queue.pop_front() {
             this.unblock_thread(writer);
-            Some(writer)
+            this.rwlock_writer_lock(id, writer);
+            true
         } else {
-            None
+            false
         }
     }