@@ -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. */
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