From c0ce998e94fadb7fdc83dbc7455372af933f8fa9 Mon Sep 17 00:00:00 2001 From: aliguori Date: Tue, 25 Nov 2008 22:13:57 +0000 Subject: [PATCH] Use sys-queue.h for break/watchpoint managment (Jan Kiszka) This switches cpu_break/watchpoint_* to TAILQ wrappers, simplifying the code and also fixing a use after release issue in cpu_break/watchpoint_remove_all. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5799 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-defs.h | 9 +++-- cpu-exec.c | 2 +- exec.c | 84 ++++++++++++---------------------------- target-alpha/translate.c | 4 +- target-arm/translate.c | 4 +- target-cris/translate.c | 4 +- target-i386/helper.c | 2 +- target-i386/translate.c | 4 +- target-m68k/translate.c | 4 +- target-mips/translate.c | 4 +- target-ppc/translate.c | 4 +- target-sh4/translate.c | 4 +- target-sparc/translate.c | 4 +- 13 files changed, 49 insertions(+), 84 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 069d312e1e7c..6eee88173dbd 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -28,6 +28,7 @@ #include #include #include "osdep.h" +#include "sys-queue.h" #ifndef TARGET_LONG_BITS #error TARGET_LONG_BITS must be defined before including this header @@ -146,14 +147,14 @@ struct KVMState; typedef struct CPUBreakpoint { target_ulong pc; int flags; /* BP_* */ - struct CPUBreakpoint *prev, *next; + TAILQ_ENTRY(CPUBreakpoint) entry; } CPUBreakpoint; typedef struct CPUWatchpoint { target_ulong vaddr; target_ulong len_mask; int flags; /* BP_* */ - struct CPUWatchpoint *prev, *next; + TAILQ_ENTRY(CPUWatchpoint) entry; } CPUWatchpoint; #define CPU_TEMP_BUF_NLONGS 128 @@ -188,10 +189,10 @@ typedef struct CPUWatchpoint { \ /* from this point: preserved by CPU reset */ \ /* ice debug support */ \ - CPUBreakpoint *breakpoints; \ + TAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \ int singlestep_enabled; \ \ - CPUWatchpoint *watchpoints; \ + TAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \ CPUWatchpoint *watchpoint_hit; \ \ struct GDBRegisterState *gdb_regs; \ diff --git a/cpu-exec.c b/cpu-exec.c index 05deafbdd2c5..a3d672511717 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -198,7 +198,7 @@ static void cpu_handle_debug_exception(CPUState *env) CPUWatchpoint *wp; if (!env->watchpoint_hit) - for (wp = env->watchpoints; wp != NULL; wp = wp->next) + TAILQ_FOREACH(wp, &env->watchpoints, entry) wp->flags &= ~BP_WATCHPOINT_HIT; if (debug_excp_handler) diff --git a/exec.c b/exec.c index 43a1b78f4639..3523c9577ebe 100644 --- a/exec.c +++ b/exec.c @@ -537,6 +537,8 @@ void cpu_exec_init(CPUState *env) cpu_index++; } env->cpu_index = cpu_index; + TAILQ_INIT(&env->breakpoints); + TAILQ_INIT(&env->watchpoints); *penv = env; #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION, @@ -1302,7 +1304,7 @@ int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len, int flags, CPUWatchpoint **watchpoint) { target_ulong len_mask = ~(len - 1); - CPUWatchpoint *wp, *prev_wp; + CPUWatchpoint *wp; /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */ if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) { @@ -1319,25 +1321,10 @@ int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len, wp->flags = flags; /* keep all GDB-injected watchpoints in front */ - if (!(flags & BP_GDB) && env->watchpoints) { - prev_wp = env->watchpoints; - while (prev_wp->next != NULL && (prev_wp->next->flags & BP_GDB)) - prev_wp = prev_wp->next; - } else { - prev_wp = NULL; - } - - /* Insert new watchpoint */ - if (prev_wp) { - wp->next = prev_wp->next; - prev_wp->next = wp; - } else { - wp->next = env->watchpoints; - env->watchpoints = wp; - } - if (wp->next) - wp->next->prev = wp; - wp->prev = prev_wp; + if (flags & BP_GDB) + TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry); + else + TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry); tlb_flush_page(env, addr); @@ -1353,7 +1340,7 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len, target_ulong len_mask = ~(len - 1); CPUWatchpoint *wp; - for (wp = env->watchpoints; wp != NULL; wp = wp->next) { + TAILQ_FOREACH(wp, &env->watchpoints, entry) { if (addr == wp->vaddr && len_mask == wp->len_mask && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { cpu_watchpoint_remove_by_ref(env, wp); @@ -1366,12 +1353,7 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len, /* Remove a specific watchpoint by reference. */ void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint) { - if (watchpoint->next) - watchpoint->next->prev = watchpoint->prev; - if (watchpoint->prev) - watchpoint->prev->next = watchpoint->next; - else - env->watchpoints = watchpoint->next; + TAILQ_REMOVE(&env->watchpoints, watchpoint, entry); tlb_flush_page(env, watchpoint->vaddr); @@ -1381,11 +1363,12 @@ void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint) /* Remove all matching watchpoints. */ void cpu_watchpoint_remove_all(CPUState *env, int mask) { - CPUWatchpoint *wp; + CPUWatchpoint *wp, *next; - for (wp = env->watchpoints; wp != NULL; wp = wp->next) + TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) { if (wp->flags & mask) cpu_watchpoint_remove_by_ref(env, wp); + } } /* Add a breakpoint. */ @@ -1393,7 +1376,7 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, CPUBreakpoint **breakpoint) { #if defined(TARGET_HAS_ICE) - CPUBreakpoint *bp, *prev_bp; + CPUBreakpoint *bp; bp = qemu_malloc(sizeof(*bp)); if (!bp) @@ -1403,25 +1386,10 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, bp->flags = flags; /* keep all GDB-injected breakpoints in front */ - if (!(flags & BP_GDB) && env->breakpoints) { - prev_bp = env->breakpoints; - while (prev_bp->next != NULL && (prev_bp->next->flags & BP_GDB)) - prev_bp = prev_bp->next; - } else { - prev_bp = NULL; - } - - /* Insert new breakpoint */ - if (prev_bp) { - bp->next = prev_bp->next; - prev_bp->next = bp; - } else { - bp->next = env->breakpoints; - env->breakpoints = bp; - } - if (bp->next) - bp->next->prev = bp; - bp->prev = prev_bp; + if (flags & BP_GDB) + TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry); + else + TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry); breakpoint_invalidate(env, pc); @@ -1439,7 +1407,7 @@ int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags) #if defined(TARGET_HAS_ICE) CPUBreakpoint *bp; - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == pc && bp->flags == flags) { cpu_breakpoint_remove_by_ref(env, bp); return 0; @@ -1455,12 +1423,7 @@ int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags) void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint) { #if defined(TARGET_HAS_ICE) - if (breakpoint->next) - breakpoint->next->prev = breakpoint->prev; - if (breakpoint->prev) - breakpoint->prev->next = breakpoint->next; - else - env->breakpoints = breakpoint->next; + TAILQ_REMOVE(&env->breakpoints, breakpoint, entry); breakpoint_invalidate(env, breakpoint->pc); @@ -1472,11 +1435,12 @@ void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint) void cpu_breakpoint_remove_all(CPUState *env, int mask) { #if defined(TARGET_HAS_ICE) - CPUBreakpoint *bp; + CPUBreakpoint *bp, *next; - for (bp = env->breakpoints; bp != NULL; bp = bp->next) + TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) { if (bp->flags & mask) cpu_breakpoint_remove_by_ref(env, bp); + } #endif } @@ -2005,7 +1969,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, code_address = address; /* Make accesses to pages with watchpoints go via the watchpoint trap routines. */ - for (wp = env->watchpoints; wp != NULL; wp = wp->next) { + TAILQ_FOREACH(wp, &env->watchpoints, entry) { if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { iotlb = io_mem_watch + paddr; /* TODO: The memory case can be optimized by not trapping @@ -2552,7 +2516,7 @@ static void check_watchpoint(int offset, int len_mask, int flags) return; } vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset; - for (wp = env->watchpoints; wp != NULL; wp = wp->next) { + TAILQ_FOREACH(wp, &env->watchpoints, entry) { if ((vaddr == (wp->vaddr & len_mask) || (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { wp->flags |= BP_WATCHPOINT_HIT; diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 3b90f6292232..7a0e54febfba 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2363,8 +2363,8 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, gen_icount_start(); for (ret = 0; ret == 0;) { - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == ctx.pc) { gen_excp(&ctx, EXCP_DEBUG, 0); break; diff --git a/target-arm/translate.c b/target-arm/translate.c index 54eb0670b51f..f984de7c5191 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -8677,8 +8677,8 @@ static inline void gen_intermediate_code_internal(CPUState *env, } #endif - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == dc->pc) { gen_set_condexec(dc); gen_set_pc_im(dc->pc); diff --git a/target-cris/translate.c b/target-cris/translate.c index ac258a9deb66..242ef9c1083b 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3189,8 +3189,8 @@ static void check_breakpoint(CPUState *env, DisasContext *dc) { CPUBreakpoint *bp; - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == dc->pc) { cris_evaluate_flags (dc); tcg_gen_movi_tl(env_pc, dc->pc); diff --git a/target-i386/helper.c b/target-i386/helper.c index 2a61cb0cc8f6..037540d79033 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1364,7 +1364,7 @@ static void breakpoint_handler(CPUState *env) cpu_resume_from_signal(env, NULL); } } else { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) + TAILQ_FOREACH(bp, &env->breakpoints, entry) if (bp->pc == env->eip) { if (bp->flags & BP_CPU) { check_hw_breakpoints(env, 1); diff --git a/target-i386/translate.c b/target-i386/translate.c index 0de238b57597..612811b0281a 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7606,8 +7606,8 @@ static inline void gen_intermediate_code_internal(CPUState *env, gen_icount_start(); for(;;) { - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == pc_ptr) { gen_debug(dc, pc_ptr - dc->cs_base); break; diff --git a/target-m68k/translate.c b/target-m68k/translate.c index a14f6c560ca3..5c27a7e6bbf6 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2999,8 +2999,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, do { pc_offset = dc->pc - pc_start; gen_throws_exception = NULL; - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == dc->pc) { gen_exception(dc, dc->pc, EXCP_DEBUG); dc->is_jmp = DISAS_JUMP; diff --git a/target-mips/translate.c b/target-mips/translate.c index cc7e71c5750a..418b9ef5da32 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -8286,8 +8286,8 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, #endif gen_icount_start(); while (ctx.bstate == BS_NONE) { - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == ctx.pc) { save_cpu_state(&ctx, 1); ctx.bstate = BS_BRANCH; diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 04d3fa0c65fd..69c67712a3eb 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -7562,8 +7562,8 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, gen_icount_start(); /* Set env in case of segfault during code fetch */ while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) { - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == ctx.nip) { gen_update_nip(&ctx, ctx.nip); gen_helper_raise_debug(); diff --git a/target-sh4/translate.c b/target-sh4/translate.c index bbfd74573dd5..505b19690f47 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1776,8 +1776,8 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, max_insns = CF_COUNT_MASK; gen_icount_start(); while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (ctx.pc == bp->pc) { /* We have hit a breakpoint - make sure PC is up-to-date */ tcg_gen_movi_i32(cpu_pc, ctx.pc); diff --git a/target-sparc/translate.c b/target-sparc/translate.c index e94e3c536cd1..07b2624b0c88 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -4816,8 +4816,8 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, max_insns = CF_COUNT_MASK; gen_icount_start(); do { - if (unlikely(env->breakpoints)) { - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { + TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == dc->pc) { if (dc->pc != pc_start) save_state(dc, cpu_cond);