mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	fs/epoll: remove unnecessary wakeups of nested epoll
Take the case where we have:
        t0
         | (ew)
        e0
         | (et)
        e1
         | (lt)
        s0
t0: thread 0
e0: epoll fd 0
e1: epoll fd 1
s0: socket fd 0
ew: epoll_wait
et: edge-trigger
lt: level-trigger
We remove unnecessary wakeups to prevent the nested epoll that working in edge-
triggered mode to waking up continuously.
Test code:
 #include <unistd.h>
 #include <sys/epoll.h>
 #include <sys/socket.h>
 int main(int argc, char *argv[])
 {
 	int sfd[2];
 	int efd[2];
 	struct epoll_event e;
 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0)
 		goto out;
 	efd[0] = epoll_create(1);
 	if (efd[0] < 0)
 		goto out;
 	efd[1] = epoll_create(1);
 	if (efd[1] < 0)
 		goto out;
 	e.events = EPOLLIN;
 	if (epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e) < 0)
 		goto out;
 	e.events = EPOLLIN | EPOLLET;
 	if (epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e) < 0)
 		goto out;
 	if (write(sfd[1], "w", 1) != 1)
 		goto out;
 	if (epoll_wait(efd[0], &e, 1, 0) != 1)
 		goto out;
 	if (epoll_wait(efd[0], &e, 1, 0) != 0)
 		goto out;
 	close(efd[0]);
 	close(efd[1]);
 	close(sfd[0]);
 	close(sfd[1]);
 	return 0;
 out:
 	return -1;
 }
More tests:
 https://github.com/heiher/epoll-wakeup
Link: http://lkml.kernel.org/r/20191009060516.3577-1-r@hev.cc
Signed-off-by: hev <r@hev.cc>
Reviewed-by: Roman Penyaev <rpenyaev@suse.de>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Davide Libenzi <davidel@xmailserver.org>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Eric Wong <e@80x24.org>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Sridhar Samudrala <sridhar.samudrala@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
			
			
This commit is contained in:
		
							parent
							
								
									f6520c5208
								
							
						
					
					
						commit
						339ddb53d3
					
				
					 1 changed files with 0 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -666,7 +666,6 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep,
 | 
			
		|||
			      void *priv, int depth, bool ep_locked)
 | 
			
		||||
{
 | 
			
		||||
	__poll_t res;
 | 
			
		||||
	int pwake = 0;
 | 
			
		||||
	struct epitem *epi, *nepi;
 | 
			
		||||
	LIST_HEAD(txlist);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -733,26 +732,11 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep,
 | 
			
		|||
	 */
 | 
			
		||||
	list_splice(&txlist, &ep->rdllist);
 | 
			
		||||
	__pm_relax(ep->ws);
 | 
			
		||||
 | 
			
		||||
	if (!list_empty(&ep->rdllist)) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Wake up (if active) both the eventpoll wait list and
 | 
			
		||||
		 * the ->poll() wait list (delayed after we release the lock).
 | 
			
		||||
		 */
 | 
			
		||||
		if (waitqueue_active(&ep->wq))
 | 
			
		||||
			wake_up(&ep->wq);
 | 
			
		||||
		if (waitqueue_active(&ep->poll_wait))
 | 
			
		||||
			pwake++;
 | 
			
		||||
	}
 | 
			
		||||
	write_unlock_irq(&ep->lock);
 | 
			
		||||
 | 
			
		||||
	if (!ep_locked)
 | 
			
		||||
		mutex_unlock(&ep->mtx);
 | 
			
		||||
 | 
			
		||||
	/* We have to call this outside the lock */
 | 
			
		||||
	if (pwake)
 | 
			
		||||
		ep_poll_safewake(&ep->poll_wait);
 | 
			
		||||
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue