log: Add locking to large logging blocks

Reuse the existing locking provided by stdio to keep in_asm, cpu,
op, op_opt, op_ind, and out_asm as contiguous blocks.

While it isn't possible to interleave e.g. in_asm or op_opt logs
because of the TB lock protecting all code generation, it is
possible to interleave cpu logs, or to interleave a cpu dump with
an out_asm dump.

For mingw32, we appear to have no viable solution for this.  The locking
functions are not properly exported from the system runtime library.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2016-09-22 15:17:10 -07:00
parent 9acbf7d8ca
commit 1ee73216f4
25 changed files with 98 additions and 1 deletions

View File

@ -150,11 +150,13 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
&& qemu_log_in_addr_range(itb->pc)) {
qemu_log_lock();
#if defined(TARGET_I386)
log_cpu_state(cpu, CPU_DUMP_CCOP);
#else
log_cpu_state(cpu, 0);
#endif
qemu_log_unlock();
}
#endif /* DEBUG_DISAS */

2
exec.c
View File

@ -911,11 +911,13 @@ void cpu_abort(CPUState *cpu, const char *fmt, ...)
fprintf(stderr, "\n");
cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU | CPU_DUMP_CCOP);
if (qemu_log_separate()) {
qemu_log_lock();
qemu_log("qemu: fatal: ");
qemu_log_vprintf(fmt, ap2);
qemu_log("\n");
log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
qemu_log_flush();
qemu_log_unlock();
qemu_log_close();
}
va_end(ap2);

View File

@ -51,6 +51,22 @@ static inline bool qemu_loglevel_mask(int mask)
return (qemu_loglevel & mask) != 0;
}
/* Lock output for a series of related logs. Since this is not needed
* for a single qemu_log / qemu_log_mask / qemu_log_mask_and_addr, we
* assume that qemu_loglevel_mask has already been tested, and that
* qemu_loglevel is never set when qemu_logfile is unset.
*/
static inline void qemu_log_lock(void)
{
qemu_flockfile(qemu_logfile);
}
static inline void qemu_log_unlock(void)
{
qemu_funlockfile(qemu_logfile);
}
/* Logging functions: */
/* main logging function

View File

@ -87,4 +87,16 @@ void *qemu_alloc_stack(size_t *sz);
*/
void qemu_free_stack(void *stack, size_t sz);
/* POSIX and Mingw32 differ in the name of the stdio lock functions. */
static inline void qemu_flockfile(FILE *f)
{
flockfile(f);
}
static inline void qemu_funlockfile(FILE *f)
{
funlockfile(f);
}
#endif

View File

