Commit c0ce998e94fadb7fdc83dbc7455372af933f8fa9
1 parent
31280d92
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 <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5799 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
13 changed files
with
49 additions
and
84 deletions
cpu-defs.h
... | ... | @@ -28,6 +28,7 @@ |
28 | 28 | #include <setjmp.h> |
29 | 29 | #include <inttypes.h> |
30 | 30 | #include "osdep.h" |
31 | +#include "sys-queue.h" | |
31 | 32 | |
32 | 33 | #ifndef TARGET_LONG_BITS |
33 | 34 | #error TARGET_LONG_BITS must be defined before including this header |
... | ... | @@ -146,14 +147,14 @@ struct KVMState; |
146 | 147 | typedef struct CPUBreakpoint { |
147 | 148 | target_ulong pc; |
148 | 149 | int flags; /* BP_* */ |
149 | - struct CPUBreakpoint *prev, *next; | |
150 | + TAILQ_ENTRY(CPUBreakpoint) entry; | |
150 | 151 | } CPUBreakpoint; |
151 | 152 | |
152 | 153 | typedef struct CPUWatchpoint { |
153 | 154 | target_ulong vaddr; |
154 | 155 | target_ulong len_mask; |
155 | 156 | int flags; /* BP_* */ |
156 | - struct CPUWatchpoint *prev, *next; | |
157 | + TAILQ_ENTRY(CPUWatchpoint) entry; | |
157 | 158 | } CPUWatchpoint; |
158 | 159 | |
159 | 160 | #define CPU_TEMP_BUF_NLONGS 128 |
... | ... | @@ -188,10 +189,10 @@ typedef struct CPUWatchpoint { |
188 | 189 | \ |
189 | 190 | /* from this point: preserved by CPU reset */ \ |
190 | 191 | /* ice debug support */ \ |
191 | - CPUBreakpoint *breakpoints; \ | |
192 | + TAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \ | |
192 | 193 | int singlestep_enabled; \ |
193 | 194 | \ |
194 | - CPUWatchpoint *watchpoints; \ | |
195 | + TAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \ | |
195 | 196 | CPUWatchpoint *watchpoint_hit; \ |
196 | 197 | \ |
197 | 198 | struct GDBRegisterState *gdb_regs; \ | ... | ... |
cpu-exec.c
... | ... | @@ -198,7 +198,7 @@ static void cpu_handle_debug_exception(CPUState *env) |
198 | 198 | CPUWatchpoint *wp; |
199 | 199 | |
200 | 200 | if (!env->watchpoint_hit) |
201 | - for (wp = env->watchpoints; wp != NULL; wp = wp->next) | |
201 | + TAILQ_FOREACH(wp, &env->watchpoints, entry) | |
202 | 202 | wp->flags &= ~BP_WATCHPOINT_HIT; |
203 | 203 | |
204 | 204 | if (debug_excp_handler) | ... | ... |
exec.c
... | ... | @@ -537,6 +537,8 @@ void cpu_exec_init(CPUState *env) |
537 | 537 | cpu_index++; |
538 | 538 | } |
539 | 539 | env->cpu_index = cpu_index; |
540 | + TAILQ_INIT(&env->breakpoints); | |
541 | + TAILQ_INIT(&env->watchpoints); | |
540 | 542 | *penv = env; |
541 | 543 | #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) |
542 | 544 | 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, |
1302 | 1304 | int flags, CPUWatchpoint **watchpoint) |
1303 | 1305 | { |
1304 | 1306 | target_ulong len_mask = ~(len - 1); |
1305 | - CPUWatchpoint *wp, *prev_wp; | |
1307 | + CPUWatchpoint *wp; | |
1306 | 1308 | |
1307 | 1309 | /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */ |
1308 | 1310 | 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, |
1319 | 1321 | wp->flags = flags; |
1320 | 1322 | |
1321 | 1323 | /* keep all GDB-injected watchpoints in front */ |
1322 | - if (!(flags & BP_GDB) && env->watchpoints) { | |
1323 | - prev_wp = env->watchpoints; | |
1324 | - while (prev_wp->next != NULL && (prev_wp->next->flags & BP_GDB)) | |
1325 | - prev_wp = prev_wp->next; | |
1326 | - } else { | |
1327 | - prev_wp = NULL; | |
1328 | - } | |
1329 | - | |
1330 | - /* Insert new watchpoint */ | |
1331 | - if (prev_wp) { | |
1332 | - wp->next = prev_wp->next; | |
1333 | - prev_wp->next = wp; | |
1334 | - } else { | |
1335 | - wp->next = env->watchpoints; | |
1336 | - env->watchpoints = wp; | |
1337 | - } | |
1338 | - if (wp->next) | |
1339 | - wp->next->prev = wp; | |
1340 | - wp->prev = prev_wp; | |
1324 | + if (flags & BP_GDB) | |
1325 | + TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry); | |
1326 | + else | |
1327 | + TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry); | |
1341 | 1328 | |
1342 | 1329 | tlb_flush_page(env, addr); |
1343 | 1330 | |
... | ... | @@ -1353,7 +1340,7 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len, |
1353 | 1340 | target_ulong len_mask = ~(len - 1); |
1354 | 1341 | CPUWatchpoint *wp; |
1355 | 1342 | |
1356 | - for (wp = env->watchpoints; wp != NULL; wp = wp->next) { | |
1343 | + TAILQ_FOREACH(wp, &env->watchpoints, entry) { | |
1357 | 1344 | if (addr == wp->vaddr && len_mask == wp->len_mask |
1358 | 1345 | && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { |
1359 | 1346 | cpu_watchpoint_remove_by_ref(env, wp); |
... | ... | @@ -1366,12 +1353,7 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len, |
1366 | 1353 | /* Remove a specific watchpoint by reference. */ |
1367 | 1354 | void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint) |
1368 | 1355 | { |
1369 | - if (watchpoint->next) | |
1370 | - watchpoint->next->prev = watchpoint->prev; | |
1371 | - if (watchpoint->prev) | |
1372 | - watchpoint->prev->next = watchpoint->next; | |
1373 | - else | |
1374 | - env->watchpoints = watchpoint->next; | |
1356 | + TAILQ_REMOVE(&env->watchpoints, watchpoint, entry); | |
1375 | 1357 | |
1376 | 1358 | tlb_flush_page(env, watchpoint->vaddr); |
1377 | 1359 | |
... | ... | @@ -1381,11 +1363,12 @@ void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint) |
1381 | 1363 | /* Remove all matching watchpoints. */ |
1382 | 1364 | void cpu_watchpoint_remove_all(CPUState *env, int mask) |
1383 | 1365 | { |
1384 | - CPUWatchpoint *wp; | |
1366 | + CPUWatchpoint *wp, *next; | |
1385 | 1367 | |
1386 | - for (wp = env->watchpoints; wp != NULL; wp = wp->next) | |
1368 | + TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) { | |
1387 | 1369 | if (wp->flags & mask) |
1388 | 1370 | cpu_watchpoint_remove_by_ref(env, wp); |
1371 | + } | |
1389 | 1372 | } |
1390 | 1373 | |
1391 | 1374 | /* Add a breakpoint. */ |
... | ... | @@ -1393,7 +1376,7 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, |
1393 | 1376 | CPUBreakpoint **breakpoint) |
1394 | 1377 | { |
1395 | 1378 | #if defined(TARGET_HAS_ICE) |
1396 | - CPUBreakpoint *bp, *prev_bp; | |
1379 | + CPUBreakpoint *bp; | |
1397 | 1380 | |
1398 | 1381 | bp = qemu_malloc(sizeof(*bp)); |
1399 | 1382 | if (!bp) |
... | ... | @@ -1403,25 +1386,10 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, |
1403 | 1386 | bp->flags = flags; |
1404 | 1387 | |
1405 | 1388 | /* keep all GDB-injected breakpoints in front */ |
1406 | - if (!(flags & BP_GDB) && env->breakpoints) { | |
1407 | - prev_bp = env->breakpoints; | |
1408 | - while (prev_bp->next != NULL && (prev_bp->next->flags & BP_GDB)) | |
1409 | - prev_bp = prev_bp->next; | |
1410 | - } else { | |
1411 | - prev_bp = NULL; | |
1412 | - } | |
1413 | - | |
1414 | - /* Insert new breakpoint */ | |
1415 | - if (prev_bp) { | |
1416 | - bp->next = prev_bp->next; | |
1417 | - prev_bp->next = bp; | |
1418 | - } else { | |
1419 | - bp->next = env->breakpoints; | |
1420 | - env->breakpoints = bp; | |
1421 | - } | |
1422 | - if (bp->next) | |
1423 | - bp->next->prev = bp; | |
1424 | - bp->prev = prev_bp; | |
1389 | + if (flags & BP_GDB) | |
1390 | + TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry); | |
1391 | + else | |
1392 | + TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry); | |
1425 | 1393 | |
1426 | 1394 | breakpoint_invalidate(env, pc); |
1427 | 1395 | |
... | ... | @@ -1439,7 +1407,7 @@ int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags) |
1439 | 1407 | #if defined(TARGET_HAS_ICE) |
1440 | 1408 | CPUBreakpoint *bp; |
1441 | 1409 | |
1442 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
1410 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
1443 | 1411 | if (bp->pc == pc && bp->flags == flags) { |
1444 | 1412 | cpu_breakpoint_remove_by_ref(env, bp); |
1445 | 1413 | return 0; |
... | ... | @@ -1455,12 +1423,7 @@ int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags) |
1455 | 1423 | void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint) |
1456 | 1424 | { |
1457 | 1425 | #if defined(TARGET_HAS_ICE) |
1458 | - if (breakpoint->next) | |
1459 | - breakpoint->next->prev = breakpoint->prev; | |
1460 | - if (breakpoint->prev) | |
1461 | - breakpoint->prev->next = breakpoint->next; | |
1462 | - else | |
1463 | - env->breakpoints = breakpoint->next; | |
1426 | + TAILQ_REMOVE(&env->breakpoints, breakpoint, entry); | |
1464 | 1427 | |
1465 | 1428 | breakpoint_invalidate(env, breakpoint->pc); |
1466 | 1429 | |
... | ... | @@ -1472,11 +1435,12 @@ void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint) |
1472 | 1435 | void cpu_breakpoint_remove_all(CPUState *env, int mask) |
1473 | 1436 | { |
1474 | 1437 | #if defined(TARGET_HAS_ICE) |
1475 | - CPUBreakpoint *bp; | |
1438 | + CPUBreakpoint *bp, *next; | |
1476 | 1439 | |
1477 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) | |
1440 | + TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) { | |
1478 | 1441 | if (bp->flags & mask) |
1479 | 1442 | cpu_breakpoint_remove_by_ref(env, bp); |
1443 | + } | |
1480 | 1444 | #endif |
1481 | 1445 | } |
1482 | 1446 | |
... | ... | @@ -2005,7 +1969,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, |
2005 | 1969 | code_address = address; |
2006 | 1970 | /* Make accesses to pages with watchpoints go via the |
2007 | 1971 | watchpoint trap routines. */ |
2008 | - for (wp = env->watchpoints; wp != NULL; wp = wp->next) { | |
1972 | + TAILQ_FOREACH(wp, &env->watchpoints, entry) { | |
2009 | 1973 | if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { |
2010 | 1974 | iotlb = io_mem_watch + paddr; |
2011 | 1975 | /* 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) |
2552 | 2516 | return; |
2553 | 2517 | } |
2554 | 2518 | vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset; |
2555 | - for (wp = env->watchpoints; wp != NULL; wp = wp->next) { | |
2519 | + TAILQ_FOREACH(wp, &env->watchpoints, entry) { | |
2556 | 2520 | if ((vaddr == (wp->vaddr & len_mask) || |
2557 | 2521 | (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { |
2558 | 2522 | wp->flags |= BP_WATCHPOINT_HIT; | ... | ... |
target-alpha/translate.c
... | ... | @@ -2363,8 +2363,8 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, |
2363 | 2363 | |
2364 | 2364 | gen_icount_start(); |
2365 | 2365 | for (ret = 0; ret == 0;) { |
2366 | - if (unlikely(env->breakpoints)) { | |
2367 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
2366 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
2367 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
2368 | 2368 | if (bp->pc == ctx.pc) { |
2369 | 2369 | gen_excp(&ctx, EXCP_DEBUG, 0); |
2370 | 2370 | break; | ... | ... |
target-arm/translate.c
... | ... | @@ -8677,8 +8677,8 @@ static inline void gen_intermediate_code_internal(CPUState *env, |
8677 | 8677 | } |
8678 | 8678 | #endif |
8679 | 8679 | |
8680 | - if (unlikely(env->breakpoints)) { | |
8681 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
8680 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
8681 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
8682 | 8682 | if (bp->pc == dc->pc) { |
8683 | 8683 | gen_set_condexec(dc); |
8684 | 8684 | gen_set_pc_im(dc->pc); | ... | ... |
target-cris/translate.c
... | ... | @@ -3189,8 +3189,8 @@ static void check_breakpoint(CPUState *env, DisasContext *dc) |
3189 | 3189 | { |
3190 | 3190 | CPUBreakpoint *bp; |
3191 | 3191 | |
3192 | - if (unlikely(env->breakpoints)) { | |
3193 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
3192 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
3193 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
3194 | 3194 | if (bp->pc == dc->pc) { |
3195 | 3195 | cris_evaluate_flags (dc); |
3196 | 3196 | tcg_gen_movi_tl(env_pc, dc->pc); | ... | ... |
target-i386/helper.c
... | ... | @@ -1364,7 +1364,7 @@ static void breakpoint_handler(CPUState *env) |
1364 | 1364 | cpu_resume_from_signal(env, NULL); |
1365 | 1365 | } |
1366 | 1366 | } else { |
1367 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) | |
1367 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) | |
1368 | 1368 | if (bp->pc == env->eip) { |
1369 | 1369 | if (bp->flags & BP_CPU) { |
1370 | 1370 | check_hw_breakpoints(env, 1); | ... | ... |
target-i386/translate.c
... | ... | @@ -7606,8 +7606,8 @@ static inline void gen_intermediate_code_internal(CPUState *env, |
7606 | 7606 | |
7607 | 7607 | gen_icount_start(); |
7608 | 7608 | for(;;) { |
7609 | - if (unlikely(env->breakpoints)) { | |
7610 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
7609 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
7610 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
7611 | 7611 | if (bp->pc == pc_ptr) { |
7612 | 7612 | gen_debug(dc, pc_ptr - dc->cs_base); |
7613 | 7613 | break; | ... | ... |
target-m68k/translate.c
... | ... | @@ -2999,8 +2999,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
2999 | 2999 | do { |
3000 | 3000 | pc_offset = dc->pc - pc_start; |
3001 | 3001 | gen_throws_exception = NULL; |
3002 | - if (unlikely(env->breakpoints)) { | |
3003 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
3002 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
3003 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
3004 | 3004 | if (bp->pc == dc->pc) { |
3005 | 3005 | gen_exception(dc, dc->pc, EXCP_DEBUG); |
3006 | 3006 | dc->is_jmp = DISAS_JUMP; | ... | ... |
target-mips/translate.c
... | ... | @@ -8286,8 +8286,8 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, |
8286 | 8286 | #endif |
8287 | 8287 | gen_icount_start(); |
8288 | 8288 | while (ctx.bstate == BS_NONE) { |
8289 | - if (unlikely(env->breakpoints)) { | |
8290 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
8289 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
8290 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
8291 | 8291 | if (bp->pc == ctx.pc) { |
8292 | 8292 | save_cpu_state(&ctx, 1); |
8293 | 8293 | ctx.bstate = BS_BRANCH; | ... | ... |
target-ppc/translate.c
... | ... | @@ -7562,8 +7562,8 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, |
7562 | 7562 | gen_icount_start(); |
7563 | 7563 | /* Set env in case of segfault during code fetch */ |
7564 | 7564 | while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) { |
7565 | - if (unlikely(env->breakpoints)) { | |
7566 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
7565 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
7566 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
7567 | 7567 | if (bp->pc == ctx.nip) { |
7568 | 7568 | gen_update_nip(&ctx, ctx.nip); |
7569 | 7569 | gen_helper_raise_debug(); | ... | ... |
target-sh4/translate.c
... | ... | @@ -1776,8 +1776,8 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, |
1776 | 1776 | max_insns = CF_COUNT_MASK; |
1777 | 1777 | gen_icount_start(); |
1778 | 1778 | while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { |
1779 | - if (unlikely(env->breakpoints)) { | |
1780 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
1779 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
1780 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
1781 | 1781 | if (ctx.pc == bp->pc) { |
1782 | 1782 | /* We have hit a breakpoint - make sure PC is up-to-date */ |
1783 | 1783 | tcg_gen_movi_i32(cpu_pc, ctx.pc); | ... | ... |
target-sparc/translate.c
... | ... | @@ -4816,8 +4816,8 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, |
4816 | 4816 | max_insns = CF_COUNT_MASK; |
4817 | 4817 | gen_icount_start(); |
4818 | 4818 | do { |
4819 | - if (unlikely(env->breakpoints)) { | |
4820 | - for (bp = env->breakpoints; bp != NULL; bp = bp->next) { | |
4819 | + if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { | |
4820 | + TAILQ_FOREACH(bp, &env->breakpoints, entry) { | |
4821 | 4821 | if (bp->pc == dc->pc) { |
4822 | 4822 | if (dc->pc != pc_start) |
4823 | 4823 | save_state(dc, cpu_cond); | ... | ... |