diff options
author | kib <kib@FreeBSD.org> | 2013-09-29 18:02:23 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2013-09-29 18:02:23 +0000 |
commit | 632f1d29f39402167db9069d25e9bdc974b29c88 (patch) | |
tree | e521a2a30027732330389023ab5d36a15df225fc | |
parent | f093c579801a670d1ae7a75f29919c66b2adae40 (diff) | |
download | FreeBSD-src-632f1d29f39402167db9069d25e9bdc974b29c88.zip FreeBSD-src-632f1d29f39402167db9069d25e9bdc974b29c88.tar.gz |
Add LK_TRYUPGRADE operation for lockmgr(9), which attempts to
atomically upgrade shared lock to exclusive. On failure, error is
returned and lock is not dropped in the process.
Tested by: pho (previous version)
No objections from: attilio
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Approved by: re (glebius)
-rw-r--r-- | sys/kern/kern_lock.c | 13 | ||||
-rw-r--r-- | sys/sys/lockmgr.h | 1 |
2 files changed, 14 insertions, 0 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index 74a5b19..8ca8acd 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -497,6 +497,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, op = LK_EXCLUSIVE; break; case LK_UPGRADE: + case LK_TRYUPGRADE: case LK_DOWNGRADE: _lockmgr_assert(lk, KA_XLOCKED | KA_NOTRECURSED, file, line); @@ -694,6 +695,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, } break; case LK_UPGRADE: + case LK_TRYUPGRADE: _lockmgr_assert(lk, KA_SLOCKED, file, line); v = lk->lk_lock; x = v & LK_ALL_WAITERS; @@ -714,6 +716,17 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, } /* + * In LK_TRYUPGRADE mode, do not drop the lock, + * returning EBUSY instead. + */ + if (op == LK_TRYUPGRADE) { + LOCK_LOG2(lk, "%s: %p failed the nowait upgrade", + __func__, lk); + error = EBUSY; + break; + } + + /* * We have been unable to succeed in upgrading, so just * give up the shared lock. */ diff --git a/sys/sys/lockmgr.h b/sys/sys/lockmgr.h index f525a06..059de81 100644 --- a/sys/sys/lockmgr.h +++ b/sys/sys/lockmgr.h @@ -169,6 +169,7 @@ _lockmgr_args_rw(struct lock *lk, u_int flags, struct rwlock *ilk, #define LK_RELEASE 0x100000 #define LK_SHARED 0x200000 #define LK_UPGRADE 0x400000 +#define LK_TRYUPGRADE 0x800000 #define LK_TOTAL_MASK (LK_INIT_MASK | LK_EATTR_MASK | LK_TYPE_MASK) |