Commit 099d6b0fe9e6d5855403d2d0a8ae800b7bdb24a7
Committed by
Riku Voipio
1 parent
4b627a23
linux-user: implement pipe2 [v3]
implement pipe2 syscall. [v2] fix do_pipe on mips and sh4 [v3] use pipe2 to ensure atomicity, but only when it is available. Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
Showing
2 changed files
with
58 additions
and
18 deletions
configure
| @@ -1304,6 +1304,24 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then | @@ -1304,6 +1304,24 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then | ||
| 1304 | utimens=yes | 1304 | utimens=yes |
| 1305 | fi | 1305 | fi |
| 1306 | 1306 | ||
| 1307 | +# check if pipe2 is there | ||
| 1308 | +pipe2=no | ||
| 1309 | +cat > $TMPC << EOF | ||
| 1310 | +#define _GNU_SOURCE | ||
| 1311 | +#include <unistd.h> | ||
| 1312 | +#include <fcntl.h> | ||
| 1313 | + | ||
| 1314 | +int main(void) | ||
| 1315 | +{ | ||
| 1316 | + int pipefd[2]; | ||
| 1317 | + pipe2(pipefd, O_CLOEXEC); | ||
| 1318 | + return 0; | ||
| 1319 | +} | ||
| 1320 | +EOF | ||
| 1321 | +if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then | ||
| 1322 | + pipe2=yes | ||
| 1323 | +fi | ||
| 1324 | + | ||
| 1307 | # Check if tools are available to build documentation. | 1325 | # Check if tools are available to build documentation. |
| 1308 | if test "$build_docs" = "yes" -a \( ! -x "`which texi2html 2>/dev/null`" -o ! -x "`which pod2man 2>/dev/null`" \) ; then | 1326 | if test "$build_docs" = "yes" -a \( ! -x "`which texi2html 2>/dev/null`" -o ! -x "`which pod2man 2>/dev/null`" \) ; then |
| 1309 | build_docs="no" | 1327 | build_docs="no" |
| @@ -1704,6 +1722,9 @@ fi | @@ -1704,6 +1722,9 @@ fi | ||
| 1704 | if test "$utimens" = "yes" ; then | 1722 | if test "$utimens" = "yes" ; then |
| 1705 | echo "#define CONFIG_UTIMENSAT 1" >> $config_h | 1723 | echo "#define CONFIG_UTIMENSAT 1" >> $config_h |
| 1706 | fi | 1724 | fi |
| 1725 | +if test "$pipe2" = "yes" ; then | ||
| 1726 | + echo "#define CONFIG_PIPE2 1" >> $config_h | ||
| 1727 | +fi | ||
| 1707 | if test "$inotify" = "yes" ; then | 1728 | if test "$inotify" = "yes" ; then |
| 1708 | echo "#define CONFIG_INOTIFY 1" >> $config_h | 1729 | echo "#define CONFIG_INOTIFY 1" >> $config_h |
| 1709 | fi | 1730 | fi |
linux-user/syscall.c
| @@ -944,6 +944,37 @@ static abi_long do_select(int n, | @@ -944,6 +944,37 @@ static abi_long do_select(int n, | ||
| 944 | return ret; | 944 | return ret; |
| 945 | } | 945 | } |
| 946 | 946 | ||
| 947 | +static abi_long do_pipe2(int host_pipe[], int flags) | ||
| 948 | +{ | ||
| 949 | +#ifdef CONFIG_PIPE2 | ||
| 950 | + return pipe2(host_pipe, flags); | ||
| 951 | +#else | ||
| 952 | + return -ENOSYS; | ||
| 953 | +#endif | ||
| 954 | +} | ||
| 955 | + | ||
| 956 | +static abi_long do_pipe(void *cpu_env, int pipedes, int flags) | ||
| 957 | +{ | ||
| 958 | + int host_pipe[2]; | ||
| 959 | + abi_long ret; | ||
| 960 | + ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe); | ||
| 961 | + | ||
| 962 | + if (is_error(ret)) | ||
| 963 | + return get_errno(ret); | ||
| 964 | +#if defined(TARGET_MIPS) | ||
| 965 | + ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1]; | ||
| 966 | + ret = host_pipe[0]; | ||
| 967 | +#elif defined(TARGET_SH4) | ||
| 968 | + ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; | ||
| 969 | + ret = host_pipe[0]; | ||
| 970 | +#else | ||
| 971 | + if (put_user_s32(host_pipe[0], pipedes) | ||
| 972 | + || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0]))) | ||
| 973 | + return -TARGET_EFAULT; | ||
| 974 | +#endif | ||
| 975 | + return get_errno(ret); | ||
| 976 | +} | ||
| 977 | + | ||
| 947 | static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, | 978 | static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, |
| 948 | abi_ulong target_addr, | 979 | abi_ulong target_addr, |
| 949 | socklen_t len) | 980 | socklen_t len) |
| @@ -4529,25 +4560,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | @@ -4529,25 +4560,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | ||
| 4529 | ret = get_errno(dup(arg1)); | 4560 | ret = get_errno(dup(arg1)); |
| 4530 | break; | 4561 | break; |
| 4531 | case TARGET_NR_pipe: | 4562 | case TARGET_NR_pipe: |
| 4532 | - { | ||
| 4533 | - int host_pipe[2]; | ||
| 4534 | - ret = get_errno(pipe(host_pipe)); | ||
| 4535 | - if (!is_error(ret)) { | ||
| 4536 | -#if defined(TARGET_MIPS) | ||
| 4537 | - CPUMIPSState *env = (CPUMIPSState*)cpu_env; | ||
| 4538 | - env->active_tc.gpr[3] = host_pipe[1]; | ||
| 4539 | - ret = host_pipe[0]; | ||
| 4540 | -#elif defined(TARGET_SH4) | ||
| 4541 | - ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; | ||
| 4542 | - ret = host_pipe[0]; | ||
| 4543 | -#else | ||
| 4544 | - if (put_user_s32(host_pipe[0], arg1) | ||
| 4545 | - || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0]))) | ||
| 4546 | - goto efault; | ||
| 4547 | -#endif | ||
| 4548 | - } | ||
| 4549 | - } | 4563 | + ret = do_pipe(cpu_env, arg1, 0); |
| 4564 | + break; | ||
| 4565 | +#ifdef TARGET_NR_pipe2 | ||
| 4566 | + case TARGET_NR_pipe2: | ||
| 4567 | + ret = do_pipe(cpu_env, arg1, arg2); | ||
| 4550 | break; | 4568 | break; |
| 4569 | +#endif | ||
| 4551 | case TARGET_NR_times: | 4570 | case TARGET_NR_times: |
| 4552 | { | 4571 | { |
| 4553 | struct target_tms *tmsp; | 4572 | struct target_tms *tmsp; |