diff mbox series

[v2,103/108] linux-user: Split out atomic_cmpxchg_32

Message ID 20180610030220.3777-104-richard.henderson@linaro.org
State New
Headers show
Series linux-user: Split do_syscall | expand

Commit Message

Richard Henderson June 10, 2018, 3:02 a.m. UTC
At the same time, make it atomic.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 linux-user/syscall.c | 47 ++++++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 21 deletions(-)

-- 
2.17.1
diff mbox series

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f898e70e98..5d60872587 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7560,6 +7560,29 @@  IMPL(atomic_barrier)
 }
 #endif
 
+#ifdef TARGET_NR_atomic_cmpxchg_32
+IMPL(atomic_cmpxchg_32)
+{
+    /* This is m68k specific.  */
+    uint32_t newval = arg1;
+    uint32_t oldval = arg2;
+    abi_ulong target_addr = arg6;
+    uint32_t *host_addr;
+
+    if (!access_ok(VERIFY_WRITE, target_addr, 4)) {
+        target_siginfo_t info;
+        info.si_signo = SIGSEGV;
+        info.si_errno = 0;
+        info.si_code = TARGET_SEGV_MAPERR;
+        info._sifields._sigfault._addr = target_addr;
+        queue_signal(cpu_env, info.si_signo, QEMU_SI_FAULT, &info);
+        return 0xdeadbeef;
+    }
+    host_addr = g2h(target_addr);
+    return atomic_cmpxchg(host_addr, oldval, newval);
+}
+#endif
+
 #ifdef TARGET_NR_bind
 IMPL(bind)
 {
@@ -13025,27 +13048,6 @@  static abi_long do_syscall1(void *cpu_env, unsigned num, abi_long arg1,
     abi_long ret;
 
     switch(num) {
-#ifdef TARGET_NR_atomic_cmpxchg_32
-    case TARGET_NR_atomic_cmpxchg_32:
-    {
-        /* should use start_exclusive from main.c */
-        abi_ulong mem_value;
-        if (get_user_u32(mem_value, arg6)) {
-            target_siginfo_t info;
-            info.si_signo = SIGSEGV;
-            info.si_errno = 0;
-            info.si_code = TARGET_SEGV_MAPERR;
-            info._sifields._sigfault._addr = arg6;
-            queue_signal((CPUArchState *)cpu_env, info.si_signo,
-                         QEMU_SI_FAULT, &info);
-            ret = 0xdeadbeef;
-
-        }
-        if (mem_value == arg2)
-            put_user_u32(arg1, arg6);
-        return mem_value;
-    }
-#endif
 #ifdef TARGET_NR_timer_create
     case TARGET_NR_timer_create:
     {
@@ -13299,6 +13301,9 @@  static impl_fn *syscall_table(unsigned num)
 #endif
 #ifdef TARGET_NR_atomic_barrier
         SYSCALL(atomic_barrier);
+#endif
+#ifdef TARGET_NR_atomic_cmpxchg_32
+        SYSCALL(atomic_cmpxchg_32);
 #endif
         SYSCALL(brk);
 #ifdef TARGET_NR_cacheflush