rumpuser_rwlock: replace internal pthread_spin_lock (for protecting reader

count) with atomic operations.  As pthread_spin_lock is not adaptive lock, it
can have hugely negative impact if contended here, especially with priority
inversions.  Now contended rwlock(9) no longer falls flat in RUMP kernels.
This commit is contained in:
rmind 2013-09-24 23:45:16 +00:00
parent d41a00c8da
commit 72b022939e
1 changed files with 18 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpuser_pth.c,v 1.31 2013/09/23 10:35:20 pooka Exp $ */ /* $NetBSD: rumpuser_pth.c,v 1.32 2013/09/24 23:45:16 rmind Exp $ */
/* /*
* Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved. * Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved.
@ -28,10 +28,13 @@
#include "rumpuser_port.h" #include "rumpuser_port.h"
#if !defined(lint) #if !defined(lint)
__RCSID("$NetBSD: rumpuser_pth.c,v 1.31 2013/09/23 10:35:20 pooka Exp $"); __RCSID("$NetBSD: rumpuser_pth.c,v 1.32 2013/09/24 23:45:16 rmind Exp $");
#endif /* !lint */ #endif /* !lint */
#include <sys/queue.h> #include <sys/queue.h>
#if defined(__NetBSD__)
#include <sys/atomic.h>
#endif
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
@ -242,7 +245,7 @@ rumpuser_mutex_owner(struct rumpuser_mtx *mtx, struct lwp **lp)
struct rumpuser_rw { struct rumpuser_rw {
pthread_rwlock_t pthrw; pthread_rwlock_t pthrw;
pthread_spinlock_t spin; pthread_spinlock_t spin;
int readers; unsigned int readers;
struct lwp *writer; struct lwp *writer;
int downgrade; /* someone is downgrading (hopefully lock holder ;) */ int downgrade; /* someone is downgrading (hopefully lock holder ;) */
}; };
@ -251,14 +254,15 @@ static int
rw_amwriter(struct rumpuser_rw *rw) rw_amwriter(struct rumpuser_rw *rw)
{ {
return rw->writer == rumpuser_curlwp() && rw->readers == -1; return rw->writer == rumpuser_curlwp() && rw->readers == (unsigned)-1;
} }
static int static int
rw_nreaders(struct rumpuser_rw *rw) rw_nreaders(struct rumpuser_rw *rw)
{ {
unsigned nreaders = rw->readers;
return rw->readers > 0 ? rw->readers : 0; return nreaders != (unsigned)-1 ? nreaders : 0;
} }
static int static int
@ -283,7 +287,7 @@ rw_setwriter(struct rumpuser_rw *rw, int retry)
} }
assert(rw->readers == 0); assert(rw->readers == 0);
rw->writer = rumpuser_curlwp(); rw->writer = rumpuser_curlwp();
rw->readers = -1; rw->readers = (unsigned)-1;
return 0; return 0;
} }
@ -300,20 +304,27 @@ static void
rw_readup(struct rumpuser_rw *rw) rw_readup(struct rumpuser_rw *rw)
{ {
#if defined(__NetBSD__)
atomic_inc_uint(&rw->readers);
#else
pthread_spin_lock(&rw->spin); pthread_spin_lock(&rw->spin);
assert(rw->readers >= 0);
++rw->readers; ++rw->readers;
pthread_spin_unlock(&rw->spin); pthread_spin_unlock(&rw->spin);
#endif
} }
static void static void
rw_readdown(struct rumpuser_rw *rw) rw_readdown(struct rumpuser_rw *rw)
{ {
#if defined(__NetBSD__)
atomic_dec_uint(&rw->readers);
#else
pthread_spin_lock(&rw->spin); pthread_spin_lock(&rw->spin);
assert(rw->readers > 0); assert(rw->readers > 0);
--rw->readers; --rw->readers;
pthread_spin_unlock(&rw->spin); pthread_spin_unlock(&rw->spin);
#endif
} }
void void