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 | 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; | ... | ... |