Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Mar 2018 16:33:41 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r330865 - stable/11/sys/compat/linuxkpi/common/src
Message-ID:  <201803131633.w2DGXfA5010572@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Tue Mar 13 16:33:41 2018
New Revision: 330865
URL: https://svnweb.freebsd.org/changeset/base/330865

Log:
  MFC r330689:
  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@gmail.com>
  Sponsored by:	Mellanox Technologies
  Sponsored by:	Limelight Networks

Modified:
  stable/11/sys/compat/linuxkpi/common/src/linux_compat.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- stable/11/sys/compat/linuxkpi/common/src/linux_compat.c	Tue Mar 13 16:33:00 2018	(r330864)
+++ stable/11/sys/compat/linuxkpi/common/src/linux_compat.c	Tue Mar 13 16:33:41 2018	(r330865)
@@ -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);
 }



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