@ -103,6 +103,21 @@ static inline char *realpath(const char *path, char *resolved_path)
return resolved_path;
}
/* ??? Mingw appears to export _lock_file and _unlock_file as the functions
* with which to lock a stdio handle. But something is wrong in the markup,
* either in the header or the library, such that we get undefined references
* to "_imp___lock_file" etc when linking. Since we seem to have no other
* alternative, and the usage within the logging functions isn't critical,
* ignore FILE locking.
*/
static inline void qemu_flockfile(FILE *f)
{
}
static inline void qemu_funlockfile(FILE *f)
{
}
/* We wrap all the sockets functions so that we can
* set errno based on WSAGetLastError()

View File

@ -2994,9 +2994,11 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, ctx.pc - pc_start, 1);
qemu_log("\n");
qemu_log_unlock();
}
#endif
}

View File

@ -11420,11 +11420,13 @@ done_generating:
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start,
4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
qemu_log("\n");
qemu_log_unlock();
}
#endif
tb->size = dc->pc - pc_start;

View File

@ -11963,11 +11963,13 @@ done_generating:
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start,
dc->thumb | (dc->sctlr_b << 1));
qemu_log("\n");
qemu_log_unlock();
}
#endif
tb->size = dc->pc - pc_start;

View File

@ -3290,12 +3290,14 @@ void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
#if !DISAS_CRIS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("--------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start,
env->pregs[PR_VR]);
qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
}
#endif
#endif

View File

@ -2432,11 +2432,13 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
if (qemu_loglevel_mask(LOG_UNIMP)) {
target_ulong pc = s->pc_start, end = s->pc;
qemu_log_lock();
qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
for (; pc < end; ++pc) {
qemu_log(" %02x", cpu_ldub_code(env, pc));
}
qemu_log("\n");
qemu_log_unlock();
}
}
@ -8470,6 +8472,7 @@ done_generating:
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
int disas_flags;
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
#ifdef TARGET_X86_64
@ -8480,6 +8483,7 @@ done_generating:
disas_flags = !dc->code32;
log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
qemu_log("\n");
qemu_log_unlock();
}
#endif

View File

@ -1148,10 +1148,12 @@ void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("\n");
log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
}
#endif
}

View File

@ -3549,10 +3549,12 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
qemu_log("\n");
qemu_log_unlock();
}
#endif
tb->size = dc->pc - pc_start;

View File

@ -1813,12 +1813,14 @@ void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
#if !SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("--------------\n");
#if DISAS_GNU
log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
#endif
qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
}
#endif
#endif

View File

@ -20043,9 +20043,11 @@ done_generating:
LOG_DISAS("\n");
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
qemu_log("\n");
qemu_log_unlock();
}
#endif
}

View File

@ -1750,11 +1750,13 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
}
#endif
}

View File

@ -7211,9 +7211,11 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
int flags;
flags = env->bfd_mach;
flags |= ctx.le_mode << 16;
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, ctx.nip - pc_start, flags);
qemu_log("\n");
qemu_log_unlock();
}
#endif
}

View File

@ -5432,9 +5432,11 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
#if defined(S390X_DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc.pc - pc_start, 1);
qemu_log("\n");
qemu_log_unlock();
}
#endif
}

View File

@ -1927,9 +1927,11 @@ void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */
log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
qemu_log("\n");
qemu_log_unlock();
}
#endif
}

View File

@ -5796,10 +5796,12 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("--------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, last_pc + 4 - pc_start, 0);
qemu_log("\n");
qemu_log_unlock();
}
#endif
}

View File

@ -2391,6 +2391,7 @@ void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)
TCGV_UNUSED_I64(dc->zero);
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
}
if (!max_insns) {
@ -2429,7 +2430,10 @@ void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)
tb->size = dc->pc - pc_start;
tb->icount = num_insns;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "\n");
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("\n");
qemu_log_unlock();
}
}
void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb,

View File

@ -8789,9 +8789,11 @@ void gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
qemu_log("\n");
qemu_log_unlock();
}
#endif
}

View File

@ -2024,10 +2024,12 @@ done_generating:
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
qemu_log("\n");
qemu_log_unlock();
}
#endif
tb->size = dc->pc - pc_start;

View File

@ -3155,10 +3155,12 @@ void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc.pc - pc_start, 0);
qemu_log("\n");
qemu_log_unlock();
}
#endif
tb->size = dc.pc - pc_start;

View File

@ -412,10 +412,12 @@ void tcg_prologue_init(TCGContext *s)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
qemu_log_lock();
qemu_log("PROLOGUE: [size=%zu]\n", prologue_size);
log_disas(buf0, prologue_size);
qemu_log("\n");
qemu_log_flush();
qemu_log_unlock();
}
#endif
}
@ -2542,9 +2544,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
&& qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock();
qemu_log("OP:\n");
tcg_dump_ops(s);
qemu_log("\n");
qemu_log_unlock();
}
#endif
@ -2570,9 +2574,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
&& qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock();
qemu_log("OP before indirect lowering:\n");
tcg_dump_ops(s);
qemu_log("\n");
qemu_log_unlock();
}
#endif
/* Replace indirect temps with direct temps. */
@ -2590,9 +2596,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
&& qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock();
qemu_log("OP after optimization and liveness analysis:\n");
tcg_dump_ops(s);
qemu_log("\n");
qemu_log_unlock();
}
#endif

View File

@ -1355,10 +1355,12 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
qemu_log_in_addr_range(tb->pc)) {
qemu_log_lock();
qemu_log("OUT: [size=%d]\n", gen_code_size);
log_disas(tb->tc_ptr, gen_code_size);
qemu_log("\n");
qemu_log_flush();
qemu_log_unlock();
}
#endif