epoll: remove unnecessary xchg
xchg in ep_unregister_pollwait() is unnecessary because it is protected by either epmutex or ep->mtx (the same protection as ep_remove()). If xchg was necessary, it would be insufficient to protect against problems: if multiple concurrent calls to ep_unregister_pollwait() were possible then a second caller that returns without doing anything because nwait == 0 could return before the waitqueues are removed by the first caller, which looks like it could lead to problematic races with ep_poll_callback(). So remove xchg and add comments about the locking. Signed-off-by: Tony Battersby <tonyb@cybernetics.com> Acked-by: Davide Libenzi <davidel@xmailserver.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
d030588282
commit
d1bc90dd5d
1 changed files with 8 additions and 14 deletions
|
@ -394,27 +394,21 @@ static void ep_poll_safewake(wait_queue_head_t *wq)
|
|||
}
|
||||
|
||||
/*
|
||||
* This function unregister poll callbacks from the associated file descriptor.
|
||||
* Since this must be called without holding "ep->lock" the atomic exchange trick
|
||||
* will protect us from multiple unregister.
|
||||
* This function unregisters poll callbacks from the associated file
|
||||
* descriptor. Must be called with "mtx" held (or "epmutex" if called from
|
||||
* ep_free).
|
||||
*/
|
||||
static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
|
||||
{
|
||||
int nwait;
|
||||
struct list_head *lsthead = &epi->pwqlist;
|
||||
struct eppoll_entry *pwq;
|
||||
|
||||
/* This is called without locks, so we need the atomic exchange */
|
||||
nwait = xchg(&epi->nwait, 0);
|
||||
while (!list_empty(lsthead)) {
|
||||
pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
|
||||
|
||||
if (nwait) {
|
||||
while (!list_empty(lsthead)) {
|
||||
pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
|
||||
|
||||
list_del_init(&pwq->llink);
|
||||
remove_wait_queue(pwq->whead, &pwq->wait);
|
||||
kmem_cache_free(pwq_cache, pwq);
|
||||
}
|
||||
list_del(&pwq->llink);
|
||||
remove_wait_queue(pwq->whead, &pwq->wait);
|
||||
kmem_cache_free(pwq_cache, pwq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue