summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/compat/linuxkpi/common/src/linux_compat.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index 54bd33b..2512297 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -1096,28 +1096,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);
}
/*
@@ -1126,18 +1136,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;
@@ -1150,16 +1164,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
OpenPOWER on IntegriCloud