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