svn commit: r330689 - head/sys/compat/linuxkpi/common/src

Hans Petter Selasky hselasky at FreeBSD.org
Fri Mar 9 12:16:56 UTC 2018


Author: hselasky
Date: Fri Mar  9 12:16:55 2018
New Revision: 330689
URL: https://svnweb.freebsd.org/changeset/base/330689

Log:
  Implement proper support for complete_all() in the LinuxKPI.
  
  When complete_all() is called there might be multiple waiters. The
  current implementation could only handle one waiter. Make sure the
  completion is sticky when complete_all() is called to be compatible
  with Linux.
  
  Found by:	Johannes Lundberg <johalun0 at gmail.com>
  MFC after:	1 week
  Sponsored by:	Mellanox Technologies
  Sponsored by:	Limelight Networks

Modified:
  head/sys/compat/linuxkpi/common/src/linux_compat.c

Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c	Fri Mar  9 11:33:56 2018	(r330688)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c	Fri Mar  9 12:16:55 2018	(r330689)
@@ -1779,11 +1779,14 @@ linux_complete_common(struct completion *c, int all)
 	int wakeup_swapper;
 
 	sleepq_lock(c);
-	c->done++;
-	if (all)
+	if (all) {
+		c->done = UINT_MAX;
 		wakeup_swapper = sleepq_broadcast(c, SLEEPQ_SLEEP, 0, 0);
-	else
+	} else {
+		if (c->done != UINT_MAX)
+			c->done++;
 		wakeup_swapper = sleepq_signal(c, SLEEPQ_SLEEP, 0, 0);
+	}
 	sleepq_release(c);
 	if (wakeup_swapper)
 		kick_proc0();
@@ -1825,7 +1828,8 @@ linux_wait_for_common(struct completion *c, int flags)
 		} else
 			sleepq_wait(c, 0);
 	}
-	c->done--;
+	if (c->done != UINT_MAX)
+		c->done--;
 	sleepq_release(c);
 
 intr:
@@ -1878,7 +1882,8 @@ linux_wait_for_timeout_common(struct completion *c, in
 			goto done;
 		}
 	}
-	c->done--;
+	if (c->done != UINT_MAX)
+		c->done--;
 	sleepq_release(c);
 
 	/* return how many jiffies are left */
@@ -1894,12 +1899,10 @@ linux_try_wait_for_completion(struct completion *c)
 {
 	int isdone;
 
-	isdone = 1;
 	sleepq_lock(c);
-	if (c->done)
+	isdone = (c->done != 0);
+	if (c->done != 0 && c->done != UINT_MAX)
 		c->done--;
-	else
-		isdone = 0;
 	sleepq_release(c);
 	return (isdone);
 }
@@ -1909,10 +1912,8 @@ linux_completion_done(struct completion *c)
 {
 	int isdone;
 
-	isdone = 1;
 	sleepq_lock(c);
-	if (c->done == 0)
-		isdone = 0;
+	isdone = (c->done != 0);
 	sleepq_release(c);
 	return (isdone);
 }


More information about the svn-src-all mailing list