From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 56F321F4BA for ; Sat, 29 Jun 2019 19:59:52 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 04/11] listener: use edge-triggered notifications Date: Sat, 29 Jun 2019 19:59:44 +0000 Message-Id: <20190629195951.32160-5-e@80x24.org> In-Reply-To: <20190629195951.32160-1-e@80x24.org> References: <20190629195951.32160-1-e@80x24.org> List-Id: We don't need extra wakeups from the kernel when we know a listener is already active. --- lib/PublicInbox/DSKQXS.pm | 4 +++- lib/PublicInbox/Listener.pm | 7 ++++--- lib/PublicInbox/Syscall.pm | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/PublicInbox/DSKQXS.pm b/lib/PublicInbox/DSKQXS.pm index 364df3d6..278d3f88 100644 --- a/lib/PublicInbox/DSKQXS.pm +++ b/lib/PublicInbox/DSKQXS.pm @@ -16,7 +16,8 @@ use warnings; use parent qw(IO::KQueue); use parent qw(Exporter); use IO::KQueue; -use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT EPOLL_CTL_DEL); +use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT EPOLLET + EPOLL_CTL_DEL); our @EXPORT_OK = qw(epoll_ctl epoll_wait); my $owner_pid = -1; # kqueue is close-on-fork (yes, fork, not exec) @@ -25,6 +26,7 @@ sub kq_flag ($$) { my ($bit, $ev) = @_; if ($ev & $bit) { my $fl = EV_ADD | EV_ENABLE; + $fl |= EV_CLEAR if $fl & EPOLLET; ($ev & EPOLLONESHOT) ? ($fl | EV_ONESHOT) : $fl; } else { EV_ADD | EV_DISABLE; diff --git a/lib/PublicInbox/Listener.pm b/lib/PublicInbox/Listener.pm index 94b2aed4..594dabb8 100644 --- a/lib/PublicInbox/Listener.pm +++ b/lib/PublicInbox/Listener.pm @@ -9,6 +9,7 @@ use base 'PublicInbox::DS'; use Socket qw(SOL_SOCKET SO_KEEPALIVE IPPROTO_TCP TCP_NODELAY); use fields qw(post_accept); require IO::Handle; +use PublicInbox::Syscall qw(EPOLLIN EPOLLEXCLUSIVE EPOLLET); sub new ($$$) { my ($class, $s, $cb) = @_; @@ -17,15 +18,14 @@ sub new ($$$) { listen($s, 1024); IO::Handle::blocking($s, 0); my $self = fields::new($class); - $self->SUPER::new($s, PublicInbox::DS::EPOLLIN()| - PublicInbox::DS::EPOLLEXCLUSIVE()); + $self->SUPER::new($s, EPOLLIN|EPOLLET|EPOLLEXCLUSIVE); $self->{post_accept} = $cb; $self } sub event_step { my ($self) = @_; - my $sock = $self->{sock}; + my $sock = $self->{sock} or return; # no loop here, we want to fairly distribute clients # between multiple processes sharing the same socket @@ -35,6 +35,7 @@ sub event_step { if (my $addr = accept(my $c, $sock)) { IO::Handle::blocking($c, 0); # no accept4 :< $self->{post_accept}->($c, $addr, $sock); + $self->requeue; } } diff --git a/lib/PublicInbox/Syscall.pm b/lib/PublicInbox/Syscall.pm index 500efa67..d7e15c72 100644 --- a/lib/PublicInbox/Syscall.pm +++ b/lib/PublicInbox/Syscall.pm @@ -22,7 +22,7 @@ use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS $VERSION); $VERSION = "0.25"; @ISA = qw(Exporter); @EXPORT_OK = qw(sendfile epoll_ctl epoll_create epoll_wait - EPOLLIN EPOLLOUT + EPOLLIN EPOLLOUT EPOLLET EPOLL_CTL_ADD EPOLL_CTL_DEL EPOLL_CTL_MOD EPOLLONESHOT EPOLLEXCLUSIVE); %EXPORT_TAGS = (epoll => [qw(epoll_ctl epoll_create epoll_wait @@ -39,7 +39,7 @@ use constant EPOLLOUT => 4; # use constant EPOLLRDBAND => 128; use constant EPOLLEXCLUSIVE => (1 << 28); use constant EPOLLONESHOT => (1 << 30); -# use constant EPOLLET => (1 << 31); +use constant EPOLLET => (1 << 31); use constant EPOLL_CTL_ADD => 1; use constant EPOLL_CTL_DEL => 2; use constant EPOLL_CTL_MOD => 3; -- EW