Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Push rwlock upgrade and downgrade into the hypervisor where ...



details:   https://anonhg.NetBSD.org/src/rev/0d1002f7928d
branches:  trunk
changeset: 786589:0d1002f7928d
user:      pooka <pooka%NetBSD.org@localhost>
date:      Thu May 02 21:35:19 2013 +0000

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

diffstat:

 lib/librumpuser/rumpuser.3        |  36 +++++++++++-------
 lib/librumpuser/rumpuser_pth.c    |  73 ++++++++++++++++++++++++++------------
 sys/rump/include/rump/rumpuser.h  |  13 +++---
 sys/rump/librump/rumpkern/locks.c |  66 +++++++++++++++++++++-------------
 4 files changed, 119 insertions(+), 69 deletions(-)

diffs (truncated from 353 to 300 lines):

diff -r 8045e6cf0025 -r 0d1002f7928d lib/librumpuser/rumpuser.3
--- a/lib/librumpuser/rumpuser.3        Thu May 02 21:11:18 2013 +0000
+++ b/lib/librumpuser/rumpuser.3        Thu May 02 21:35:19 2013 +0000
@@ -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 @@
 .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 @@
 .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"
+.Fo rumpuser_rw_held
+.Fa "struct rumpuser_rw *rw" "const enum rumprwlock lk" "int *heldp"
+.Fc
 .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.
-.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"
diff -r 8045e6cf0025 -r 0d1002f7928d lib/librumpuser/rumpuser_pth.c
--- a/lib/librumpuser/rumpuser_pth.c    Thu May 02 21:11:18 2013 +0000
+++ b/lib/librumpuser/rumpuser_pth.c    Thu May 02 21:35:19 2013 +0000
@@ -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 @@
 }
 
 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 @@
 }
 
 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
diff -r 8045e6cf0025 -r 0d1002f7928d sys/rump/include/rump/rumpuser.h
--- a/sys/rump/include/rump/rumpuser.h  Thu May 02 21:11:18 2013 +0000
+++ b/sys/rump/include/rump/rumpuser.h  Thu May 02 21:35:19 2013 +0000
@@ -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_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 **);
diff -r 8045e6cf0025 -r 0d1002f7928d sys/rump/librump/rumpkern/locks.c
--- a/sys/rump/librump/rumpkern/locks.c Thu May 02 21:11:18 2013 +0000
+++ b/sys/rump/librump/rumpkern/locks.c Thu May 02 21:35:19 2013 +0000
@@ -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 @@
 
 /* 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 @@
 
 
        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 @@
 {
        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,24 +256,37 @@
        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)



Home | Main Index | Thread Index | Old Index