Module Name:    src
Committed By:   pooka
Date:           Thu May  2 21:35:19 UTC 2013

Modified Files:
        src/lib/librumpuser: rumpuser.3 rumpuser_pth.c
        src/sys/rump/include/rump: rumpuser.h
        src/sys/rump/librump/rumpkern: locks.c

Log Message:
Push rwlock upgrade and downgrade into the hypervisor where there's
at least a chance to implement them with minimal fuss.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/lib/librumpuser/rumpuser.3
cvs rdiff -u -r1.24 -r1.25 src/lib/librumpuser/rumpuser_pth.c
cvs rdiff -u -r1.101 -r1.102 src/sys/rump/include/rump/rumpuser.h
cvs rdiff -u -r1.62 -r1.63 src/sys/rump/librump/rumpkern/locks.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/librumpuser/rumpuser.3
diff -u src/lib/librumpuser/rumpuser.3:1.6 src/lib/librumpuser/rumpuser.3:1.7
--- src/lib/librumpuser/rumpuser.3:1.6	Thu May  2 19:14:59 2013
+++ src/lib/librumpuser/rumpuser.3	Thu May  2 21:35:19 2013
@@ -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,30 +561,38 @@ will never be called for that particular
 .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 void
-.Fn rumpuser_rw_exit "struct rumpuser_rw *rw"
+.Ft int
+.Fn rumpuser_rw_tryupgrade "struct rumpuser_rw *rw"
 .Pp
 .Ft void
-.Fn rumpuser_rw_destroy "struct rumpuser_rw *rw"
+.Fn rumpuser_rw_downgrade "struct rumpuser_rw *rw"
 .Pp
 .Ft void
-.Fn rumpuser_rw_held "struct rumpuser_rw *rw" "int *heldp"
+.Fn rumpuser_rw_exit "struct rumpuser_rw *rw"
 .Pp
 .Ft void
-.Fn rumpuser_rw_rdheld "struct rumpuser_rw *rw" "int *heldp"
+.Fn rumpuser_rw_destroy "struct rumpuser_rw *rw"
 .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"

Index: src/lib/librumpuser/rumpuser_pth.c
diff -u src/lib/librumpuser/rumpuser_pth.c:1.24 src/lib/librumpuser/rumpuser_pth.c:1.25
--- src/lib/librumpuser/rumpuser_pth.c:1.24	Thu May  2 20:33:54 2013
+++ src/lib/librumpuser/rumpuser_pth.c	Thu May  2 21:35:19 2013
@@ -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 *
 }
 
 void
-rumpuser_rw_held(struct rumpuser_rw *rw, int *rv)
-{
-
-	*rv = rw->readers != 0;
-}
-
-void
-rumpuser_rw_rdheld(struct rumpuser_rw *rw, int *rv)
+rumpuser_rw_held(struct rumpuser_rw *rw, const enum rumprwlock lk, 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

Index: src/sys/rump/include/rump/rumpuser.h
diff -u src/sys/rump/include/rump/rumpuser.h:1.101 src/sys/rump/include/rump/rumpuser.h:1.102
--- src/sys/rump/include/rump/rumpuser.h:1.101	Thu May  2 19:15:01 2013
+++ src/sys/rump/include/rump/rumpuser.h	Thu May  2 21:35:19 2013
@@ -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 rumpu
 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 **);

Index: src/sys/rump/librump/rumpkern/locks.c
diff -u src/sys/rump/librump/rumpkern/locks.c:1.62 src/sys/rump/librump/rumpkern/locks.c:1.63
--- src/sys/rump/librump/rumpkern/locks.c:1.62	Thu May  2 20:37:32 2013
+++ src/sys/rump/librump/rumpkern/locks.c	Thu May  2 21:35:19 2013
@@ -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 o
 {
 	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,51 +256,53 @@ 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;
+	rumpuser_rw_downgrade(RUMPRW(rw));
+	UNLOCKED(rw, 0);
+	WANTLOCK(rw, 1, false);
+	LOCKED(rw, 1);
 }
 
 int
-rw_write_held(krwlock_t *rw)
+rw_read_held(krwlock_t *rw)
 {
 	int rv;
 
-	rumpuser_rw_wrheld(RUMPRW(rw), &rv);
+	rumpuser_rw_held(RUMPRW(rw), RUMPUSER_RW_READER, &rv);
 	return rv;
 }
 
 int
-rw_read_held(krwlock_t *rw)
+rw_write_held(krwlock_t *rw)
 {
 	int rv;
 
-	rumpuser_rw_rdheld(RUMPRW(rw), &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 */

Reply via email to