Push rwlock upgrade and downgrade into the hypervisor where there's
at least a chance to implement them with minimal fuss.
This commit is contained in:
parent
5d1d1ac212
commit
f950fd3d52
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: rumpuser.3,v 1.6 2013/05/02 19:14:59 pooka Exp $
|
||||
.\" $NetBSD: rumpuser.3,v 1.7 2013/05/02 21:35:19 pooka Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2013 Antti Kantee. All rights reserved.
|
||||
.\"
|
||||
|
@ -561,10 +561,16 @@ will never be called for that particular mutex.
|
|||
.Fn rumpuser_rw_init "struct rumpuser_rw **rwp"
|
||||
.Pp
|
||||
.Ft void
|
||||
.Fn rumpuser_rw_enter "struct rumpuser_rw *rw" "int writelock"
|
||||
.Fn rumpuser_rw_enter "struct rumpuser_rw *rw" "const enum rumprwlock lk"
|
||||
.Pp
|
||||
.Ft int
|
||||
.Fn rumpuser_rw_tryenter "struct rumpuser_rw *rw" "int writelock"
|
||||
.Fn rumpuser_rw_tryenter "struct rumpuser_rw *rw" "const enum rumprwlock lk"
|
||||
.Pp
|
||||
.Ft int
|
||||
.Fn rumpuser_rw_tryupgrade "struct rumpuser_rw *rw"
|
||||
.Pp
|
||||
.Ft void
|
||||
.Fn rumpuser_rw_downgrade "struct rumpuser_rw *rw"
|
||||
.Pp
|
||||
.Ft void
|
||||
.Fn rumpuser_rw_exit "struct rumpuser_rw *rw"
|
||||
|
@ -573,18 +579,20 @@ will never be called for that particular mutex.
|
|||
.Fn rumpuser_rw_destroy "struct rumpuser_rw *rw"
|
||||
.Pp
|
||||
.Ft void
|
||||
.Fn rumpuser_rw_held "struct rumpuser_rw *rw" "int *heldp"
|
||||
.Pp
|
||||
.Ft void
|
||||
.Fn rumpuser_rw_rdheld "struct rumpuser_rw *rw" "int *heldp"
|
||||
.Pp
|
||||
.Ft void
|
||||
.Fn rumpuser_rw_wrheld "struct rumpuser_rw *rw" "int *heldp"
|
||||
.Pp
|
||||
Read/write locks acquire an exclusive version of the lock if the
|
||||
.Fa writelock
|
||||
parameter is non-zero and a shared lock otherwise.
|
||||
.Fo rumpuser_rw_held
|
||||
.Fa "struct rumpuser_rw *rw" "const enum rumprwlock lk" "int *heldp"
|
||||
.Fc
|
||||
.Pp
|
||||
Read/write locks provide either shared or exclusive locking.
|
||||
The possible values for
|
||||
.Fa lk
|
||||
are
|
||||
.Dv RUMPUSER_RW_READER
|
||||
and
|
||||
.Dv RUMPUSER_RW_WRITER .
|
||||
Upgrading means trying to migrate from an already owned shared
|
||||
lock to an exclusive lock and downgrading means migrating from
|
||||
an already owned exclusive lock to a shared lock.
|
||||
.Pp
|
||||
.Ft void
|
||||
.Fn rumpuser_cv_init "struct rumpuser_cv **cvp"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rumpuser_pth.c,v 1.24 2013/05/02 20:33:54 pooka Exp $ */
|
||||
/* $NetBSD: rumpuser_pth.c,v 1.25 2013/05/02 21:35:19 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved.
|
||||
|
@ -28,7 +28,7 @@
|
|||
#include "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_pth.c,v 1.24 2013/05/02 20:33:54 pooka Exp $");
|
||||
__RCSID("$NetBSD: rumpuser_pth.c,v 1.25 2013/05/02 21:35:19 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
@ -286,40 +286,72 @@ rumpuser_rw_init(struct rumpuser_rw **rw)
|
|||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_enter(struct rumpuser_rw *rw, int iswrite)
|
||||
rumpuser_rw_enter(struct rumpuser_rw *rw, const enum rumprwlock lk)
|
||||
{
|
||||
|
||||
if (iswrite) {
|
||||
switch (lk) {
|
||||
case RUMPUSER_RW_WRITER:
|
||||
if (pthread_rwlock_trywrlock(&rw->pthrw) != 0)
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(
|
||||
pthread_rwlock_wrlock(&rw->pthrw)));
|
||||
RURW_SETWRITE(rw);
|
||||
} else {
|
||||
break;
|
||||
case RUMPUSER_RW_READER:
|
||||
if (pthread_rwlock_tryrdlock(&rw->pthrw) != 0)
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(
|
||||
pthread_rwlock_rdlock(&rw->pthrw)));
|
||||
RURW_INCREAD(rw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_tryenter(struct rumpuser_rw *rw, int iswrite)
|
||||
rumpuser_rw_tryenter(struct rumpuser_rw *rw, const enum rumprwlock lk)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (iswrite) {
|
||||
switch (lk) {
|
||||
case RUMPUSER_RW_WRITER:
|
||||
rv = pthread_rwlock_trywrlock(&rw->pthrw);
|
||||
if (rv == 0)
|
||||
RURW_SETWRITE(rw);
|
||||
} else {
|
||||
break;
|
||||
case RUMPUSER_RW_READER:
|
||||
rv = pthread_rwlock_tryrdlock(&rw->pthrw);
|
||||
if (rv == 0)
|
||||
RURW_INCREAD(rw);
|
||||
break;
|
||||
default:
|
||||
rv = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_tryupgrade(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
/* not supported by pthreads */
|
||||
ET(EBUSY);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_downgrade(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
/*
|
||||
* I guess this is not strictly speaking correct,
|
||||
* but the option is to provide a complete implementation
|
||||
* of rwlocks here, or at least wrap acquiry in 1) lock
|
||||
* 2) check if someone is downgrading. if not, we're done
|
||||
* 3) unlock 4) yield 5) goto 1.
|
||||
*/
|
||||
rumpuser_rw_exit(rw);
|
||||
rumpuser_rw_enter(rw, RUMPUSER_RW_READER);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_exit(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
@ -341,24 +373,17 @@ rumpuser_rw_destroy(struct rumpuser_rw *rw)
|
|||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_held(struct rumpuser_rw *rw, int *rv)
|
||||
rumpuser_rw_held(struct rumpuser_rw *rw, const enum rumprwlock lk, int *rv)
|
||||
{
|
||||
|
||||
*rv = rw->readers != 0;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_rdheld(struct rumpuser_rw *rw, int *rv)
|
||||
{
|
||||
|
||||
*rv = RURW_HASREAD(rw);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_wrheld(struct rumpuser_rw *rw, int *rv)
|
||||
{
|
||||
|
||||
*rv = RURW_AMWRITER(rw);
|
||||
switch (lk) {
|
||||
case RUMPUSER_RW_WRITER:
|
||||
*rv = RURW_AMWRITER(rw);
|
||||
break;
|
||||
case RUMPUSER_RW_READER:
|
||||
*rv = RURW_HASREAD(rw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rumpuser.h,v 1.101 2013/05/02 19:15:01 pooka Exp $ */
|
||||
/* $NetBSD: rumpuser.h,v 1.102 2013/05/02 21:35:19 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2013 Antti Kantee. All Rights Reserved.
|
||||
|
@ -180,14 +180,15 @@ void rumpuser_mutex_destroy(struct rumpuser_mtx *);
|
|||
void rumpuser_mutex_owner(struct rumpuser_mtx *, struct lwp **);
|
||||
|
||||
struct rumpuser_rw;
|
||||
enum rumprwlock { RUMPUSER_RW_READER, RUMPUSER_RW_WRITER };
|
||||
void rumpuser_rw_init(struct rumpuser_rw **);
|
||||
void rumpuser_rw_enter(struct rumpuser_rw *, int);
|
||||
int rumpuser_rw_tryenter(struct rumpuser_rw *, int);
|
||||
void rumpuser_rw_enter(struct rumpuser_rw *, const enum rumprwlock);
|
||||
int rumpuser_rw_tryenter(struct rumpuser_rw *, const enum rumprwlock);
|
||||
int rumpuser_rw_tryupgrade(struct rumpuser_rw *);
|
||||
void rumpuser_rw_downgrade(struct rumpuser_rw *);
|
||||
void rumpuser_rw_exit(struct rumpuser_rw *);
|
||||
void rumpuser_rw_destroy(struct rumpuser_rw *);
|
||||
void rumpuser_rw_held(struct rumpuser_rw *, int *);
|
||||
void rumpuser_rw_rdheld(struct rumpuser_rw *, int *);
|
||||
void rumpuser_rw_wrheld(struct rumpuser_rw *, int *);
|
||||
void rumpuser_rw_held(struct rumpuser_rw *, const enum rumprwlock, int *);
|
||||
|
||||
struct rumpuser_cv;
|
||||
void rumpuser_cv_init(struct rumpuser_cv **);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: locks.c,v 1.62 2013/05/02 20:37:32 pooka Exp $ */
|
||||
/* $NetBSD: locks.c,v 1.63 2013/05/02 21:35:19 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2011 Antti Kantee. All Rights Reserved.
|
||||
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: locks.c,v 1.62 2013/05/02 20:37:32 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: locks.c,v 1.63 2013/05/02 21:35:19 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kmem.h>
|
||||
|
@ -187,6 +187,20 @@ mutex_owner(kmutex_t *mtx)
|
|||
|
||||
/* reader/writer locks */
|
||||
|
||||
static enum rumprwlock
|
||||
krw2rumprw(const krw_t op)
|
||||
{
|
||||
|
||||
switch (op) {
|
||||
case RW_READER:
|
||||
return RUMPUSER_RW_READER;
|
||||
case RW_WRITER:
|
||||
return RUMPUSER_RW_WRITER;
|
||||
default:
|
||||
panic("unknown rwlock type");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rw_init(krwlock_t *rw)
|
||||
{
|
||||
|
@ -211,7 +225,7 @@ rw_enter(krwlock_t *rw, const krw_t op)
|
|||
|
||||
|
||||
WANTLOCK(rw, op == RW_READER, false);
|
||||
rumpuser_rw_enter(RUMPRW(rw), op == RW_WRITER);
|
||||
rumpuser_rw_enter(RUMPRW(rw), krw2rumprw(op));
|
||||
LOCKED(rw, op == RW_READER);
|
||||
}
|
||||
|
||||
|
@ -220,7 +234,7 @@ rw_tryenter(krwlock_t *rw, const krw_t op)
|
|||
{
|
||||
int error;
|
||||
|
||||
error = rumpuser_rw_tryenter(RUMPRW(rw), op == RW_WRITER);
|
||||
error = rumpuser_rw_tryenter(RUMPRW(rw), krw2rumprw(op));
|
||||
if (error == 0) {
|
||||
WANTLOCK(rw, op == RW_READER, true);
|
||||
LOCKED(rw, op == RW_READER);
|
||||
|
@ -242,33 +256,28 @@ rw_exit(krwlock_t *rw)
|
|||
rumpuser_rw_exit(RUMPRW(rw));
|
||||
}
|
||||
|
||||
/* always fails */
|
||||
int
|
||||
rw_tryupgrade(krwlock_t *rw)
|
||||
{
|
||||
int rv;
|
||||
|
||||
return 0;
|
||||
rv = rumpuser_rw_tryupgrade(RUMPRW(rw));
|
||||
if (rv == 0) {
|
||||
UNLOCKED(rw, 1);
|
||||
WANTLOCK(rw, 0, true);
|
||||
LOCKED(rw, 0);
|
||||
}
|
||||
return rv == 0;
|
||||
}
|
||||
|
||||
void
|
||||
rw_downgrade(krwlock_t *rw)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX HACK: How we can downgrade re lock in rump properly.
|
||||
*/
|
||||
rw_exit(rw);
|
||||
rw_enter(rw, RW_READER);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
rw_write_held(krwlock_t *rw)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rumpuser_rw_wrheld(RUMPRW(rw), &rv);
|
||||
return rv;
|
||||
rumpuser_rw_downgrade(RUMPRW(rw));
|
||||
UNLOCKED(rw, 0);
|
||||
WANTLOCK(rw, 1, false);
|
||||
LOCKED(rw, 1);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -276,17 +285,24 @@ rw_read_held(krwlock_t *rw)
|
|||
{
|
||||
int rv;
|
||||
|
||||
rumpuser_rw_rdheld(RUMPRW(rw), &rv);
|
||||
rumpuser_rw_held(RUMPRW(rw), RUMPUSER_RW_READER, &rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
rw_write_held(krwlock_t *rw)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rumpuser_rw_held(RUMPRW(rw), RUMPUSER_RW_WRITER, &rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
rw_lock_held(krwlock_t *rw)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rumpuser_rw_held(RUMPRW(rw), &rv);
|
||||
return rv;
|
||||
return rw_read_held(rw) || rw_write_held(rw);
|
||||
}
|
||||
|
||||
/* curriculum vitaes */
|
||||
|
|
Loading…
Reference in New Issue