Change the implementation of these functions to use an actual reader/writer lock, allowing multiple simultaneous readers.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- linux-user/mmap.c | 52 ++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 21 deletions(-) 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. */ -- 2.17.1