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-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 16E391F990 for ; Fri, 7 Aug 2020 10:15:05 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH] syscall: support sparc64 (and maybe other big-endian systems) Date: Fri, 7 Aug 2020 10:15:04 +0000 Message-Id: <20200807101504.9703-1-e@yhbt.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Thanks to the GCC compile farm project, we can wire up syscalls for sparc64 and set system-specific SFD_* constants properly. I've FINALLY figured out how to use POSIX::SigSet to generate a usable buffer for the syscall perlfunc. This is required for endian-neutral behavior and relevant to sparc64, at least. There's no need for signalfd-related stuff to be constants, either. signalfd initialization is never a hot path and a stub subroutine for constants uses several KB of memory in the interpreter. We'll drop the needless SEEK_CUR import while we're importing O_NONBLOCK, too. --- lib/PublicInbox/DSKQXS.pm | 4 ++-- lib/PublicInbox/Daemon.pm | 4 ++-- lib/PublicInbox/Sigfd.pm | 4 ++-- lib/PublicInbox/Syscall.pm | 29 +++++++++++++++++------------ script/public-inbox-watch | 4 ++-- t/sigfd.t | 6 +++--- 6 files changed, 28 insertions(+), 23 deletions(-) diff --git a/lib/PublicInbox/DSKQXS.pm b/lib/PublicInbox/DSKQXS.pm index 35cdecda8..d1d3fe60d 100644 --- a/lib/PublicInbox/DSKQXS.pm +++ b/lib/PublicInbox/DSKQXS.pm @@ -18,7 +18,7 @@ use Symbol qw(gensym); use IO::KQueue; use Errno qw(EAGAIN); use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT EPOLLET - EPOLL_CTL_ADD EPOLL_CTL_MOD EPOLL_CTL_DEL SFD_NONBLOCK); + EPOLL_CTL_ADD EPOLL_CTL_MOD EPOLL_CTL_DEL $SFD_NONBLOCK); our @EXPORT_OK = qw(epoll_ctl epoll_wait); sub EV_DISPATCH () { 0x0080 } @@ -57,7 +57,7 @@ sub signalfd { sub TIEHANDLE { # similar to signalfd() my ($class, $signo, $flags) = @_; my $self = $class->new; - $self->{timeout} = ($flags & SFD_NONBLOCK) ? 0 : -1; + $self->{timeout} = ($flags & $SFD_NONBLOCK) ? 0 : -1; my $kq = $self->{kq}; $kq->EV_SET($_, EVFILT_SIGNAL, EV_ADD) for @$signo; $self; diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index ab0c2226e..454751834 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -15,7 +15,7 @@ use Cwd qw/abs_path/; STDOUT->autoflush(1); STDERR->autoflush(1); use PublicInbox::DS qw(now); -use PublicInbox::Syscall qw(SFD_NONBLOCK); +use PublicInbox::Syscall qw($SFD_NONBLOCK); require PublicInbox::Listener; require PublicInbox::ParentPipe; use PublicInbox::Sigfd; @@ -622,7 +622,7 @@ sub daemon_loop ($$$$) { # this calls epoll_create: PublicInbox::Listener->new($_, $tls_cb || $post_accept) } @listeners; - my $sigfd = PublicInbox::Sigfd->new($sig, SFD_NONBLOCK); + my $sigfd = PublicInbox::Sigfd->new($sig, $SFD_NONBLOCK); local %SIG = (%SIG, %$sig) if !$sigfd; if (!$sigfd) { # wake up every second to accept signals if we don't diff --git a/lib/PublicInbox/Sigfd.pm b/lib/PublicInbox/Sigfd.pm index bf91bb377..5d61e6308 100644 --- a/lib/PublicInbox/Sigfd.pm +++ b/lib/PublicInbox/Sigfd.pm @@ -6,7 +6,7 @@ package PublicInbox::Sigfd; use strict; use parent qw(PublicInbox::DS); -use PublicInbox::Syscall qw(signalfd EPOLLIN EPOLLET SFD_NONBLOCK); +use PublicInbox::Syscall qw(signalfd EPOLLIN EPOLLET $SFD_NONBLOCK); use POSIX qw(:signal_h); use IO::Handle (); @@ -33,7 +33,7 @@ sub new { } else { return; # wake up every second to check for signals } - if ($flags & SFD_NONBLOCK) { # it can go into the event loop + if ($flags & $SFD_NONBLOCK) { # it can go into the event loop $self->SUPER::new($io, EPOLLIN | EPOLLET); } else { # master main loop $self->{sock} = $io; diff --git a/lib/PublicInbox/Syscall.pm b/lib/PublicInbox/Syscall.pm index ce6b0f3af..e4f00a2a2 100644 --- a/lib/PublicInbox/Syscall.pm +++ b/lib/PublicInbox/Syscall.pm @@ -14,7 +14,7 @@ package PublicInbox::Syscall; use strict; use parent qw(Exporter); -use POSIX qw(ENOSYS SEEK_CUR); +use POSIX qw(ENOSYS O_NONBLOCK); use Config; # $VERSION = '0.25'; # Sys::Syscall version @@ -22,7 +22,7 @@ our @EXPORT_OK = qw(epoll_ctl epoll_create epoll_wait EPOLLIN EPOLLOUT EPOLLET EPOLL_CTL_ADD EPOLL_CTL_DEL EPOLL_CTL_MOD EPOLLONESHOT EPOLLEXCLUSIVE - signalfd SFD_NONBLOCK); + 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 @@ -41,9 +41,6 @@ use constant { EPOLL_CTL_ADD => 1, EPOLL_CTL_DEL => 2, EPOLL_CTL_MOD => 3, - - SFD_CLOEXEC => 02000000, - SFD_NONBLOCK => 00004000, }; our $loaded_syscall = 0; @@ -69,6 +66,8 @@ our ( $SYS_signalfd4, ); +my $SFD_CLOEXEC = 02000000; # Perl does not expose O_CLOEXEC +our $SFD_NONBLOCK = O_NONBLOCK; our $no_deprecated = 0; if ($^O eq "linux") { @@ -103,6 +102,13 @@ if ($^O eq "linux") { $SYS_epoll_ctl = 1073742057; $SYS_epoll_wait = 1073742056; $SYS_signalfd4 = 1073742113; + } elsif ($machine eq 'sparc64') { + $SYS_epoll_create = 193; + $SYS_epoll_ctl = 194; + $SYS_epoll_wait = 195; + $u64_mod_8 = 1; + $SYS_signalfd4 = 317; + $SFD_CLOEXEC = 020000000; } elsif ($machine =~ m/^parisc/) { $SYS_epoll_create = 224; $SYS_epoll_ctl = 225; @@ -140,6 +146,7 @@ if ($^O eq "linux") { $SYS_epoll_wait = 409; $u64_mod_8 = 1; $SYS_signalfd4 = 484; + $SFD_CLOEXEC = 010000000; } elsif ($machine eq "aarch64") { $SYS_epoll_create = 20; # (sys_epoll_create1) $SYS_epoll_ctl = 21; @@ -257,13 +264,11 @@ sub epoll_wait_mod8 { 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); + my $set = POSIX::SigSet->new(@$signos); + syscall($SYS_signalfd4, $fd, "$$set", + # $Config{sig_count} is NSIG, so this is NSIG/8: + int($Config{sig_count}/8), + $flags|$SFD_CLOEXEC); } else { $! = ENOSYS; undef; diff --git a/script/public-inbox-watch b/script/public-inbox-watch index c07d45d74..20534bf2a 100755 --- a/script/public-inbox-watch +++ b/script/public-inbox-watch @@ -7,7 +7,7 @@ use PublicInbox::WatchMaildir; use PublicInbox::Config; use PublicInbox::DS; use PublicInbox::Sigfd; -use PublicInbox::Syscall qw(SFD_NONBLOCK); +use PublicInbox::Syscall qw($SFD_NONBLOCK); my $oldset = PublicInbox::Sigfd::block_signals(); STDOUT->autoflush(1); STDERR->autoflush(1); @@ -35,7 +35,7 @@ if ($watch_md) { unless (grep(/\A--no-scan\z/, @ARGV)) { PublicInbox::DS::requeue($scan); } - my $sigfd = PublicInbox::Sigfd->new($sig, SFD_NONBLOCK); + my $sigfd = PublicInbox::Sigfd->new($sig, $SFD_NONBLOCK); local %SIG = (%SIG, %$sig) if !$sigfd; if (!$sigfd) { PublicInbox::Sigfd::set_sigmask($oldset); diff --git a/t/sigfd.t b/t/sigfd.t index 07120b64c..8daf31374 100644 --- a/t/sigfd.t +++ b/t/sigfd.t @@ -4,7 +4,7 @@ use Test::More; use IO::Handle; use POSIX qw(:signal_h); use Errno qw(ENOSYS); -use PublicInbox::Syscall qw(SFD_NONBLOCK); +use PublicInbox::Syscall qw($SFD_NONBLOCK); require_ok 'PublicInbox::Sigfd'; SKIP: { @@ -42,8 +42,8 @@ SKIP: { } $sigfd = undef; - my $nbsig = PublicInbox::Sigfd->new($sig, SFD_NONBLOCK); - ok($nbsig, 'Sigfd->new SFD_NONBLOCK works'); + my $nbsig = PublicInbox::Sigfd->new($sig, $SFD_NONBLOCK); + ok($nbsig, 'Sigfd->new $SFD_NONBLOCK works'); is($nbsig->wait_once, undef, 'nonblocking ->wait_once'); ok($! == Errno::EAGAIN, 'got EAGAIN'); kill('HUP', $$) or die "kill $!";