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
This commit is contained in:
parent
d1b671061b
commit
be15e1332d
@ -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, int timeout, int flags)
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user