Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Jan 2020 18:18:17 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356885 - in head/sys: kern sys
Message-ID:  <202001191818.00JIIHOv049443@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jeff
Date: Sun Jan 19 18:18:17 2020
New Revision: 356885
URL: https://svnweb.freebsd.org/changeset/base/356885

Log:
  Provide an API for interlocked refcount sleeps.
  
  Reviewed by:	kib, markj
  Differential Revision:	https://reviews.freebsd.org/D22908

Modified:
  head/sys/kern/kern_synch.c
  head/sys/sys/refcount.h

Modified: head/sys/kern/kern_synch.c
==============================================================================
--- head/sys/kern/kern_synch.c	Sun Jan 19 17:47:04 2020	(r356884)
+++ head/sys/kern/kern_synch.c	Sun Jan 19 18:18:17 2020	(r356885)
@@ -381,15 +381,21 @@ refcount_release_last(volatile u_int *count, u_int n, 
  * a precise answer should use refcount_wait().
  */
 void
-refcount_sleep(volatile u_int *count, const char *wmesg, int pri)
+_refcount_sleep(volatile u_int *count, struct lock_object *lock,
+    const char *wmesg, int pri)
 {
 	void *wchan;
 	u_int old;
 
-	if (REFCOUNT_COUNT(*count) == 0)
+	if (REFCOUNT_COUNT(*count) == 0) {
+		if (lock != NULL)
+			LOCK_CLASS(lock)->lc_unlock(lock);
 		return;
+	}
 	wchan = __DEVOLATILE(void *, count);
 	sleepq_lock(wchan);
+	if (lock != NULL)
+		LOCK_CLASS(lock)->lc_unlock(lock);
 	old = *count;
 	for (;;) {
 		if (REFCOUNT_COUNT(old) == 0) {

Modified: head/sys/sys/refcount.h
==============================================================================
--- head/sys/sys/refcount.h	Sun Jan 19 17:47:04 2020	(r356884)
+++ head/sys/sys/refcount.h	Sun Jan 19 18:18:17 2020	(r356885)
@@ -46,7 +46,6 @@
 #define	REFCOUNT_COUNT(x)		((x) & ~REFCOUNT_WAITER)
 
 bool refcount_release_last(volatile u_int *count, u_int n, u_int old);
-void refcount_sleep(volatile u_int *count, const char *wmesg, int prio);
 
 /*
  * Attempt to handle reference count overflow and underflow.  Force the counter
@@ -135,13 +134,29 @@ refcount_release(volatile u_int *count)
 	return (refcount_releasen(count, 1));
 }
 
+#ifdef _KERNEL
+struct lock_object;
+void _refcount_sleep(volatile u_int *count, struct lock_object *,
+    const char *wmesg, int prio);
+
 static __inline void
+refcount_sleep(volatile u_int *count, const char *wmesg, int prio)
+{
+
+	_refcount_sleep(count, NULL, wmesg, prio);
+}
+
+#define	refcount_sleep_interlock(count, lock, wmesg, prio)		\
+	_refcount_sleep((count), (struct lock_object *)(lock), (wmesg), (prio))
+
+static __inline void
 refcount_wait(volatile u_int *count, const char *wmesg, int prio)
 {
 
 	while (*count != 0)
 		refcount_sleep(count, wmesg, prio);
 }
+#endif
 
 /*
  * This functions returns non-zero if the refcount was



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202001191818.00JIIHOv049443>