diff options
author | Alexander Graf <agraf@suse.de> | 2012-07-05 17:31:39 +0200 |
---|---|---|
committer | hyokeun <hyokeun.jeon@samsung.com> | 2016-09-06 15:55:32 +0900 |
commit | 1336233c814d00a5f90b22e28058c3f848bbb985 (patch) | |
tree | abd8023a43a814c9b07e1d5831a38aad7de2e081 | |
parent | b52bb5365686c78fb8c0945eddcacc0da0efdb4a (diff) | |
download | qemu-1336233c814d00a5f90b22e28058c3f848bbb985.tar.gz qemu-1336233c814d00a5f90b22e28058c3f848bbb985.tar.bz2 qemu-1336233c814d00a5f90b22e28058c3f848bbb985.zip |
linux-user: lock tcg
The tcg code generator is not thread safe. Lock its generation between
different threads.
Signed-off-by: Alexander Graf <agraf@suse.de>
[AF: Rebased onto exec.c/translate-all.c split for 1.4]
[AF: Rebased for v2.1.0-rc0]
[AF: Rebased onto tcg_gen_code_common() drop for v2.5.0-rc0]
[AF: Rebased for v2.7.0-rc2]
Signed-off-by: Andreas Färber <afaerber@suse.de>
-rw-r--r-- | linux-user/mmap.c | 3 | ||||
-rw-r--r-- | tcg/tcg.c | 29 | ||||
-rw-r--r-- | tcg/tcg.h | 6 |
3 files changed, 38 insertions, 0 deletions
diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 68a655e63..d202e453f 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -22,6 +22,7 @@ #include "qemu.h" #include "qemu-common.h" +#include "tcg.h" #include "translate-all.h" //#define DEBUG_MMAP @@ -33,6 +34,7 @@ void mmap_lock(void) { if (mmap_lock_count++ == 0) { pthread_mutex_lock(&mmap_mutex); + tcg_lock(); } } @@ -40,6 +42,7 @@ void mmap_unlock(void) { if (--mmap_lock_count == 0) { pthread_mutex_unlock(&mmap_mutex); + tcg_unlock(); } } @@ -33,6 +33,8 @@ #include "qemu/cutils.h" #include "qemu/host-utils.h" #include "qemu/timer.h" +#include "config-host.h" +#include "qemu/thread.h" /* Note: the long term plan is to reduce the dependencies on the QEMU CPU definitions. Currently they are used for qemu_ld/st @@ -120,6 +122,29 @@ static bool tcg_out_tb_finalize(TCGContext *s); static TCGRegSet tcg_target_available_regs[2]; static TCGRegSet tcg_target_call_clobber_regs; +#ifdef CONFIG_USER_ONLY +static __thread int tcg_lock_count; +#endif +void tcg_lock(void) +{ +#ifdef CONFIG_USER_ONLY + TCGContext *s = &tcg_ctx; + if (tcg_lock_count++ == 0) { + qemu_mutex_lock(&s->lock); + } +#endif +} + +void tcg_unlock(void) +{ +#ifdef CONFIG_USER_ONLY + TCGContext *s = &tcg_ctx; + if (--tcg_lock_count == 0) { + qemu_mutex_unlock(&s->lock); + } +#endif +} + #if TCG_TARGET_INSN_UNIT_SIZE == 1 static __attribute__((unused)) inline void tcg_out8(TCGContext *s, uint8_t v) { @@ -332,6 +357,7 @@ void tcg_context_init(TCGContext *s) memset(s, 0, sizeof(*s)); s->nb_globals = 0; + qemu_mutex_init(&s->lock); /* Count total number of arguments and allocate the corresponding space */ @@ -2551,6 +2577,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) qemu_log("\n"); } #endif + tcg_lock(); #ifdef CONFIG_PROFILER s->opt_time -= profile_getclock(); @@ -2673,6 +2700,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) the buffer completely. Thus we can test for overflow after generating code without having to check during generation. */ if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) { + tcg_unlock(); return -1; } } @@ -2686,6 +2714,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) /* flush instruction cache */ flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr); + tcg_unlock(); return tcg_current_code_size(s); } @@ -29,6 +29,7 @@ #include "cpu.h" #include "exec/tb-context.h" #include "qemu/bitops.h" +#include "qemu/thread.h" #include "tcg-target.h" /* XXX: make safe guess about sizes */ @@ -697,6 +698,8 @@ struct TCGContext { uint16_t gen_insn_end_off[TCG_MAX_INSNS]; target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS]; + + QemuMutex lock; }; extern TCGContext tcg_ctx; @@ -904,6 +907,9 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, TCGOpcode opc, int narg); void tcg_optimize(TCGContext *s); +extern void tcg_lock(void); +extern void tcg_unlock(void); + /* only used for debugging purposes */ void tcg_dump_ops(TCGContext *s); |