]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/Syscall.pm
treewide: run update-copyrights from gnulib for 2019
[public-inbox.git] / lib / PublicInbox / Syscall.pm
index d7e15c72c003e800c697449aaeea075fd9456c1f..ca7aa1c8a957ff7ecb13af576c847ae6311fe684 100644 (file)
@@ -5,7 +5,7 @@
 # This license differs from the rest of public-inbox
 #
 # This module is Copyright (c) 2005 Six Apart, Ltd.
-# Copyright (C) 2019 all contributors <meta@public-inbox.org>
+# Copyright (C) 2019-2020 all contributors <meta@public-inbox.org>
 #
 # All rights reserved.
 #
 # License or the Artistic License, as specified in the Perl README file.
 package PublicInbox::Syscall;
 use strict;
+use parent qw(Exporter);
 use POSIX qw(ENOSYS SEEK_CUR);
 use Config;
 
-require Exporter;
-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
+# $VERSION = '0.25'; # Sys::Syscall version
+our @EXPORT_OK = qw(epoll_ctl epoll_create epoll_wait
                   EPOLLIN EPOLLOUT EPOLLET
                   EPOLL_CTL_ADD EPOLL_CTL_DEL EPOLL_CTL_MOD
-                  EPOLLONESHOT EPOLLEXCLUSIVE);
-%EXPORT_TAGS = (epoll => [qw(epoll_ctl epoll_create epoll_wait
+                  EPOLLONESHOT EPOLLEXCLUSIVE
+                  signalfd SFD_NONBLOCK);
+our %EXPORT_TAGS = (epoll => [qw(epoll_ctl epoll_create epoll_wait
                              EPOLLIN EPOLLOUT
                              EPOLL_CTL_ADD EPOLL_CTL_DEL EPOLL_CTL_MOD
                              EPOLLONESHOT EPOLLEXCLUSIVE)],
-                sendfile => [qw(sendfile)],
                 );
 
-use constant EPOLLIN       => 1;
-use constant EPOLLOUT      => 4;
-# use constant EPOLLERR      => 8;
-# use constant EPOLLHUP      => 16;
-# use constant EPOLLRDBAND   => 128;
-use constant EPOLLEXCLUSIVE => (1 << 28);
-use constant EPOLLONESHOT => (1 << 30);
-use constant EPOLLET => (1 << 31);
-use constant EPOLL_CTL_ADD => 1;
-use constant EPOLL_CTL_DEL => 2;
-use constant EPOLL_CTL_MOD => 3;
+use constant {
+       EPOLLIN => 1,
+       EPOLLOUT => 4,
+       # EPOLLERR => 8,
+       # EPOLLHUP => 16,
+       # EPOLLRDBAND => 128,
+       EPOLLEXCLUSIVE => (1 << 28),
+       EPOLLONESHOT => (1 << 30),
+       EPOLLET => (1 << 31),
+       EPOLL_CTL_ADD => 1,
+       EPOLL_CTL_DEL => 2,
+       EPOLL_CTL_MOD => 3,
+
+       SFD_CLOEXEC => 02000000,
+       SFD_NONBLOCK => 00004000,
+};
 
 our $loaded_syscall = 0;
 
@@ -64,7 +66,7 @@ our (
      $SYS_epoll_create,
      $SYS_epoll_ctl,
      $SYS_epoll_wait,
-     $SYS_sendfile,
+     $SYS_signalfd4,
      );
 
 our $no_deprecated = 0;
@@ -90,75 +92,75 @@ if ($^O eq "linux") {
         $SYS_epoll_create = 254;
         $SYS_epoll_ctl    = 255;
         $SYS_epoll_wait   = 256;
-        $SYS_sendfile     = 187;  # or 64: 239
+        $SYS_signalfd4 = 327;
     } elsif ($machine eq "x86_64") {
         $SYS_epoll_create = 213;
         $SYS_epoll_ctl    = 233;
         $SYS_epoll_wait   = 232;
-        $SYS_sendfile     =  40;
+        $SYS_signalfd4 = 289;
     } elsif ($machine =~ m/^parisc/) {
         $SYS_epoll_create = 224;
         $SYS_epoll_ctl    = 225;
         $SYS_epoll_wait   = 226;
-        $SYS_sendfile     = 122;  # sys_sendfile64=209
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 309;
     } elsif ($machine =~ m/^ppc64/) {
         $SYS_epoll_create = 236;
         $SYS_epoll_ctl    = 237;
         $SYS_epoll_wait   = 238;
-        $SYS_sendfile     = 186;  # (sys32_sendfile).  sys32_sendfile64=226  (64 bit processes: sys_sendfile64=186)
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 313;
     } elsif ($machine eq "ppc") {
         $SYS_epoll_create = 236;
         $SYS_epoll_ctl    = 237;
         $SYS_epoll_wait   = 238;
-        $SYS_sendfile     = 186;  # sys_sendfile64=226
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 313;
     } elsif ($machine =~ m/^s390/) {
         $SYS_epoll_create = 249;
         $SYS_epoll_ctl    = 250;
         $SYS_epoll_wait   = 251;
-        $SYS_sendfile     = 187;  # sys_sendfile64=223
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 322;
     } elsif ($machine eq "ia64") {
         $SYS_epoll_create = 1243;
         $SYS_epoll_ctl    = 1244;
         $SYS_epoll_wait   = 1245;
-        $SYS_sendfile     = 1187;
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 289;
     } elsif ($machine eq "alpha") {
         # natural alignment, ints are 32-bits
-        $SYS_sendfile     = 370;  # (sys_sendfile64)
         $SYS_epoll_create = 407;
         $SYS_epoll_ctl    = 408;
         $SYS_epoll_wait   = 409;
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 484;
     } elsif ($machine eq "aarch64") {
         $SYS_epoll_create = 20;  # (sys_epoll_create1)
         $SYS_epoll_ctl    = 21;
         $SYS_epoll_wait   = 22;  # (sys_epoll_pwait)
-        $SYS_sendfile     = 71;  # (sys_sendfile64)
         $u64_mod_8        = 1;
         $no_deprecated    = 1;
+        $SYS_signalfd4 = 74;
     } elsif ($machine =~ m/arm(v\d+)?.*l/) {
         # ARM OABI
         $SYS_epoll_create = 250;
         $SYS_epoll_ctl    = 251;
         $SYS_epoll_wait   = 252;
-        $SYS_sendfile     = 187;
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 355;
     } elsif ($machine =~ m/^mips64/) {
-        $SYS_sendfile     = 5039;
         $SYS_epoll_create = 5207;
         $SYS_epoll_ctl    = 5208;
         $SYS_epoll_wait   = 5209;
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 5283;
     } elsif ($machine =~ m/^mips/) {
-        $SYS_sendfile     = 4207;
         $SYS_epoll_create = 4248;
         $SYS_epoll_ctl    = 4249;
         $SYS_epoll_wait   = 4250;
         $u64_mod_8        = 1;
+        $SYS_signalfd4 = 4324;
     } else {
         # as a last resort, try using the *.ph files which may not
         # exist or may be wrong
@@ -166,6 +168,11 @@ if ($^O eq "linux") {
         $SYS_epoll_create = eval { &SYS_epoll_create; } || 0;
         $SYS_epoll_ctl    = eval { &SYS_epoll_ctl;    } || 0;
         $SYS_epoll_wait   = eval { &SYS_epoll_wait;   } || 0;
+
+       # Note: do NOT add new syscalls to depend on *.ph, here.
+       # Better to miss syscalls (so we can fallback to IO::Poll)
+       # than to use wrong ones, since the names are not stable
+       # (at least not on FreeBSD), if the actual numbers are.
     }
 
     if ($u64_mod_8) {
@@ -180,68 +187,9 @@ if ($^O eq "linux") {
 elsif ($^O eq "freebsd") {
     if ($ENV{FREEBSD_SENDFILE}) {
         # this is still buggy and in development
-        $SYS_sendfile = 393;  # old is 336
     }
 }
 
-############################################################################
-# sendfile functions
-############################################################################
-
-unless ($SYS_sendfile) {
-    _load_syscall();
-    $SYS_sendfile = eval { &SYS_sendfile; } || 0;
-}
-
-sub sendfile_defined { return $SYS_sendfile ? 1 : 0; }
-
-if ($^O eq "linux" && $SYS_sendfile) {
-    *sendfile = \&sendfile_linux;
-} elsif ($^O eq "freebsd" && $SYS_sendfile) {
-    *sendfile = \&sendfile_freebsd;
-} else {
-    *sendfile = \&sendfile_noimpl;
-}
-
-sub sendfile_noimpl {
-    $! = ENOSYS;
-    return -1;
-}
-
-# C: ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
-# Perl:  sendfile($write_fd, $read_fd, $max_count) --> $actually_sent
-sub sendfile_linux {
-    return syscall(
-                   $SYS_sendfile,
-                   $_[0] + 0,  # fd
-                   $_[1] + 0,  # fd
-                   0,          # don't keep track of offset.  callers can lseek and keep track.
-                   $_[2] + 0   # count
-                   );
-}
-
-sub sendfile_freebsd {
-    my $offset = POSIX::lseek($_[1]+0, 0, SEEK_CUR) + 0;
-    my $ct = $_[2] + 0;
-    my $sbytes_buf = "\0" x 8;
-    my $rv = syscall(
-                     $SYS_sendfile,
-                     $_[1] + 0,   # fd     (from)
-                     $_[0] + 0,   # socket (to)
-                     $offset,
-                     $ct,
-                     0,           # struct sf_hdtr *hdtr
-                     $sbytes_buf, # off_t *sbytes
-                     0);          # flags
-    return $rv if $rv < 0;
-
-
-    my $set = unpack("L", $sbytes_buf);
-    POSIX::lseek($_[1]+0, SEEK_CUR, $set);
-    return $set;
-}
-
-
 ############################################################################
 # epoll functions
 ############################################################################
@@ -301,6 +249,22 @@ sub epoll_wait_mod8 {
     return $ct;
 }
 
+sub signalfd ($$$) {
+       my ($fd, $signos, $flags) = @_;
+       if ($SYS_signalfd4) {
+               # Not sure if there's a way to get pack/unpack to get the
+               # contents of POSIX::SigSet to a buffer, but prepping the
+               # bitmap like one would for select() works:
+               my $buf = "\0" x 8;
+               vec($buf, $_ - 1, 1) = 1 for @$signos;
+
+               syscall($SYS_signalfd4, $fd, $buf, 8, $flags|SFD_CLOEXEC);
+       } else {
+               $! = ENOSYS;
+               undef;
+       }
+}
+
 1;
 
 =head1 WARRANTY