diff --git a/doio.c b/doio.c index d0681ad6ccbe..d19a2a1a51f3 100644 --- a/doio.c +++ b/doio.c @@ -196,7 +196,7 @@ Perl_PerlLIO_dup_cloexec(pTHX_ int oldfd) * PERL_IMPLICIT_SYS builds. */ DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_dup, + PL_strategy.dup, fcntl(oldfd, F_DUPFD_CLOEXEC, 0), PerlLIO_dup(oldfd)); #else @@ -214,7 +214,7 @@ Perl_PerlLIO_dup2_cloexec(pTHX_ int oldfd, int newfd) * PERL_IMPLICIT_SYS builds. */ DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_dup2, + PL_strategy.dup2, dup3(oldfd, newfd, O_CLOEXEC), PerlLIO_dup2(oldfd, newfd)); #else @@ -279,7 +279,7 @@ Perl_PerlLIO_open_cloexec(pTHX_ const char *file, int flag) PERL_ARGS_ASSERT_PERLLIO_OPEN_CLOEXEC; #if defined(O_CLOEXEC) DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_open, + PL_strategy.open, PerlLIO_open(file, flag | O_CLOEXEC), PerlLIO_open(file, flag)); #else @@ -293,7 +293,7 @@ Perl_PerlLIO_open3_cloexec(pTHX_ const char *file, int flag, int perm) PERL_ARGS_ASSERT_PERLLIO_OPEN3_CLOEXEC; #if defined(O_CLOEXEC) DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_open3, + PL_strategy.open3, PerlLIO_open3(file, flag | O_CLOEXEC, perm), PerlLIO_open3(file, flag, perm)); #else @@ -310,7 +310,7 @@ static int Internal_Perl_my_mkstemp_cloexec(char *templte) PERL_ARGS_ASSERT_MY_MKSTEMP_CLOEXEC; # if defined(O_CLOEXEC) DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_mkstemp, + PL_strategy.mkstemp, Perl_my_mkostemp(templte, O_CLOEXEC), Perl_my_mkstemp(templte)); # else @@ -334,7 +334,7 @@ Perl_my_mkstemp_cloexec(char *templte) PERL_ARGS_ASSERT_MY_MKSTEMP_CLOEXEC; # if defined(O_CLOEXEC) DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_mkstemp, + PL_strategy.mkstemp, Perl_my_mkostemp(templte, O_CLOEXEC), Perl_my_mkstemp(templte)); # else @@ -349,7 +349,7 @@ Perl_my_mkostemp_cloexec(char *templte, int flags) PERL_ARGS_ASSERT_MY_MKOSTEMP_CLOEXEC; #if defined(O_CLOEXEC) DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_mkstemp, + PL_strategy.mkstemp, Perl_my_mkostemp(templte, flags | O_CLOEXEC), Perl_my_mkostemp(templte, flags)); #else @@ -368,7 +368,7 @@ Perl_PerlProc_pipe_cloexec(pTHX_ int *pipefd) * PERL_IMPLICIT_SYS builds. */ # if !defined(PERL_IMPLICIT_SYS) && defined(HAS_PIPE2) && defined(O_CLOEXEC) - DO_PIPEOPEN_EXPERIMENTING_CLOEXEC(PL_strategy_pipe, pipefd, + DO_PIPEOPEN_EXPERIMENTING_CLOEXEC(PL_strategy.pipe, pipefd, pipe2(pipefd, O_CLOEXEC), PerlProc_pipe(pipefd)); # else @@ -384,7 +384,7 @@ Perl_PerlSock_socket_cloexec(pTHX_ int domain, int type, int protocol) { # if defined(SOCK_CLOEXEC) DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_socket, + PL_strategy.socket, PerlSock_socket(domain, type | SOCK_CLOEXEC, protocol), PerlSock_socket(domain, type, protocol)); # else @@ -404,7 +404,7 @@ Perl_PerlSock_accept_cloexec(pTHX_ int listenfd, struct sockaddr *addr, * on PERL_IMPLICIT_SYS builds. */ DO_ONEOPEN_EXPERIMENTING_CLOEXEC( - PL_strategy_accept, + PL_strategy.accept, accept4(listenfd, addr, addrlen, SOCK_CLOEXEC), PerlSock_accept(listenfd, addr, addrlen)); # else @@ -423,7 +423,7 @@ Perl_PerlSock_socketpair_cloexec(pTHX_ int domain, int type, int protocol, { PERL_ARGS_ASSERT_PERLSOCK_SOCKETPAIR_CLOEXEC; # ifdef SOCK_CLOEXEC - DO_PIPEOPEN_EXPERIMENTING_CLOEXEC(PL_strategy_socketpair, pairfd, + DO_PIPEOPEN_EXPERIMENTING_CLOEXEC(PL_strategy.socketpair, pairfd, PerlSock_socketpair(domain, type | SOCK_CLOEXEC, protocol, pairfd), PerlSock_socketpair(domain, type, protocol, pairfd)); # else diff --git a/globvar.sym b/globvar.sym index b9cea72af64b..798bc5f6857e 100644 --- a/globvar.sym +++ b/globvar.sym @@ -66,15 +66,7 @@ PL_sig_name PL_sig_num PL_simple PL_simple_bitmask -PL_strategy_dup -PL_strategy_dup2 -PL_strategy_open -PL_strategy_open3 -PL_strategy_mkstemp -PL_strategy_socket -PL_strategy_accept -PL_strategy_pipe -PL_strategy_socketpair +PL_strategy PL_strict_utf8_dfa_tab PL_subversion PL_utf8skip diff --git a/perl.h b/perl.h index 1154cb99dfaf..247119a6bdfb 100644 --- a/perl.h +++ b/perl.h @@ -5230,6 +5230,35 @@ EXTERN_C void PerlIO_teardown(void); # define PERLIO_TERM #endif +/* these record the best way to perform certain IO operations while + * atomically setting FD_CLOEXEC. On the first call, a probe is done + * and the result recorded for use by subsequent calls. + * In theory these variables aren't thread-safe, but the worst that can + * happen is that two threads will both do an initial probe or even less + * likley both ithreads will repeat the probe a couple times over the next + * 100 ms. + * + * If a cross platform atomic API gets added to perl.h, all reads and writes + * to PL_strategy need force a memory fence. Certain archs like ARM in SMP mode + * by design will never re-read or flush memory writes between their L2 cache + * central physical unless software commands the CPU core to do it. + * + * struct io_stategy {} can be reduced to a U32 with 18 bits if its known + * the CC guarentees (PL_strategy & 0xC == 0x8) is safe against sharding. + */ + +struct io_strategy { + int strategy_dup; /* doio.c */ + int strategy_dup2; /* doio.c */ + int strategy_open; /* doio.c */ + int strategy_open3; /* doio.c */ + int strategy_mkstemp; /* doio.c */ + int strategy_socket; /* doio.c */ + int strategy_accept; /* doio.c */ + int strategy_pipe; /* doio.c */ + int strategy_socketpair; /* doio.c */ +}; + #ifdef MYMALLOC # ifdef MUTEX_INIT_CALLS_MALLOC # define MALLOC_INIT \ diff --git a/perlvars.h b/perlvars.h index 7b0c01a43f30..ec7a5c25108c 100644 --- a/perlvars.h +++ b/perlvars.h @@ -400,21 +400,20 @@ PERLVAR(G, user_prop_mutex, perl_mutex) /* Mutex for manipulating */ PERLVARI(G, shutdownhook, shutdown_proc_t, &Perl_noshutdownhook) -/* these record the best way to perform certain IO operations while +/* This struct records the best way to perform certain IO operations while * atomically setting FD_CLOEXEC. On the first call, a probe is done * and the result recorded for use by subsequent calls. * In theory these variables aren't thread-safe, but the worst that can * happen is that two treads will both do an initial probe + * + * Boolean-like probe results for certain I/O operations and FD_CLOEXEC. + * Each flag has 3 states: enum CLOEXEC_EXPERIMENT (== 0), CLOEXEC_AT_OPEN, + * and CLOEXEC_AFTER_OPEN. + * + * doio.c is the only user of this var currently. This variable is exported + * in case experimental XS code needs to perfectly replicate an IO pp_*() func. */ -PERLVARI(G, strategy_dup, int, 0) /* doio.c */ -PERLVARI(G, strategy_dup2, int, 0) /* doio.c */ -PERLVARI(G, strategy_open, int, 0) /* doio.c */ -PERLVARI(G, strategy_open3, int, 0) /* doio.c */ -PERLVARI(G, strategy_mkstemp, int, 0) /* doio.c */ -PERLVARI(G, strategy_socket, int, 0) /* doio.c */ -PERLVARI(G, strategy_accept, int, 0) /* doio.c */ -PERLVARI(G, strategy_pipe, int, 0) /* doio.c */ -PERLVARI(G, strategy_socketpair, int, 0) /* doio.c */ +PERLVAR(G, strategy, struct io_strategy) PERLVARI(G, my_environ, char **, NULL) PERLVARI(G, origenviron, char **, NULL)