diff mbox series

[2/2] linux-user: Use pthread_rwlock_t for mmap_rd/wrlock

Message ID 20180621173635.21537-3-richard.henderson@linaro.org
State New
Headers show
Series linux-user: Change mmap_lock to rwlock | expand

Commit Message

Richard Henderson June 21, 2018, 5:36 p.m. UTC
Change the implementation of these functions to use an actual
reader/writer lock, allowing multiple simultaneous readers.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 linux-user/mmap.c | 52 ++++++++++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 21 deletions(-)

-- 
2.17.1

Comments

Emilio Cota June 22, 2018, 9:13 p.m. UTC | #1
On Thu, Jun 21, 2018 at 07:36:35 -1000, Richard Henderson wrote:
>  void mmap_wrlock(void)

>  {

> -    mmap_lock_internal();

> +    if (likely(mmap_lock_held == 0)) {

> +        pthread_rwlock_rdlock(&mmap_rwlock);


s/rwlock_rdlock/rwlock_wrlock/

		E.
diff mbox series

Patch

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 71b6bed5e2..2dc133515a 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -24,52 +24,62 @@ 
 
 //#define DEBUG_MMAP
 
-static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
-static __thread int mmap_lock_count;
-
-static void mmap_lock_internal(void)
-{
-    if (mmap_lock_count++ == 0) {
-        pthread_mutex_lock(&mmap_mutex);
-    }
-}
+static pthread_rwlock_t mmap_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+/* Bit 0 indicates reading; bit 1 indicates writing; bits 2+ are count-1.  */
+static __thread int mmap_lock_held;
 
 void mmap_rdlock(void)
 {
-    mmap_lock_internal();
+    if (likely(mmap_lock_held == 0)) {
+        pthread_rwlock_rdlock(&mmap_rwlock);
+        mmap_lock_held = 1;
+    } else {
+        /* can read-lock when write-lock held */
+        mmap_lock_held += 4;
+    }
 }
 
 void mmap_wrlock(void)
 {
-    mmap_lock_internal();
+    if (likely(mmap_lock_held == 0)) {
+        pthread_rwlock_rdlock(&mmap_rwlock);
+        mmap_lock_held = 2;
+    } else {
+        /* cannot upgrade a read-lock to a write-lock */
+        assert((mmap_lock_held & 1) == 0);
+        mmap_lock_held += 4;
+    }
 }
 
 void mmap_unlock(void)
 {
-    if (--mmap_lock_count == 0) {
-        pthread_mutex_unlock(&mmap_mutex);
+    assert(mmap_lock_held > 0);
+    mmap_lock_held -= 4;
+    if (mmap_lock_held < 0) {
+        mmap_lock_held = 0;
+        pthread_rwlock_unlock(&mmap_rwlock);
     }
 }
 
 bool have_mmap_lock(void)
 {
-    return mmap_lock_count > 0 ? true : false;
+    return mmap_lock_held != 0;
 }
 
 /* Grab lock to make sure things are in a consistent state after fork().  */
 void mmap_fork_start(void)
 {
-    if (mmap_lock_count)
-        abort();
-    pthread_mutex_lock(&mmap_mutex);
+    assert(mmap_lock_held == 0);
+    pthread_rwlock_wrlock(&mmap_rwlock);
 }
 
 void mmap_fork_end(int child)
 {
-    if (child)
-        pthread_mutex_init(&mmap_mutex, NULL);
-    else
-        pthread_mutex_unlock(&mmap_mutex);
+    if (child) {
+        pthread_rwlock_init(&mmap_rwlock, NULL);
+    } else {
+        pthread_rwlock_unlock(&mmap_rwlock);
+    }
 }
 
 /* NOTE: all the constants are the HOST ones, but addresses are target. */