Commit 099d6b0fe9e6d5855403d2d0a8ae800b7bdb24a7

Authored by Riku Voipio
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>
configure
... ... @@ -1304,6 +1304,24 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2&gt; /dev/null ; then
1304 1304 utimens=yes
1305 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 1325 # Check if tools are available to build documentation.
1308 1326 if test "$build_docs" = "yes" -a \( ! -x "`which texi2html 2>/dev/null`" -o ! -x "`which pod2man 2>/dev/null`" \) ; then
1309 1327 build_docs="no"
... ... @@ -1704,6 +1722,9 @@ fi
1704 1722 if test "$utimens" = "yes" ; then
1705 1723 echo "#define CONFIG_UTIMENSAT 1" >> $config_h
1706 1724 fi
  1725 +if test "$pipe2" = "yes" ; then
  1726 + echo "#define CONFIG_PIPE2 1" >> $config_h
  1727 +fi
1707 1728 if test "$inotify" = "yes" ; then
1708 1729 echo "#define CONFIG_INOTIFY 1" >> $config_h
1709 1730 fi
... ...
linux-user/syscall.c
... ... @@ -944,6 +944,37 @@ static abi_long do_select(int n,
944 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 978 static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
948 979 abi_ulong target_addr,
949 980 socklen_t len)
... ... @@ -4529,25 +4560,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4529 4560 ret = get_errno(dup(arg1));
4530 4561 break;
4531 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 4568 break;
  4569 +#endif
4551 4570 case TARGET_NR_times:
4552 4571 {
4553 4572 struct target_tms *tmsp;
... ...