Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1bc90dd authored by Tony Battersby's avatar Tony Battersby Committed by Linus Torvalds
Browse files

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: default avatarTony Battersby <tonyb@cybernetics.com>
Acked-by: default avatarDavide Libenzi <davidel@xmailserver.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d0305882
Loading
Loading
Loading
Loading
+8 −14
Original line number Diff line number Diff line
@@ -394,29 +394,23 @@ 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);

	if (nwait) {
	while (!list_empty(lsthead)) {
		pwq = list_first_entry(lsthead, struct eppoll_entry, llink);

			list_del_init(&pwq->llink);
		list_del(&pwq->llink);
		remove_wait_queue(pwq->whead, &pwq->wait);
		kmem_cache_free(pwq_cache, pwq);
	}
}
}

/**
 * ep_scan_ready_list - Scans the ready list in a way that makes possible for