From 209ad55c2157201aa3ccd0b451ac33a91d3964ce Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Fri, 20 Jul 2018 18:03:37 +0200
Subject: [PATCH] Add lockmgr_try() to port FreeBSD's mtx_trylock and Linux'
 mutex_trylock().

---
 doc/porting_drivers.txt                    |  2 +-
 share/man/man9/Makefile                    |  1 +
 share/man/man9/lock.9                      | 11 ++++++++++-
 sys/dev/drm/include/linux/mutex.h          |  3 +--
 sys/dev/raid/arcmsr/arcmsr.h               |  2 +-
 sys/dev/sound/pcm/channel.h                |  4 ++--
 sys/dev/sound/pcm/sound.h                  |  2 +-
 sys/dev/virtual/vmware/vmxnet3/if_vmxvar.h |  2 +-
 sys/sys/lock.h                             | 11 +++++++++++
 9 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/doc/porting_drivers.txt b/doc/porting_drivers.txt
index e9757b9b5b..f1ca49c492 100644
--- a/doc/porting_drivers.txt
+++ b/doc/porting_drivers.txt
@@ -82,7 +82,7 @@
   An
 	mtx_trylock(&my_mtx);
   call is replaced with
-	lockmgr(&my_lock, LK_EXCLUSIVE|LK_NOWAIT);
+	lockmgr_try(&my_lock, LK_EXCLUSIVE);
 
   As for mtx_assert() calls, translate them like this:
 
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index 5932b1a811..0514cf4849 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -629,6 +629,7 @@ MLINKS+=kether_ntoa.9 kether_aton.9
 MLINKS+=lock.9 lockinit.9 \
 	lock.9 lockmgr.9 \
 	lock.9 lockmgr_printinfo.9 \
+	lock.9 lockmgr_try.9 \
 	lock.9 lockowned.9 \
 	lock.9 lockstatus.9 \
 	lock.9 lockuninit.9
diff --git a/share/man/man9/lock.9 b/share/man/man9/lock.9
index fe244dfa6e..9362a46b78 100644
--- a/share/man/man9/lock.9
+++ b/share/man/man9/lock.9
@@ -26,12 +26,13 @@
 .\"
 .\" $FreeBSD: src/share/man/man9/lock.9,v 1.11 2003/09/08 19:57:21 ru Exp $
 .\"
-.Dd November 25, 2017
+.Dd July 20, 2018
 .Dt LOCK 9
 .Os
 .Sh NAME
 .Nm lockinit ,
 .Nm lockmgr ,
+.Nm lockmgr_try ,
 .Nm lockstatus ,
 .Nm lockmgr_printinfo ,
 .Nm lockowned
@@ -45,6 +46,8 @@
 .Fn lockuninit "struct lock *lkp"
 .Ft int
 .Fn lockmgr "struct lock *lkp" "u_int flags"
+.Ft boolean_t
+.Fn lockmgr_try "struct lock *lkp" "u_int flags"
 .Ft int
 .Fn lockstatus "struct lock *lkp" "struct thread *td"
 .Ft void
@@ -154,6 +157,12 @@ For every lock there must be a release.
 .El
 .Pp
 The
+.Fn lockmgr_try
+function tries to acquire a lock and returns
+.Dv true
+upon success.
+.Pp
+The
 .Fn lockstatus
 function returns the status of the lock in relation to the
 .Vt thread
diff --git a/sys/dev/drm/include/linux/mutex.h b/sys/dev/drm/include/linux/mutex.h
index 320b77f30b..a9dab77e24 100644
--- a/sys/dev/drm/include/linux/mutex.h
+++ b/sys/dev/drm/include/linux/mutex.h
@@ -37,8 +37,7 @@
 #define mutex_lock(lock)	lockmgr(lock, LK_EXCLUSIVE)
 #define mutex_unlock(lock)	lockmgr(lock, LK_RELEASE)
 
-/* NOTE: mutex_trylock() returns non-zero on success */
-#define mutex_trylock(lock)	(!lockmgr(lock, LK_EXCLUSIVE|LK_NOWAIT))
+#define mutex_trylock(lock)	lockmgr_try(lock, LK_EXCLUSIVE)
 
 static inline int
 mutex_lock_interruptible(struct lock *lock)
diff --git a/sys/dev/raid/arcmsr/arcmsr.h b/sys/dev/raid/arcmsr/arcmsr.h
index 1b90b99528..5140e6b7e3 100644
--- a/sys/dev/raid/arcmsr/arcmsr.h
+++ b/sys/dev/raid/arcmsr/arcmsr.h
@@ -74,7 +74,7 @@
 #define ARCMSR_LOCK_DESTROY(l)	lockuninit(l)
 #define ARCMSR_LOCK_ACQUIRE(l)	lockmgr(l, LK_EXCLUSIVE)
 #define ARCMSR_LOCK_RELEASE(l)	lockmgr(l, LK_RELEASE)
-#define ARCMSR_LOCK_TRY(l)	lockmgr(&l, LK_EXCLUSIVE|LK_NOWAIT)
+#define ARCMSR_LOCK_TRY(l)	lockmgr_try(l, LK_EXCLUSIVE)
 #define arcmsr_htole32(x)	htole32(x)
 typedef struct lock		arcmsr_lock_t;
 
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index bb78d53303..c1f9a272db 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -54,7 +54,7 @@ extern struct lock snd_pcm_syncgroups_mtx;
 extern SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups;
 
 #define PCM_SG_LOCK()	    lockmgr(&snd_pcm_syncgroups_mtx, LK_EXCLUSIVE)
-#define PCM_SG_TRYLOCK()    mtx_trylock(&snd_pcm_syncgroups_mtx)
+#define PCM_SG_TRYLOCK()    lockmgr_try(&snd_pcm_syncgroups_mtx, LK_EXCLUSIVE)
 #define PCM_SG_UNLOCK()	    lockmgr(&snd_pcm_syncgroups_mtx, LK_RELEASE)
 #define PCM_SG_ASSERTOWNED     KKASSERT(lockstatus(&snd_pcm_syncgroups_mtx, curthread) == LK_EXCLUSIVE)
 #define PCM_SG_ASSERTNOTOWNED  KKASSERT(lockstatus(&snd_pcm_syncgroups_mtx, curthread) != LK_EXCLUSIVE)
@@ -312,7 +312,7 @@ int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
 #define CHN_LOCKOWNED(c)	(lockstatus((c)->lock, curthread) == LK_EXCLUSIVE)
 #define CHN_LOCK(c)		lockmgr((c)->lock, LK_EXCLUSIVE)
 #define CHN_UNLOCK(c)		lockmgr((c)->lock, LK_RELEASE)
-#define CHN_TRYLOCK(c)		lockmgr((c)->lock, LK_EXCLUSIVE|LK_NOWAIT)
+#define CHN_TRYLOCK(c)		lockmgr_try((c)->lock, LK_EXCLUSIVE)
 #define CHN_LOCKASSERT(c)	KKASSERT(lockstatus((c)->lock, curthread) == LK_EXCLUSIVE)
 #define CHN_UNLOCKASSERT(c)	KKASSERT(lockstatus((c)->lock, curthread) != LK_EXCLUSIVE)
 
diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h
index 770ebdc33b..6c46fee7c1 100644
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -434,7 +434,7 @@ int	sound_oss_card_info(oss_card_info *);
 #define PCM_LOCKOWNED(d)	(lockstatus((d)->lock, curthread) == LK_EXCLUSIVE)
 #define PCM_LOCK(d)		lockmgr((d)->lock, LK_EXCLUSIVE)
 #define PCM_UNLOCK(d)		lockmgr((d)->lock, LK_RELEASE)
-#define PCM_TRYLOCK(d)		lockmgr((d)->lock, LK_EXCLUSIVE|LK_NOWAIT)
+#define PCM_TRYLOCK(d)		lockmgr_try((d)->lock, LK_EXCLUSIVE)
 #define PCM_LOCKASSERT(d)	KKASSERT(lockstatus((d)->lock, curthread) == LK_EXCLUSIVE)
 #define PCM_UNLOCKASSERT(d)	KKASSERT(lockstatus((d)->lock, curthread) != LK_EXCLUSIVE)
 
diff --git a/sys/dev/virtual/vmware/vmxnet3/if_vmxvar.h b/sys/dev/virtual/vmware/vmxnet3/if_vmxvar.h
index 03695c82cc..9f32d564d4 100644
--- a/sys/dev/virtual/vmware/vmxnet3/if_vmxvar.h
+++ b/sys/dev/virtual/vmware/vmxnet3/if_vmxvar.h
@@ -149,7 +149,7 @@ struct vmxnet3_txqueue {
 } __cachealign;
 
 #define VMXNET3_TXQ_LOCK(_txq)		lockmgr(&(_txq)->vxtxq_lock, LK_EXCLUSIVE)
-#define VMXNET3_TXQ_TRYLOCK(_txq)	mtx_trylock(&(_txq)->vxtxq_mtx)
+#define VMXNET3_TXQ_TRYLOCK(_txq)	lockmgr_try(&(_txq)->vxtxq_lock, LK_EXCLUSIVE)
 #define VMXNET3_TXQ_UNLOCK(_txq)	lockmgr(&(_txq)->vxtxq_lock, LK_RELEASE)
 #define VMXNET3_TXQ_LOCK_ASSERT(_txq)		\
     KKASSERT(lockowned(&(_txq)->vxtxq_lock) != 0)
diff --git a/sys/sys/lock.h b/sys/sys/lock.h
index 299e5c5fa2..ac14020842 100644
--- a/sys/sys/lock.h
+++ b/sys/sys/lock.h
@@ -299,6 +299,17 @@ lockinuse(struct lock *lkp)
 	return ((lkp->lk_count & (LKC_SMASK | LKC_XMASK)) != 0);
 }
 
+/*
+ * Returns true if the lock was acquired. Used mainly to port mtx_trylock()
+ * from FreeBSD.
+ */
+static __inline
+boolean_t
+lockmgr_try(struct lock *lkp, u_int flags)
+{
+	return (lockmgr(lkp, flags | LK_NOWAIT) == 0);
+}
+
 #endif /* _KERNEL */
 #endif /* _KERNEL || _KERNEL_STRUCTURES */
 #endif /* _SYS_LOCK_H_ */
-- 
2.17.1

