1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-22 11:17:19 +00:00

Drop Giant before sleeping in linux_wait_for_{timeout_,}common().

Reported and tested by:	Pete Wright <pete@nomadlogic.org>
Reviewed by:	hselasky (previous version)
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D10414
This commit is contained in:
Mark Johnston 2017-04-19 16:12:02 +00:00
parent 2452e16e5b
commit b602c283b3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=317148

View File

@ -1321,28 +1321,38 @@ linux_complete_common(struct completion *c, int all)
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);
}
/*
@ -1351,18 +1361,22 @@ linux_wait_for_common(struct completion *c, int flags)
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;
@ -1375,16 +1389,20 @@ linux_wait_for_timeout_common(struct completion *c, long timeout, int flags)
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