From patchwork Tue Feb 15 18:35:05 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 155 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:40:23 -0000 Delivered-To: patches@linaro.org Received: by 10.146.83.12 with SMTP id g12cs355447yab; Tue, 15 Feb 2011 10:35:10 -0800 (PST) Received: by 10.14.45.74 with SMTP id o50mr2671974eeb.28.1297794909121; Tue, 15 Feb 2011 10:35:09 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk [81.2.115.146]) by mx.google.com with ESMTPS id w11si8752118eeh.52.2011.02.15.10.35.08 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 15 Feb 2011 10:35:09 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) client-ip=81.2.115.146; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1PpPjt-0001Ug-4Y; Tue, 15 Feb 2011 18:35:05 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Riku Voipio Subject: [PATCH] linux-user: Support the epoll syscalls Date: Tue, 15 Feb 2011 18:35:05 +0000 Message-Id: <1297794905-5719-1-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.3 Support the epoll family of syscalls: epoll_create(), epoll_create1(), epoll_ctl(), epoll_wait() and epoll_pwait(). Note that epoll_create1() and epoll_pwait() are later additions, so we have to test separately in configure for their presence. Signed-off-by: Peter Maydell --- configure | 54 +++++++++++++++++++++++ linux-user/syscall.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ linux-user/syscall_defs.h | 13 +++++ 3 files changed, 174 insertions(+), 0 deletions(-) diff --git a/configure b/configure index 598e8e1..8b0fdcd 100755 --- a/configure +++ b/configure @@ -2136,6 +2136,51 @@ if compile_prog "" "" ; then dup3=yes fi +# check for epoll support +epoll=no +cat > $TMPC << EOF +#include + +int main(void) +{ + epoll_create(0); + return 0; +} +EOF +if compile_prog "$ARCH_CFLAGS" "" ; then + epoll=yes +fi + +# epoll_create1 and epoll_pwait are later additions +# so we must check separately for their presence +epoll_create1=no +cat > $TMPC << EOF +#include + +int main(void) +{ + epoll_create1(0); + return 0; +} +EOF +if compile_prog "$ARCH_CFLAGS" "" ; then + epoll_create1=yes +fi + +epoll_pwait=no +cat > $TMPC << EOF +#include + +int main(void) +{ + epoll_pwait(0, 0, 0, 0, 0); + return 0; +} +EOF +if compile_prog "$ARCH_CFLAGS" "" ; then + epoll_pwait=yes +fi + # Check if tools are available to build documentation. if test "$docs" != "no" ; then if has makeinfo && has pod2man; then @@ -2668,6 +2713,15 @@ fi if test "$dup3" = "yes" ; then echo "CONFIG_DUP3=y" >> $config_host_mak fi +if test "$epoll" = "yes" ; then + echo "CONFIG_EPOLL=y" >> $config_host_mak +fi +if test "$epoll_create1" = "yes" ; then + echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak +fi +if test "$epoll_pwait" = "yes" ; then + echo "CONFIG_EPOLL_PWAIT=y" >> $config_host_mak +fi if test "$inotify" = "yes" ; then echo "CONFIG_INOTIFY=y" >> $config_host_mak fi diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 4412a9b..cf8a4c3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -66,6 +66,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #ifdef CONFIG_EVENTFD #include #endif +#ifdef CONFIG_EPOLL +#include +#endif #define termios host_termios #define winsize host_winsize @@ -7612,6 +7615,110 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif #endif +#if defined(CONFIG_EPOLL) +#if defined(TARGET_NR_epoll_create) + case TARGET_NR_epoll_create: + ret = get_errno(epoll_create(arg1)); + break; +#endif +#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1) + case TARGET_NR_epoll_create1: + ret = get_errno(epoll_create1(arg1)); + break; +#endif +#if defined(TARGET_NR_epoll_ctl) + case TARGET_NR_epoll_ctl: + { + struct epoll_event ep; + struct epoll_event *epp = 0; + if (arg4) { + struct target_epoll_event *target_ep; + if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) { + goto efault; + } + ep.events = tswap32(target_ep->events); + /* The epoll_data_t union is just opaque data to the kernel, + * so we transfer all 64 bits across and need not worry what + * actual data type it is. + */ + ep.data.u64 = tswap64(target_ep->data.u64); + unlock_user_struct(target_ep, arg4, 0); + epp = &ep; + } + ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp)); + break; + } +#endif + +#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT) +#define IMPLEMENT_EPOLL_PWAIT +#endif +#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT) +#if defined(TARGET_NR_epoll_wait) + case TARGET_NR_epoll_wait: +#endif +#if defined(IMPLEMENT_EPOLL_PWAIT) + case TARGET_NR_epoll_pwait: +#endif + { + struct target_epoll_event *target_ep; + struct epoll_event *ep; + int epfd = arg1; + int maxevents = arg3; + int timeout = arg4; + + target_ep = lock_user(VERIFY_WRITE, arg2, + maxevents * sizeof(struct target_epoll_event), 1); + if (!target_ep) { + goto efault; + } + + ep = alloca(maxevents * sizeof(struct epoll_event)); + + switch (num) { +#if defined(IMPLEMENT_EPOLL_PWAIT) + case TARGET_NR_epoll_pwait: + { + target_sigset_t *target_set; + sigset_t _set, *set = &_set; + + if (arg5) { + target_set = lock_user(VERIFY_READ, arg5, + sizeof(target_sigset_t), 1); + if (!target_set) { + unlock_user(target_ep, arg2, 0); + goto efault; + } + target_to_host_sigset(set, target_set); + unlock_user(target_set, arg5, 0); + } else { + set = NULL; + } + + ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set)); + break; + } +#endif +#if defined(TARGET_NR_epoll_wait) + case TARGET_NR_epoll_wait: + ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout)); + break; +#endif + default: + ret = -TARGET_ENOSYS; + } + if (!is_error(ret)) { + int i; + for (i = 0; i < ret; i++) { + target_ep[i].events = tswap32(ep[i].events); + target_ep[i].data.u64 = tswap64(ep[i].data.u64); + } + } + unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event)); + break; + } +#endif +#endif default: unimplemented: gemu_log("qemu: Unsupported syscall: %d\n", num); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 4742ac0..702652c 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2206,3 +2206,16 @@ struct target_mq_attr { #define FUTEX_CLOCK_REALTIME 256 #define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) +#ifdef CONFIG_EPOLL +typedef union target_epoll_data { + abi_ulong ptr; + abi_ulong fd; + uint32_t u32; + uint64_t u64; +} target_epoll_data_t; + +struct target_epoll_event { + uint32_t events; + target_epoll_data_t data; +}; +#endif