about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2020-12-27 02:53:07 +0000
committerEric Wong <e@80x24.org>2020-12-28 23:19:50 +0000
commit0f461dcd3317f44670e2fc50346f87ff41e80127 (patch)
tree816e7f83431804824ee09d1571546aeb070350c3 /lib
parenta7794134700c855a7a4fc030720ee8901b38a5f0 (diff)
downloadpublic-inbox-0f461dcd3317f44670e2fc50346f87ff41e80127.tar.gz
Consistently returning the equivalent of pollfd.revents in a
portable manner was never worth the effort for us, as we use the
same ->event_step callback regardless of POLLIN/POLLOUT/POLLHUP.

Being a Perl, @events knows it size and we don't have to return
a maximum index for the caller to iterate on.

We can also avoid redundant integer coercion ("+0") since we
ensure everything is an IV in other places.

Finally, vec() is preferable to ("\0" x $size) for resizing
buffers because it only needs to write the extended portion
and not overwrite the entire buffer.
Diffstat (limited to 'lib')
-rw-r--r--lib/PublicInbox/DS.pm20
-rw-r--r--lib/PublicInbox/DSKQXS.pm2
-rw-r--r--lib/PublicInbox/DSPoll.pm3
-rw-r--r--lib/PublicInbox/Syscall.pm66
4 files changed, 45 insertions, 46 deletions
diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm
index 12df5919..97a6f6ef 100644
--- a/lib/PublicInbox/DS.pm
+++ b/lib/PublicInbox/DS.pm
@@ -87,9 +87,7 @@ A timeout of 0 (zero) means poll forever. A timeout of -1 means poll and return
 immediately.
 
 =cut
-sub SetLoopTimeout {
-    return $LoopTimeout = $_[1] + 0;
-}
+sub SetLoopTimeout { $LoopTimeout = $_[1] + 0 }
 
 =head2 C<< PublicInbox::DS::add_timer( $seconds, $coderef, $arg) >>
 
@@ -200,12 +198,7 @@ sub RunTimers {
     my $timeout = int(($Timers[0][0] - $now) * 1000) + 1;
 
     # -1 is an infinite timeout, so prefer a real timeout
-    return $timeout     if $LoopTimeout == -1;
-
-    # otherwise pick the lower of our regular timeout and time until
-    # the next timer
-    return $LoopTimeout if $LoopTimeout < $timeout;
-    return $timeout;
+    ($LoopTimeout < 0 || $LoopTimeout >= $timeout) ? $timeout : $LoopTimeout;
 }
 
 # We can't use waitpid(-1) safely here since it can hit ``, system(),
@@ -261,19 +254,18 @@ sub PostEventLoop () {
 sub EventLoop {
     $Epoll //= _InitPoller();
     local $in_loop = 1;
+    my @events;
     do {
-        my @events;
-        my $i;
         my $timeout = RunTimers();
 
         # get up to 1000 events
-        my $evcount = epoll_wait($Epoll, 1000, $timeout, \@events);
-        for ($i=0; $i<$evcount; $i++) {
+        epoll_wait($Epoll, 1000, $timeout, \@events);
+        for my $fd (@events) {
             # it's possible epoll_wait returned many events, including some at the end
             # that ones in the front triggered unregister-interest actions.  if we
             # can't find the %sock entry, it's because we're no longer interested
             # in that event.
-            $DescriptorMap{$events[$i]->[0]}->event_step;
+            $DescriptorMap{$fd}->event_step;
         }
     } while (PostEventLoop());
     _run_later();
diff --git a/lib/PublicInbox/DSKQXS.pm b/lib/PublicInbox/DSKQXS.pm
index d1d3fe60..aa2c9168 100644
--- a/lib/PublicInbox/DSKQXS.pm
+++ b/lib/PublicInbox/DSKQXS.pm
@@ -134,7 +134,7 @@ sub epoll_wait {
                 }
         }
         # caller only cares for $events[$i]->[0]
-        scalar(@$events);
+        $_ = $_->[0] for @$events;
 }
 
 # kqueue is close-on-fork (not exec), so we must not close it
diff --git a/lib/PublicInbox/DSPoll.pm b/lib/PublicInbox/DSPoll.pm
index 1d9b51d9..a218f695 100644
--- a/lib/PublicInbox/DSPoll.pm
+++ b/lib/PublicInbox/DSPoll.pm
@@ -45,14 +45,13 @@ sub epoll_wait {
                         my $fd = $pset[$i++];
                         my $revents = $pset[$i++] or next;
                         delete($self->{$fd}) if $self->{$fd} & EPOLLONESHOT;
-                        push @$events, [ $fd ];
+                        push @$events, $fd;
                 }
                 my $nevents = scalar @$events;
                 if ($n != $nevents) {
                         warn "BUG? poll() returned $n, but got $nevents";
                 }
         }
