diff options
author | Riku Voipio <riku.voipio@iki.fi> | 2009-05-05 12:10:04 +0300 |
---|---|---|
committer | Riku Voipio <riku.voipio@nokia.com> | 2009-06-16 16:56:29 +0300 |
commit | 099d6b0fe9e6d5855403d2d0a8ae800b7bdb24a7 (patch) | |
tree | 5261676792ad13d698cadf660227bbaed8679a31 | |
parent | 4b627a236ada4c097cf8cb682a7ae393fb4a4e10 (diff) |
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>
-rwxr-xr-x | configure | 21 | ||||
-rw-r--r-- | linux-user/syscall.c | 55 |
2 files changed, 58 insertions, 18 deletions
@@ -1304,6 +1304,24 @@ if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then utimens=yes fi +# check if pipe2 is there +pipe2=no +cat > $TMPC << EOF +#define _GNU_SOURCE +#include <unistd.h> +#include <fcntl.h> + +int main(void) +{ + int pipefd[2]; + pipe2(pipefd, O_CLOEXEC); + return 0; +} +EOF +if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then + pipe2=yes +fi + # Check if tools are available to build documentation. if test "$build_docs" = "yes" -a \( ! -x "`which texi2html 2>/dev/null`" -o ! -x "`which pod2man 2>/dev/null`" \) ; then build_docs="no" @@ -1704,6 +1722,9 @@ fi if test "$utimens" = "yes" ; then echo "#define CONFIG_UTIMENSAT 1" >> $config_h fi +if test "$pipe2" = "yes" ; then + echo "#define CONFIG_PIPE2 1" >> $config_h +fi if test "$inotify" = "yes" ; then echo "#define CONFIG_INOTIFY 1" >> $config_h fi diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3fc6cbc7ca..36eb9f5b53 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -944,6 +944,37 @@ static abi_long do_select(int n, return ret; } +static abi_long do_pipe2(int host_pipe[], int flags) +{ +#ifdef CONFIG_PIPE2 + return pipe2(host_pipe, flags); +#else + return -ENOSYS; +#endif +} + +static abi_long do_pipe(void *cpu_env, int pipedes, int flags) +{ + int host_pipe[2]; + abi_long ret; + ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe); + + if (is_error(ret)) + return get_errno(ret); +#if defined(TARGET_MIPS) + ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1]; + ret = host_pipe[0]; +#elif defined(TARGET_SH4) + ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; + ret = host_pipe[0]; +#else + if (put_user_s32(host_pipe[0], pipedes) + || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0]))) + return -TARGET_EFAULT; +#endif + return get_errno(ret); +} + static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, abi_ulong target_addr, socklen_t len) @@ -4529,25 +4560,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(dup(arg1)); break; case TARGET_NR_pipe: - { - int host_pipe[2]; - ret = get_errno(pipe(host_pipe)); - if (!is_error(ret)) { -#if defined(TARGET_MIPS) - CPUMIPSState *env = (CPUMIPSState*)cpu_env; - env->active_tc.gpr[3] = host_pipe[1]; - ret = host_pipe[0]; -#elif defined(TARGET_SH4) - ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; - ret = host_pipe[0]; -#else - if (put_user_s32(host_pipe[0], arg1) - || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0]))) - goto efault; -#endif - } - } + ret = do_pipe(cpu_env, arg1, 0); + break; +#ifdef TARGET_NR_pipe2 + case TARGET_NR_pipe2: + ret = do_pipe(cpu_env, arg1, arg2); break; +#endif case TARGET_NR_times: { struct target_tms *tmsp; |