aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure29
-rw-r--r--linux-user/syscall.c61
2 files changed, 90 insertions, 0 deletions
diff --git a/configure b/configure
index b3d7fd8642..8eec675eec 100755
--- a/configure
+++ b/configure
@@ -112,6 +112,7 @@ darwin_user="no"
build_docs="no"
uname_release=""
curses="yes"
+nptl="yes"
# OS specific
targetos=`uname -s`
@@ -331,6 +332,8 @@ for opt do
;;
--disable-curses) curses="no"
;;
+ --disable-nptl) nptl="no"
+ ;;
*) echo "ERROR: unknown option $opt"; show_help="yes"
;;
esac
@@ -424,6 +427,7 @@ echo " --enable-dsound enable DirectSound audio driver"
echo " --disable-brlapi disable BrlAPI"
echo " --disable-vnc-tls disable TLS encryption for VNC server"
echo " --disable-curses disable curses output"
+echo " --disable-nptl disable usermode NPTL support"
echo " --enable-system enable all system emulation targets"
echo " --disable-system disable all system emulation targets"
echo " --enable-linux-user enable all linux usermode emulation targets"
@@ -641,6 +645,24 @@ int main(void) {
}
EOF
+# Check host NPTL support
+cat > $TMPC <<EOF
+#include <sched.h>
+#include <sys/futex.h>
+void foo()
+{
+#if !defined(CLONE_SETTLS) || !defined(FUTEX_WAIT)
+#error bork
+#endif
+}
+EOF
+
+if $cc $ARCH_CFLAGS -c -o $TMPO $TMPC 2> /dev/null ; then
+ :
+else
+ nptl="no"
+fi
+
##########################################
# SDL probe
@@ -839,6 +861,7 @@ echo "brlapi support $brlapi"
echo "Documentation $build_docs"
[ ! -z "$uname_release" ] && \
echo "uname -r $uname_release"
+echo "NPTL support $nptl"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -1190,6 +1213,7 @@ echo "#include \"../config-host.h\"" >> $config_h
bflt="no"
elfload32="no"
+target_nptl="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
@@ -1232,6 +1256,7 @@ case "$target_cpu" in
echo "#define TARGET_ARCH \"arm\"" >> $config_h
echo "#define TARGET_ARM 1" >> $config_h
bflt="yes"
+ target_nptl="yes"
;;
cris)
echo "TARGET_ARCH=cris" >> $config_mak
@@ -1379,6 +1404,10 @@ if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
echo "TARGET_HAS_BFLT=yes" >> $config_mak
echo "#define TARGET_HAS_BFLT 1" >> $config_h
fi
+if test "$target_user_only" = "yes" \
+ -a "$nptl" = "yes" -a "$target_nptl" = "yes"; then
+ echo "#define USE_NPTL 1" >> $config_h
+fi
# 32 bit ELF loader in addition to native 64 bit loader?
if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index fe97be1c9a..0c5f0a2ae9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -52,6 +52,9 @@
//#include <sys/user.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
+#if defined(USE_NPTL)
+#include <sys/futex.h>
+#endif
#define termios host_termios
#define winsize host_winsize
@@ -160,6 +163,7 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
#define __NR_sys_tkill __NR_tkill
#define __NR_sys_unlinkat __NR_unlinkat
#define __NR_sys_utimensat __NR_utimensat
+#define __NR_sys_futex __NR_futex
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
#define __NR__llseek __NR_lseek
@@ -241,6 +245,11 @@ _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
const struct timespec *,tsp,int,flags)
#endif
+#if defined(TARGET_NR_futex) && defined(__NR_futex)
+_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
+ const struct timespec *,timeout,int *,uaddr2,int,val3)
+
+#endif
extern int personality(int);
extern int flock(int, int);
@@ -2718,6 +2727,14 @@ int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp)
CPUState *new_env;
if (flags & CLONE_VM) {
+#if defined(USE_NPTL)
+ /* qemu is not threadsafe. Bail out immediately if application
+ tries to create a thread. */
+ if (!(flags & CLONE_VFORK)) {
+ gemu_log ("clone(CLONE_VM) not supported\n");
+ return -EINVAL;
+ }
+#endif
ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
memset(ts, 0, sizeof(TaskState));
new_stack = ts->stack;
@@ -3056,6 +3073,45 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
return 0;
}
+#if defined(USE_NPTL)
+/* ??? Using host futex calls even when target atomic operations
+ are not really atomic probably breaks things. However implementing
+ futexes locally would make futexes shared between multiple processes
+ tricky. However they're probably useless because guest atomic
+ operations won't work either. */
+int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
+ target_ulong uaddr2, int val3)
+{
+ struct timespec ts, *pts;
+
+ /* ??? We assume FUTEX_* constants are the same on both host
+ and target. */
+ switch (op) {
+ case FUTEX_WAIT:
+ if (timeout) {
+ pts = &ts;
+ target_to_host_timespec(pts, timeout);
+ } else {
+ pts = NULL;
+ }
+ return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
+ pts, NULL, 0));
+ case FUTEX_WAKE:
+ return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
+ case FUTEX_FD:
+ return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
+ case FUTEX_REQUEUE:
+ return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
+ NULL, g2h(uaddr2), 0));
+ case FUTEX_CMP_REQUEUE:
+ return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
+ NULL, g2h(uaddr2), tswap32(val3)));
+ default:
+ return -TARGET_ENOSYS;
+ }
+}
+#endif
+
int get_osversion(void)
{
static int osversion;
@@ -5614,6 +5670,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#if defined(USE_NPTL)
+ case TARGET_NR_futex:
+ ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+#endif
default:
unimplemented: