From 16cc853bcfbcc8dba6eadd91b434c05387034c0a Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 16 Dec 2021 01:59:14 +0100 Subject: [PATCH] target/smp: use a struct list_head to hold the smp targets Instead of reinventing a simply linked list, reuse the list helper for the list of targets in a smp cluster. Using the existing helper, that implements a double linked list, makes trivial going through the list in reverse order. Change-Id: Ib36ad2955f15cd2a601b0b9e36ca6d948b12d00f Signed-off-by: Antonio Borneo Reviewed-on: https://review.openocd.org/c/openocd/+/6783 Tested-by: jenkins --- src/rtos/hwthread.c | 8 +-- src/rtos/linux.c | 16 ++---- src/server/gdb_server.c | 11 ++-- src/target/aarch64.c | 15 +++--- src/target/armv7a.c | 9 ++-- src/target/armv7a_cache.c | 9 ++-- src/target/armv7a_cache_l2x.c | 9 ++-- src/target/armv8_cache.c | 8 ++- src/target/breakpoints.c | 95 +++++++++++++++-------------------- src/target/cortex_a.c | 26 ++++------ src/target/mips_m4k.c | 22 +++----- src/target/riscv/riscv.c | 23 +++++---- src/target/smp.c | 10 ++-- src/target/smp.h | 3 +- src/target/target.c | 44 ++++++++-------- src/target/target.h | 6 ++- 16 files changed, 136 insertions(+), 178 deletions(-) diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c index 3702b0b47..7c998861f 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -23,6 +23,7 @@ #include "target/target.h" #include "target/target_type.h" #include "target/register.h" +#include #include "rtos.h" #include "helper/log.h" #include "helper/types.h" @@ -107,7 +108,7 @@ static int hwthread_update_threads(struct rtos *rtos) /* determine the number of "threads" */ if (target->smp) { - for (head = target->head; head; head = head->next) { + foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; if (!target_was_examined(curr)) @@ -123,7 +124,7 @@ static int hwthread_update_threads(struct rtos *rtos) if (target->smp) { /* loop over all threads */ - for (head = target->head; head; head = head->next) { + foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; if (!target_was_examined(curr)) @@ -218,7 +219,8 @@ static struct target *hwthread_find_thread(struct target *target, int64_t thread if (!target) return NULL; if (target->smp) { - for (struct target_list *head = target->head; head; head = head->next) { + struct target_list *head; + foreach_smp_target(head, target->smp_targets) { if (thread_id == threadid_from_target(head->target)) return head->target; } diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 84b4c6524..d147c1cf0 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -30,6 +30,7 @@ #include "rtos.h" #include "rtos_standard_stackings.h" #include +#include #include "server/gdb_server.h" #define LINUX_USER_KERNEL_BORDER 0xc0000000 @@ -191,16 +192,14 @@ static int linux_os_thread_reg_list(struct rtos *rtos, /* search target to perform the access */ struct reg **gdb_reg_list; struct target_list *head; - head = target->head; found = 0; - do { + foreach_smp_target(head, target->smp_targets) { if (head->target->coreid == next->core_id) { target = head->target; found = 1; break; } - head = head->next; - } while (head); + } if (found == 0) { LOG_ERROR @@ -397,7 +396,6 @@ static int get_name(struct target *target, struct threads *t) static int get_current(struct target *target, int create) { struct target_list *head; - head = target->head; uint8_t *buf; uint32_t val; uint32_t ti_addr; @@ -413,7 +411,7 @@ static int get_current(struct target *target, int create) ctt = ctt->next; } - while (head) { + foreach_smp_target(head, target->smp_targets) { struct reg **reg_list; int reg_list_size; int retval; @@ -474,7 +472,6 @@ static int get_current(struct target *target, int create) } free(reg_list); - head = head->next; } free(buffer); @@ -1394,9 +1391,8 @@ static int linux_os_smp_init(struct target *target) struct linux_os *os_linux = (struct linux_os *)rtos->rtos_specific_params; struct current_thread *ct; - head = target->head; - while (head) { + foreach_smp_target(head, target->smp_targets) { if (head->target->rtos != rtos) { struct linux_os *smp_os_linux = (struct linux_os *)head->target->rtos->rtos_specific_params; @@ -1413,8 +1409,6 @@ static int linux_os_smp_init(struct target *target) os_linux->nr_cpus++; free(smp_os_linux); } - - head = head->next; } return ERROR_OK; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index b6f4a8264..537670c52 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2280,7 +2280,7 @@ static int smp_reg_list_noread(struct target *target, *combined_list_size = 0; struct target_list *head; - foreach_smp_target(head, target->head) { + foreach_smp_target(head, target->smp_targets) { struct reg **reg_list = NULL; int reg_list_size; int result = target_get_gdb_reg_list_noread(head->target, ®_list, @@ -2330,7 +2330,7 @@ static int smp_reg_list_noread(struct target *target, } /* Now warn the user about any registers that weren't found in every target. */ - foreach_smp_target(head, target->head) { + foreach_smp_target(head, target->smp_targets) { struct reg **reg_list = NULL; int reg_list_size; int result = target_get_gdb_reg_list_noread(head->target, ®_list, @@ -3659,13 +3659,10 @@ static int gdb_target_start(struct target *target, const char *port) /* initialize all targets gdb service with the same pointer */ { struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if (curr != target) curr->gdb_service = gdb_service; - head = head->next; } } return ret; diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d11fd943b..a45322d2f 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -333,15 +333,14 @@ static int aarch64_wait_halt_one(struct target *target) static int aarch64_prepare_halt_smp(struct target *target, bool exc_target, struct target **p_first) { int retval = ERROR_OK; - struct target_list *head = target->head; + struct target_list *head; struct target *first = NULL; LOG_DEBUG("target %s exc %i", target_name(target), exc_target); - while (head) { + foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; struct armv8_common *armv8 = target_to_armv8(curr); - head = head->next; if (exc_target && curr == target) continue; @@ -430,7 +429,7 @@ static int aarch64_halt_smp(struct target *target, bool exc_target) struct target_list *head; struct target *curr; - foreach_smp_target(head, target->head) { + foreach_smp_target(head, target->smp_targets) { int halted; curr = head->target; @@ -480,7 +479,7 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug } /* poll all targets in the group, but skip the target that serves GDB */ - foreach_smp_target(head, target->head) { + foreach_smp_target(head, target->smp_targets) { curr = head->target; /* skip calling context */ if (curr == target) @@ -745,7 +744,7 @@ static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoint struct target *first = NULL; uint64_t address; - foreach_smp_target(head, target->head) { + foreach_smp_target(head, target->smp_targets) { struct target *curr = head->target; /* skip calling target */ @@ -800,7 +799,7 @@ static int aarch64_step_restart_smp(struct target *target) struct target *curr = target; bool all_resumed = true; - foreach_smp_target(head, target->head) { + foreach_smp_target(head, target->smp_targets) { uint32_t prsr; int resumed; @@ -888,7 +887,7 @@ static int aarch64_resume(struct target *target, int current, struct target_list *head; bool all_resumed = true; - foreach_smp_target(head, target->head) { + foreach_smp_target(head, target->smp_targets) { uint32_t prsr; int resumed; diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 2259fa560..d564f19ae 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -38,6 +38,7 @@ #include "arm_opcodes.h" #include "target.h" #include "target_type.h" +#include "smp.h" static void armv7a_show_fault_registers(struct target *target) { @@ -193,8 +194,7 @@ done: static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way) { struct armv7a_l2x_cache *l2x_cache; - struct target_list *head = target->head; - struct target *curr; + struct target_list *head; struct armv7a_common *armv7a = target_to_armv7a(target); l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache)); @@ -207,15 +207,14 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; /* initialize all target in this cluster (smp target) * l2 cache must be configured after smp declaration */ - while (head) { - curr = head->target; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if (curr != target) { armv7a = target_to_armv7a(curr); if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) LOG_ERROR("smp target : outer cache already initialized\n"); armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; } - head = head->next; } return JIM_OK; } diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index 4078fdde2..ba6f076f0 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -26,6 +26,7 @@ #include "armv7a_cache.h" #include #include "arm_opcodes.h" +#include "smp.h" static int armv7a_l1_d_cache_sanity_check(struct target *target) { @@ -138,14 +139,10 @@ int armv7a_cache_auto_flush_all_data(struct target *target) if (target->smp) { struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if (curr->state == TARGET_HALTED) retval = armv7a_l1_d_cache_clean_inval_all(curr); - - head = head->next; } } else retval = armv7a_l1_d_cache_clean_inval_all(target); diff --git a/src/target/armv7a_cache_l2x.c b/src/target/armv7a_cache_l2x.c index 6b42fae53..c26d05173 100644 --- a/src/target/armv7a_cache_l2x.c +++ b/src/target/armv7a_cache_l2x.c @@ -27,6 +27,7 @@ #include #include "target.h" #include "target_type.h" +#include "smp.h" static int arm7a_l2x_sanity_check(struct target *target) { @@ -194,8 +195,7 @@ static int arm7a_handle_l2x_cache_info_command(struct command_invocation *cmd, static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way) { struct armv7a_l2x_cache *l2x_cache; - struct target_list *head = target->head; - struct target *curr; + struct target_list *head; struct armv7a_common *armv7a = target_to_armv7a(target); if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) { @@ -210,8 +210,8 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t /* initialize all targets in this cluster (smp target) * l2 cache must be configured after smp declaration */ - while (head) { - curr = head->target; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if (curr != target) { armv7a = target_to_armv7a(curr); if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) { @@ -220,7 +220,6 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t } armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache; } - head = head->next; } return ERROR_OK; } diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index f05ac07cd..5b58d3f9f 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -23,6 +23,7 @@ #include "armv8_cache.h" #include "armv8_dpm.h" #include "armv8_opcodes.h" +#include "smp.h" /* CLIDR cache types */ #define CACHE_LEVEL_HAS_UNIFIED_CACHE 0x4 @@ -250,15 +251,12 @@ static int armv8_flush_all_data(struct target *target) /* look if all the other target have been flushed in order to flush level * 2 */ struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if (curr->state == TARGET_HALTED) { LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid); retval = _armv8_flush_all_data(curr); } - head = head->next; } } else retval = _armv8_flush_all_data(target); diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index dd901ef25..8439ff395 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -26,6 +26,7 @@ #include "target.h" #include #include "breakpoints.h" +#include "smp.h" static const char * const breakpoint_type_strings[] = { "hardware", @@ -216,22 +217,22 @@ int breakpoint_add(struct target *target, uint32_t length, enum breakpoint_type type) { - int retval = ERROR_OK; if (target->smp) { struct target_list *head; - struct target *curr; - head = target->head; - if (type == BKPT_SOFT) - return breakpoint_add_internal(head->target, address, length, type); - while (head) { - curr = head->target; - retval = breakpoint_add_internal(curr, address, length, type); + if (type == BKPT_SOFT) { + head = list_first_entry(target->smp_targets, struct target_list, lh); + return breakpoint_add_internal(head->target, address, length, type); + } + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; + int retval = breakpoint_add_internal(curr, address, length, type); if (retval != ERROR_OK) return retval; - head = head->next; } - return retval; + + return ERROR_OK; } else { return breakpoint_add_internal(target, address, length, type); } @@ -242,19 +243,17 @@ int context_breakpoint_add(struct target *target, uint32_t length, enum breakpoint_type type) { - int retval = ERROR_OK; if (target->smp) { struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; - retval = context_breakpoint_add_internal(curr, asid, length, type); + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; + int retval = context_breakpoint_add_internal(curr, asid, length, type); if (retval != ERROR_OK) return retval; - head = head->next; } - return retval; + + return ERROR_OK; } else { return context_breakpoint_add_internal(target, asid, length, type); } @@ -266,19 +265,17 @@ int hybrid_breakpoint_add(struct target *target, uint32_t length, enum breakpoint_type type) { - int retval = ERROR_OK; if (target->smp) { struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; - retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type); + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; + int retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type); if (retval != ERROR_OK) return retval; - head = head->next; } - return retval; + + return ERROR_OK; } else return hybrid_breakpoint_add_internal(target, address, asid, length, type); } @@ -345,12 +342,10 @@ void breakpoint_remove(struct target *target, target_addr_t address) if (target->smp) { unsigned int num_breakpoints = 0; struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; num_breakpoints += breakpoint_remove_internal(curr, address); - head = head->next; } if (!num_breakpoints) LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address); @@ -363,12 +358,10 @@ void breakpoint_remove_all(struct target *target) { if (target->smp) { struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; breakpoint_remove_all_internal(curr); - head = head->next; } } else { breakpoint_remove_all_internal(target); @@ -387,12 +380,10 @@ void breakpoint_clear_target(struct target *target) { if (target->smp) { struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; breakpoint_clear_target_internal(curr); - head = head->next; } } else { breakpoint_clear_target_internal(target); @@ -482,21 +473,17 @@ bye: int watchpoint_add(struct target *target, target_addr_t address, uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) { - int retval = ERROR_OK; if (target->smp) { struct target_list *head; - struct target *curr; - head = target->head; - while (head != (struct target_list *)NULL) { - curr = head->target; - retval = watchpoint_add_internal(curr, address, length, rw, value, - mask); + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; + int retval = watchpoint_add_internal(curr, address, length, rw, value, mask); if (retval != ERROR_OK) return retval; - head = head->next; } - return retval; + + return ERROR_OK; } else { return watchpoint_add_internal(target, address, length, rw, value, mask); @@ -549,12 +536,10 @@ void watchpoint_remove(struct target *target, target_addr_t address) if (target->smp) { unsigned int num_watchpoints = 0; struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; num_watchpoints += watchpoint_remove_internal(curr, address); - head = head->next; } if (num_watchpoints == 0) LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address); diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index bf65544f5..272411359 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -639,14 +639,11 @@ static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr) static struct target *get_cortex_a(struct target *target, int32_t coreid) { struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) return curr; - head = head->next; } return target; } @@ -656,14 +653,12 @@ static int cortex_a_halt_smp(struct target *target) { int retval = 0; struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if ((curr != target) && (curr->state != TARGET_HALTED) && target_was_examined(curr)) retval += cortex_a_halt(curr); - head = head->next; } return retval; } @@ -684,7 +679,7 @@ static int update_halt_gdb(struct target *target) if (target->gdb_service) gdb_target = target->gdb_service->target; - foreach_smp_target(head, target->head) { + foreach_smp_target(head, target->smp_targets) { curr = head->target; /* skip calling context */ if (curr == target) @@ -951,11 +946,10 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) { int retval = 0; struct target_list *head; - struct target *curr; target_addr_t address; - head = target->head; - while (head) { - curr = head->target; + + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) { /* resume current address , not in step mode */ @@ -963,8 +957,6 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) handle_breakpoints, 0); retval += cortex_a_internal_restart(curr); } - head = head->next; - } return retval; } diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index ca4416981..8627bce6e 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -128,14 +128,11 @@ static int mips_m4k_debug_entry(struct target *target) static struct target *get_mips_m4k(struct target *target, int32_t coreid) { struct target_list *head; - struct target *curr; - head = target->head; - while (head) { - curr = head->target; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) return curr; - head = head->next; } return target; } @@ -144,11 +141,10 @@ static int mips_m4k_halt_smp(struct target *target) { int retval = ERROR_OK; struct target_list *head; - struct target *curr; - head = target->head; - while (head) { + + foreach_smp_target(head, target->smp_targets) { int ret = ERROR_OK; - curr = head->target; + struct target *curr = head->target; if ((curr != target) && (curr->state != TARGET_HALTED)) ret = mips_m4k_halt(curr); @@ -156,7 +152,6 @@ static int mips_m4k_halt_smp(struct target *target) LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid); retval = ret; } - head = head->next; } return retval; } @@ -414,12 +409,10 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han { int retval = ERROR_OK; struct target_list *head; - struct target *curr; - head = target->head; - while (head) { + foreach_smp_target(head, target->smp_targets) { int ret = ERROR_OK; - curr = head->target; + struct target *curr = head->target; if ((curr != target) && (curr->state != TARGET_RUNNING)) { /* resume current address , not in step mode */ ret = mips_m4k_internal_restore(curr, 1, address, @@ -431,7 +424,6 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han retval = ret; } } - head = head->next; } return retval; } diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index c9840fe50..931f76290 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -13,6 +13,7 @@ #include "target/target.h" #include "target/algorithm.h" #include "target/target_type.h" +#include #include "jtag/jtag.h" #include "target/register.h" #include "target/breakpoints.h" @@ -1232,13 +1233,14 @@ int riscv_halt(struct target *target) int result = ERROR_OK; if (target->smp) { - for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { + struct target_list *tlist; + foreach_smp_target(tlist, target->smp_targets) { struct target *t = tlist->target; if (halt_prep(t) != ERROR_OK) result = ERROR_FAIL; } - for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { + foreach_smp_target(tlist, target->smp_targets) { struct target *t = tlist->target; riscv_info_t *i = riscv_info(t); if (i->prepped) { @@ -1247,7 +1249,7 @@ int riscv_halt(struct target *target) } } - for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { + foreach_smp_target(tlist, target->smp_targets) { struct target *t = tlist->target; if (halt_finish(t) != ERROR_OK) return ERROR_FAIL; @@ -1469,14 +1471,15 @@ int riscv_resume( LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints); int result = ERROR_OK; if (target->smp && !single_hart) { - for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { + struct target_list *tlist; + foreach_smp_target(tlist, target->smp_targets) { struct target *t = tlist->target; if (resume_prep(t, current, address, handle_breakpoints, debug_execution) != ERROR_OK) result = ERROR_FAIL; } - for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { + foreach_smp_target(tlist, target->smp_targets) { struct target *t = tlist->target; riscv_info_t *i = riscv_info(t); if (i->prepped) { @@ -1486,7 +1489,7 @@ int riscv_resume( } } - for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) { + foreach_smp_target(tlist, target->smp_targets) { struct target *t = tlist->target; if (resume_finish(t) != ERROR_OK) return ERROR_FAIL; @@ -2180,9 +2183,8 @@ int riscv_openocd_poll(struct target *target) unsigned halts_discovered = 0; unsigned should_remain_halted = 0; unsigned should_resume = 0; - unsigned i = 0; - for (struct target_list *list = target->head; list; - list = list->next, i++) { + struct target_list *list; + foreach_smp_target(list, target->smp_targets) { struct target *t = list->target; riscv_info_t *r = riscv_info(t); enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid); @@ -2242,8 +2244,7 @@ int riscv_openocd_poll(struct target *target) } /* Sample memory if any target is running. */ - for (struct target_list *list = target->head; list; - list = list->next, i++) { + foreach_smp_target(list, target->smp_targets) { struct target *t = list->target; if (t->state == TARGET_RUNNING) { sample_memory(target); diff --git a/src/target/smp.c b/src/target/smp.c index 518f6e458..3e1ded8bc 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -111,18 +111,18 @@ COMMAND_HANDLER(default_handle_smp_command) } if (!strcmp(CMD_ARGV[0], "on")) { - foreach_smp_target(head, target->head) + foreach_smp_target(head, target->smp_targets) head->target->smp = 1; return ERROR_OK; } if (!strcmp(CMD_ARGV[0], "off")) { - foreach_smp_target(head, target->head) + foreach_smp_target(head, target->smp_targets) head->target->smp = 0; /* fixes the target display to the debugger */ - if (target->head) + if (!list_empty(target->smp_targets)) target->gdb_service->target = target; return ERROR_OK; @@ -135,9 +135,7 @@ COMMAND_HANDLER(handle_smp_gdb_command) { struct target *target = get_current_target(CMD_CTX); int retval = ERROR_OK; - struct target_list *head; - head = target->head; - if (head) { + if (!list_empty(target->smp_targets)) { if (CMD_ARGC == 1) { int coreid = 0; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); diff --git a/src/target/smp.h b/src/target/smp.h index 3338240ad..46fc55f75 100644 --- a/src/target/smp.h +++ b/src/target/smp.h @@ -19,10 +19,11 @@ #ifndef OPENOCD_TARGET_SMP_H #define OPENOCD_TARGET_SMP_H +#include #include "server/server.h" #define foreach_smp_target(pos, head) \ - for (pos = head; (pos); pos = pos->next) + list_for_each_entry(pos, head, lh) extern const struct command_registration smp_command_handlers[]; diff --git a/src/target/target.c b/src/target/target.c index acfbd3df5..6250d3031 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -56,6 +56,7 @@ #include "rtos/rtos.h" #include "transport/transport.h" #include "arm_cti.h" +#include "smp.h" /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 @@ -159,6 +160,7 @@ static int64_t target_timer_next_event_value; static LIST_HEAD(target_reset_callback_list); static LIST_HEAD(target_trace_callback_list); static const int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL; +static LIST_HEAD(empty_smp_targets); static const struct jim_nvp nvp_assert[] = { { .name = "assert", NVP_ASSERT }, @@ -2272,13 +2274,15 @@ static void target_destroy(struct target *target) /* release the targets SMP list */ if (target->smp) { - struct target_list *head = target->head; - while (head) { - struct target_list *pos = head->next; + struct target_list *head, *tmp; + + list_for_each_entry_safe(head, tmp, target->smp_targets, lh) { + list_del(&head->lh); head->target->smp = 0; free(head); - head = pos; } + if (target->smp_targets != &empty_smp_targets) + free(target->smp_targets); target->smp = 0; } @@ -5786,6 +5790,9 @@ static int target_create(struct jim_getopt_info *goi) return JIM_ERR; } + /* set empty smp cluster */ + target->smp_targets = &empty_smp_targets; + /* set target number */ target->target_number = new_target_number(); @@ -5998,9 +6005,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) const char *targetname; int retval, len; struct target *target = NULL; - struct target_list *head, *curr, *new; - curr = NULL; - head = NULL; + struct target_list *head, *new; retval = 0; LOG_DEBUG("%d", argc); @@ -6009,6 +6014,13 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) * argv[3] ... */ + struct list_head *lh = malloc(sizeof(*lh)); + if (!lh) { + LOG_ERROR("Out of memory"); + return JIM_ERR; + } + INIT_LIST_HEAD(lh); + for (i = 1; i < argc; i++) { targetname = Jim_GetString(argv[i], &len); @@ -6017,24 +6029,14 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (target) { new = malloc(sizeof(struct target_list)); new->target = target; - new->next = NULL; - if (!head) { - head = new; - curr = head; - } else { - curr->next = new; - curr = new; - } + list_add_tail(&new->lh, lh); } } /* now parse the list of cpu and put the target in smp mode*/ - curr = head; - - while (curr) { - target = curr->target; + foreach_smp_target(head, lh) { + target = head->target; target->smp = 1; - target->head = head; - curr = curr->next; + target->smp_targets = lh; } if (target && target->rtos) diff --git a/src/target/target.h b/src/target/target.h index 974630f17..1f1a35420 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -201,7 +201,9 @@ struct target { * and must be detected when symbols are offered */ struct backoff_timer backoff; int smp; /* add some target attributes for smp support */ - struct target_list *head; + struct list_head *smp_targets; /* list all targets in this smp group/cluster + * The head of the list is shared between the + * cluster, thus here there is a pointer */ /* the gdb service is there in case of smp, we have only one gdb server * for all smp target * the target attached to the gdb is changing dynamically by changing @@ -220,8 +222,8 @@ struct target { }; struct target_list { + struct list_head lh; struct target *target; - struct target_list *next; }; struct gdb_fileio_info {