Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 May 2017 23:41:10 +0000 (UTC)
From:      Mark Johnston <markj@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: r317780 - stable/11/sys/compat/linuxkpi/common/src
Message-ID:  <201705032341.v43NfAwY032794@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Wed May  3 23:41:09 2017
New Revision: 317780
URL: https://svnweb.freebsd.org/changeset/base/317780

Log:
  MFC r317148:
  Drop Giant before sleeping in linux_wait_for_{timeout_,}common().

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	Wed May  3 22:35:41 2017	(r317779)
+++ stable/11/sys/compat/linuxkpi/common/src/linux_compat.c	Wed May  3 23:41:09 2017	(r317780)
@@ -1096,28 +1096,38 @@ linux_complete_common(struct completion 
 long
 linux_wait_for_common(struct completion *c, int flags)
 {
+	long error;
+
 	if (SCHEDULER_STOPPED())
 		return (0);
 
+	DROP_GIANT();
+
 	if (flags != 0)
 		flags = SLEEPQ_INTERRUPTIBLE | SLEEPQ_SLEEP;
 	else
 		flags = SLEEPQ_SLEEP;
+	error = 0;
 	for (;;) {
 		sleepq_lock(c);
 		if (c->done)
 			break;
 		sleepq_add(c, NULL, "completion", flags, 0);
 		if (flags & SLEEPQ_INTERRUPTIBLE) {
-			if (sleepq_wait_sig(c, 0) != 0)
-				return (-ERESTARTSYS);
+			if (sleepq_wait_sig(c, 0) != 0) {
+				error = -ERESTARTSYS;
+				goto intr;
+			}
 		} else
 			sleepq_wait(c, 0);
 	}
 	c->done--;
 	sleepq_release(c);
 
-	return (0);
+intr:
+	PICKUP_GIANT();
+
+	return (error);
 }
 
 /*
@@ -1126,18 +1136,22 @@ linux_wait_for_common(struct completion 
 long
 linux_wait_for_timeout_common(struct completion *c, long timeout, int flags)
 {
-	long end = jiffies + timeout;
+	long end = jiffies + timeout, error;
+	int ret;
 
 	if (SCHEDULER_STOPPED())
 		return (0);
 
+	DROP_GIANT();
+
 	if (flags != 0)
 		flags = SLEEPQ_INTERRUPTIBLE | SLEEPQ_SLEEP;
 	else
 		flags = SLEEPQ_SLEEP;
-	for (;;) {
-		int ret;
 
+	error = 0;
+	ret = 0;
+	for (;;) {
 		sleepq_lock(c);
 		if (c->done)
 			break;
@@ -1150,16 +1164,20 @@ linux_wait_for_timeout_common(struct com
 		if (ret != 0) {
 			/* check for timeout or signal */
 			if (ret == EWOULDBLOCK)
-				return (0);
+				error = 0;
 			else
-				return (-ERESTARTSYS);
+				error = -ERESTARTSYS;
+			goto intr;
 		}
 	}
 	c->done--;
 	sleepq_release(c);
 
+intr:
+	PICKUP_GIANT();
+
 	/* return how many jiffies are left */
-	return (linux_timer_jiffies_until(end));
+	return (ret != 0 ? error : linux_timer_jiffies_until(end));
 }
 
 int



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