]> git.proxmox.com Git - qemu.git/commitdiff
The _exit syscall is used for both thread termination in NPTL applications,
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 7 Mar 2009 15:24:59 +0000 (15:24 +0000)
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 7 Mar 2009 15:24:59 +0000 (15:24 +0000)
and process termination in legacy applications.  Try to guess which we want
based on the presence of multiple threads.

Also implement locking when modifying the CPU list.

Signed-off-by: Paul Brook <paul@codesourcery.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6735 c046a42c-6fe2-441c-8c8c-71466251a162

15 files changed:
cpu-defs.h
exec.c
linux-user/main.c
linux-user/qemu.h
linux-user/signal.c
linux-user/syscall.c
target-alpha/cpu.h
target-arm/cpu.h
target-cris/cpu.h
target-i386/cpu.h
target-m68k/cpu.h
target-mips/cpu.h
target-ppc/cpu.h
target-sh4/cpu.h
target-sparc/cpu.h

index aa46fc3bce1f20eb78f9de4df301205a36ffa164..b462a9fa0c1f5ef72dd1e441d2f30968e0b62e50 100644 (file)
@@ -203,7 +203,7 @@ typedef struct CPUWatchpoint {
     jmp_buf jmp_env;                                                    \
     int exception_index;                                                \
                                                                         \
-    void *next_cpu; /* next CPU sharing TB cache */                     \
+    CPUState *next_cpu; /* next CPU sharing TB cache */                 \
     int cpu_index; /* CPU index (informative) */                        \
     int running; /* Nonzero if cpu is currently running(usermode).  */  \
     /* user data */                                                     \
diff --git a/exec.c b/exec.c
index 902031c48dfeab4ddfbd09b607a97b6be8c64779..ab9399116c1aeb9efd89e290a094f9abf42a5e5d 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -534,6 +534,9 @@ void cpu_exec_init(CPUState *env)
     CPUState **penv;
     int cpu_index;
 
+#if defined(CONFIG_USER_ONLY)
+    cpu_list_lock();
+#endif
     env->next_cpu = NULL;
     penv = &first_cpu;
     cpu_index = 0;
@@ -545,6 +548,9 @@ void cpu_exec_init(CPUState *env)
     TAILQ_INIT(&env->breakpoints);
     TAILQ_INIT(&env->watchpoints);
     *penv = env;
+#if defined(CONFIG_USER_ONLY)
+    cpu_list_unlock();
+#endif
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
     register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
                     cpu_common_save, cpu_common_load, env);
index 6e2984c44bbcba7cec744fcf4eaa150b01fb1fd5..2c1e4df6e5b8197e07c9b822d3ee6fe6e0ddfc0b 100644 (file)
@@ -143,6 +143,7 @@ int64_t cpu_get_real_ticks(void)
    We don't require a full sync, only that no cpus are executing guest code.
    The alternative is to map target atomic ops onto host equivalents,
    which requires quite a lot of per host/target work.  */
+static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER;
 static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER;
@@ -165,6 +166,7 @@ void fork_end(int child)
         thread_env->next_cpu = NULL;
         pending_cpus = 0;
         pthread_mutex_init(&exclusive_lock, NULL);
+        pthread_mutex_init(&cpu_list_mutex, NULL);
         pthread_cond_init(&exclusive_cond, NULL);
         pthread_cond_init(&exclusive_resume, NULL);
         pthread_mutex_init(&tb_lock, NULL);
@@ -237,6 +239,16 @@ static inline void cpu_exec_end(CPUState *env)
     exclusive_idle();
     pthread_mutex_unlock(&exclusive_lock);
 }
+
+void cpu_list_lock(void)
+{
+    pthread_mutex_lock(&cpu_list_mutex);
+}
+
+void cpu_list_unlock(void)
+{
+    pthread_mutex_unlock(&cpu_list_mutex);
+}
 #else /* if !USE_NPTL */
 /* These are no-ops because we are not threadsafe.  */
 static inline void cpu_exec_start(CPUState *env)
@@ -265,6 +277,14 @@ void fork_end(int child)
         gdbserver_fork(thread_env);
     }
 }
+
+void cpu_list_lock(void)
+{
+}
+
+void cpu_list_unlock(void)
+{
+}
 #endif
 
 
