linux-user: Support the epoll syscalls
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 <peter.maydell@linaro.org> Signed-off-by: Riku Voipio <riku.voipio@nokia.com>
This commit is contained in:
parent
d2ee72a5b1
commit
3b6edd1611
54
configure
vendored
54
configure
vendored
@ -2142,6 +2142,51 @@ if compile_prog "" "" ; then
|
||||
dup3=yes
|
||||
fi
|
||||
|
||||
# check for epoll support
|
||||
epoll=no
|
||||
cat > $TMPC << EOF
|
||||
#include <sys/epoll.h>
|
||||
|
||||
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 <sys/epoll.h>
|
||||
|
||||
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 <sys/epoll.h>
|
||||
|
||||
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
|
||||
@ -2674,6 +2719,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
|
||||
|
@ -66,6 +66,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
||||
#ifdef CONFIG_EVENTFD
|
||||
#include <sys/eventfd.h>
|
||||
#endif
|
||||
#ifdef CONFIG_EPOLL
|
||||
#include <sys/epoll.h>
|
||||
#endif
|
||||
|
||||
#define termios host_termios
|
||||
#define winsize host_winsize
|
||||
@ -7611,6 +7614,110 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#endif
|
||||
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:
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user