-        $n;
 }
 
 1;
diff --git a/lib/PublicInbox/Syscall.pm b/lib/PublicInbox/Syscall.pm
index e4f00a2a..c403f78a 100644
--- a/lib/PublicInbox/Syscall.pm
+++ b/lib/PublicInbox/Syscall.pm
@@ -227,38 +227,46 @@ sub epoll_ctl_mod8 {
 our $epoll_wait_events;
 our $epoll_wait_size = 0;
 sub epoll_wait_mod4 {
-    # resize our static buffer if requested size is bigger than we've ever done
-    if ($_[1] > $epoll_wait_size) {
-        $epoll_wait_size = $_[1];
-        $epoll_wait_events = "\0" x 12 x $epoll_wait_size;
-    }
-    my $ct = syscall($SYS_epoll_wait, $_[0]+0, $epoll_wait_events, $_[1]+0, $_[2]+0);
-    for (0..$ct-1) {
-        @{$_[3]->[$_]}[1,0] = unpack("LL", substr($epoll_wait_events, 12*$_, 8));
-    }
-    return $ct;
+        my ($epfd, $maxevents, $timeout_msec, $events) = @_;
+        # resize our static buffer if maxevents bigger than we've ever done
+        if ($maxevents > $epoll_wait_size) {
+                $epoll_wait_size = $maxevents;
+                vec($epoll_wait_events, $maxevents * 12 * 8 - 1, 1) = 0;
+        }
+        @$events = ();
+        my $ct = syscall($SYS_epoll_wait, $epfd, $epoll_wait_events,
+                        $maxevents, $timeout_msec);
+        for (0..$ct - 1) {
+                # 12-byte struct epoll_event
+                # 4 bytes uint32_t events mask (skipped, useless to us)
+                # 8 bytes: epoll_data_t union (first 4 bytes are the fd)
+                # So we skip the first 4 bytes and take the middle 4:
+                $events->[$_] = unpack('L', substr($epoll_wait_events,
+                                                        12 * $_ + 4, 4));
+        }
 }
 
 sub epoll_wait_mod8 {
-    # resize our static buffer if requested size is bigger than we've ever done
-    if ($_[1] > $epoll_wait_size) {
-        $epoll_wait_size = $_[1];
-        $epoll_wait_events = "\0" x 16 x $epoll_wait_size;
-    }
-    my $ct;
-    if ($no_deprecated) {
-        $ct = syscall($SYS_epoll_wait, $_[0]+0, $epoll_wait_events, $_[1]+0, $_[2]+0, undef);
-    } else {
-        $ct = syscall($SYS_epoll_wait, $_[0]+0, $epoll_wait_events, $_[1]+0, $_[2]+0);
-    }
-    for (0..$ct-1) {
-        # 16 byte epoll_event structs, with format:
-        #    4 byte mask [idx 1]
-        #    4 byte padding (we put it into idx 2, useless)
-        #    8 byte data (first 4 bytes are fd, into idx 0)
-        @{$_[3]->[$_]}[1,2,0] = unpack("LLL", substr($epoll_wait_events, 16*$_, 12));
-    }
-    return $ct;
+        my ($epfd, $maxevents, $timeout_msec, $events) = @_;
+
+        # resize our static buffer if maxevents bigger than we've ever done
+        if ($maxevents > $epoll_wait_size) {
+                $epoll_wait_size = $maxevents;
+                vec($epoll_wait_events, $maxevents * 16 * 8 - 1, 1) = 0;
+        }
+        @$events = ();
+        my $ct = syscall($SYS_epoll_wait, $epfd, $epoll_wait_events,
+                        $maxevents, $timeout_msec,
+                        $no_deprecated ? undef : ());
+        for (0..$ct - 1) {
+                # 16-byte struct epoll_event
+                # 4 bytes uint32_t events mask (skipped, useless to us)
+                # 4 bytes padding (skipped, useless)
+                # 8 bytes epoll_data_t union (first 4 bytes are the fd)
+                # So skip the first 8 bytes, take 4, and ignore the last 4:
+                $events->[$_] = unpack('L', substr($epoll_wait_events,
+                                                        16 * $_ + 8, 4));
+        }
 }
 
 sub signalfd ($$$) {