index 41375677fe4f66b10734471f13e0442e6c0b66b8..94ae3338e8b07b9280381dcb8733f0552db0ca34 100644 (file)
@@ -100,6 +100,9 @@ typedef struct TaskState {
     uint32_t v86flags;
     uint32_t v86mask;
 #endif
+#ifdef USE_NPTL
+    abi_ulong child_tidptr;
+#endif
 #ifdef TARGET_M68K
     int sim_syscalls;
 #endif
@@ -225,6 +228,8 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
 extern unsigned long last_brk;
 void mmap_lock(void);
 void mmap_unlock(void);
+void cpu_list_lock(void);
+void cpu_list_unlock(void);
 #if defined(USE_NPTL)
 void mmap_fork_start(void);
 void mmap_fork_end(int child);
index 4f3741e912235fb634bbc74c7b9b4f00ae80b085..48640ec835af256c55cf5458b504f327d27ba79d 100644 (file)
@@ -2691,7 +2691,7 @@ static int setup_sigcontext(struct target_sigcontext *sc,
     return err;
 }
 
-static int restore_sigcontext(struct CPUState *regs,
+static int restore_sigcontext(CPUState *regs,
                              struct target_sigcontext *sc)
 {
     unsigned int err = 0;
index 40eab4e624dc876ea2eb387d99fddd05581c142d..226ee6ca6e6b9f96086b2f98c7411948c82d7071 100644 (file)
@@ -156,7 +156,6 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,   \
 }
 
 
-#define __NR_sys_exit __NR_exit
 #define __NR_sys_uname __NR_uname
 #define __NR_sys_faccessat __NR_faccessat
 #define __NR_sys_fchmodat __NR_fchmodat
@@ -198,7 +197,6 @@ static int gettid(void) {
     return -ENOSYS;
 }
 #endif
-_syscall1(int,sys_exit,int,status)
 _syscall1(int,sys_uname,struct new_utsname *,buf)
 #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
 _syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
@@ -2936,7 +2934,10 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         nptl_flags = flags;
         flags &= ~CLONE_NPTL_FLAGS2;
 
-        /* TODO: Implement CLONE_CHILD_CLEARTID.  */
+        if (nptl_flags & CLONE_CHILD_CLEARTID) {
+            ts->child_tidptr = child_tidptr;
+        }
+
         if (nptl_flags & CLONE_SETTLS)
             cpu_set_tls (new_env, newtls);
 
@@ -2961,6 +2962,7 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
 
         ret = pthread_create(&info.thread, &attr, clone_func, &info);
+        /* TODO: Free new CPU state if thread creation failed.  */
 
         sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
         pthread_attr_destroy(&attr);
@@ -3011,7 +3013,8 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
             ts = (TaskState *)env->opaque;
             if (flags & CLONE_SETTLS)
                 cpu_set_tls (env, newtls);
-            /* TODO: Implement CLONE_CHILD_CLEARTID.  */
+            if (flags & CLONE_CHILD_CLEARTID)
+                ts->child_tidptr = child_tidptr;
 #endif
         } else {
             fork_end(0);
@@ -3428,12 +3431,46 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
     switch(num) {
     case TARGET_NR_exit:
+#ifdef USE_NPTL
+      /* In old applications this may be used to implement _exit(2).
+         However in threaded applictions it is used for thread termination,
+         and _exit_group is used for application termination.
+         Do thread termination if we have more then one thread.  */
+      /* FIXME: This probably breaks if a signal arrives.  We should probably
+         be disabling signals.  */
+      if (first_cpu->next_cpu) {
+          CPUState **lastp;
+          CPUState *p;
+
+          cpu_list_lock();
+          lastp = &first_cpu;
+          p = first_cpu;
+          while (p && p != (CPUState *)cpu_env) {
+              lastp = &p->next_cpu;
+              p = p->next_cpu;
+          }
+          /* If we didn't find the CPU for this thread then something is
+             horribly wrong.  */
+          if (!p)
+              abort();
+          /* Remove the CPU from the list.  */
+          *lastp = p->next_cpu;
+          cpu_list_unlock();
+          TaskState *ts = ((CPUState *)cpu_env)->opaque;
+          if (ts->child_tidptr) {
+              put_user_u32(0, ts->child_tidptr);
+              sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
+                        NULL, NULL, 0);
+          }
+          /* TODO: Free CPU state.  */
+          pthread_exit(NULL);
+      }
+#endif
 #ifdef HAVE_GPROF
         _mcleanup();
 #endif
         gdb_exit(cpu_env, arg1);
-        /* XXX: should free thread stack and CPU env */
-        sys_exit(arg1);
+        _exit(arg1);
         ret = 0; /* avoid warning */
         break;
     case TARGET_NR_read:
index a160760f8696b8ea6eb127323db70bce980d2488..3e0050714900c66107d3ac461b51d658f1f29670 100644 (file)
@@ -25,6 +25,8 @@
 
 #define TARGET_LONG_BITS 64
 
+#define CPUState struct CPUAlphaState
+
 #include "cpu-defs.h"
 
 #include <setjmp.h>
@@ -291,7 +293,6 @@ struct CPUAlphaState {
     pal_handler_t *pal_handler;
 };
 
-#define CPUState CPUAlphaState
 #define cpu_init cpu_alpha_init
 #define cpu_exec cpu_alpha_exec
 #define cpu_gen_code cpu_alpha_gen_code
index cab80cdfe6f42b889f999104d742b33bf18b89b5..f98655f8037d131abe7b51cca40a1927abb8e259 100644 (file)
@@ -24,6 +24,8 @@
 
 #define ELF_MACHINE    EM_ARM
 
+#define CPUState struct CPUARMState
+
 #include "cpu-defs.h"
 
 #include "softfloat.h"
@@ -398,7 +400,6 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define TARGET_PAGE_BITS 10
 #endif
 
-#define CPUState CPUARMState
 #define cpu_init cpu_arm_init
 #define cpu_exec cpu_arm_exec
 #define cpu_gen_code cpu_arm_gen_code
index 754953cda053c3fa990d4478bb641843eacc8f30..e98a48d658c9118e4f87850eeedd7d40476d0e11 100644 (file)
@@ -23,6 +23,8 @@
 
 #define TARGET_LONG_BITS 32
 
+#define CPUState struct CPUCRISState
+
 #include "cpu-defs.h"
 
 #define TARGET_HAS_ICE 1
@@ -199,7 +201,6 @@ enum {
 #define TARGET_PAGE_BITS 13
 #define MMAP_SHIFT TARGET_PAGE_BITS
 
-#define CPUState CPUCRISState
 #define cpu_init cpu_cris_init
 #define cpu_exec cpu_cris_exec
 #define cpu_gen_code cpu_cris_gen_code
index a6bbeb29be62823499ea713847403cb98866dda2..90bceab68f1249aaedab7507bc5ac2bccb8681c1 100644 (file)
@@ -42,6 +42,8 @@
 #define ELF_MACHINE    EM_386
 #endif
 
+#define CPUState struct CPUX86State
+
 #include "cpu-defs.h"
 
 #include "softfloat.h"
@@ -828,7 +830,6 @@ static inline int cpu_get_time_fast(void)
 
 #define TARGET_PAGE_BITS 12
 
-#define CPUState CPUX86State
 #define cpu_init cpu_x86_init
 #define cpu_exec cpu_x86_exec
 #define cpu_gen_code cpu_x86_gen_code
index 4f55a6e6812cb3441b8ec8a13df17222348c9a97..6a2aba480549fcb933078e33456a3a0cea586183 100644 (file)
@@ -23,6 +23,8 @@
 
 #define TARGET_LONG_BITS 32
 
+#define CPUState struct CPUM68KState
+
 #include "cpu-defs.h"
 
 #include "softfloat.h"
@@ -207,7 +209,6 @@ void register_m68k_insns (CPUM68KState *env);
 #define TARGET_PAGE_BITS 10
 #endif
 
-#define CPUState CPUM68KState
 #define cpu_init cpu_m68k_init
 #define cpu_exec cpu_m68k_exec
 #define cpu_gen_code cpu_m68k_gen_code
index 3fa0c3817bbbf34bae474f3728e208b1901bad95..eb32fb881d7201565efb691f10ca19c7fd89d15b 100644 (file)
@@ -5,6 +5,8 @@
 
 #define ELF_MACHINE    EM_MIPS
 
+#define CPUState struct CPUMIPSState
+
 #include "config.h"
 #include "mips-defs.h"
 #include "cpu-defs.h"
@@ -473,7 +475,6 @@ void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
                           int unused, int size);
 
-#define CPUState CPUMIPSState
 #define cpu_init cpu_mips_init
 #define cpu_exec cpu_mips_exec
 #define cpu_gen_code cpu_mips_gen_code
index bdc3cf974aedb0502c97c486eac0c5b56e12707b..fba5a8fec28620d108f0b63661703623f53f0ba4 100644 (file)
@@ -54,6 +54,8 @@
 
 #endif /* defined (TARGET_PPC64) */
 
+#define CPUState struct CPUPPCState
+
 #include "cpu-defs.h"
 
 #define REGX "%016" PRIx64
@@ -786,7 +788,6 @@ static always_inline uint64_t ppc_dump_gpr (CPUPPCState *env, int gprn)
 int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp);
 int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
 
-#define CPUState CPUPPCState
 #define cpu_init cpu_ppc_init
 #define cpu_exec cpu_ppc_exec
 #define cpu_gen_code cpu_ppc_gen_code
index c0215f8ae0420f5bb0440f301fdfde4632cf7ae8..aea7108fce1589c3532c6476c7e290130672572f 100644 (file)
@@ -37,6 +37,8 @@
 #define SH_CPU_SH7750_ALL (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7750R)
 #define SH_CPU_SH7751_ALL (SH_CPU_SH7751 | SH_CPU_SH7751R)
 
+#define CPUState struct CPUSH4State
+
 #include "cpu-defs.h"
 
 #include "softfloat.h"
@@ -169,7 +171,6 @@ void cpu_load_tlb(CPUSH4State * env);
 
 #include "softfloat.h"
 
-#define CPUState CPUSH4State
 #define cpu_init cpu_sh4_init
 #define cpu_exec cpu_sh4_exec
 #define cpu_gen_code cpu_sh4_gen_code
index 1fb249b65a86deefed2335796ba910b1eef0b769..8b847897ef796b69b475e0bc6a9638edf4245513 100644 (file)
@@ -15,6 +15,8 @@
 
 #define TARGET_PHYS_ADDR_BITS 64
 
+#define CPUState struct CPUSPARCState
+
 #include "cpu-defs.h"
 
 #include "softfloat.h"
@@ -436,7 +438,6 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
                           int is_asi, int size);
 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 
-#define CPUState CPUSPARCState
 #define cpu_init cpu_sparc_init
 #define cpu_exec cpu_sparc_exec
 #define cpu_gen_code cpu_sparc_gen_code