Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Mar 2018 12:16:55 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r330689 - head/sys/compat/linuxkpi/common/src
Message-ID:  <201803091216.w29CGtif043665@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@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);
 }



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