diff options
author | Tim Newsome <tim@sifive.com> | 2022-09-27 10:13:12 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-27 10:13:12 -0700 |
commit | 23df83e830f355fbe7aebd3a06a75bd4421746ff (patch) | |
tree | b695bc69a59742966fd63c519989f78190e34c97 /src | |
parent | e53fd14f50ea9e2073c099d61010129bb1744aef (diff) | |
parent | 3c5be531dfe40d67199ffbb57c28b7bd96651923 (diff) | |
download | riscv-openocd-23df83e830f355fbe7aebd3a06a75bd4421746ff.zip riscv-openocd-23df83e830f355fbe7aebd3a06a75bd4421746ff.tar.gz riscv-openocd-23df83e830f355fbe7aebd3a06a75bd4421746ff.tar.bz2 |
Merge pull request #727 from riscv/poll_backoff
Make poll backoff time based.
Diffstat (limited to 'src')
-rw-r--r-- | src/target/target.c | 62 | ||||
-rw-r--r-- | src/target/target.h | 7 |
2 files changed, 34 insertions, 35 deletions
diff --git a/src/target/target.c b/src/target/target.c index 7d3861a..927329a 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -159,7 +159,7 @@ static struct target_timer_callback *target_timer_callbacks; 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 const unsigned int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL; static LIST_HEAD(empty_smp_targets); static const struct jim_nvp nvp_assert[] = { @@ -3046,44 +3046,40 @@ static int handle_target(void *priv) is_jtag_poll_safe() && target; target = target->next) { - if (!target->tap->enabled) + /* This function only gets called every polling_interval, so + * allow some slack in the time comparison. Otherwise, if we + * schedule for now+polling_interval, the next poll won't + * actually happen until a polling_interval later. */ + bool poll_needed = timeval_ms() + polling_interval / 2 >= target->backoff.next_attempt; + if (!target->tap->enabled || power_dropout || srst_asserted || !poll_needed) continue; - if (target->backoff.times > target->backoff.count) { - /* do not poll this time as we failed previously */ - target->backoff.count++; - continue; + /* polling may fail silently until the target has been examined */ + retval = target_poll(target); + if (retval == ERROR_OK) { + /* Polling succeeded, reset the back-off interval */ + target->backoff.interval = polling_interval; + } else { + /* Increase interval between polling up to 5000ms */ + target->backoff.interval = MAX(polling_interval, + MIN(target->backoff.interval * 2 + 1, 5000)); + /* Tell GDB to halt the debugger. This allows the user to run + * monitor commands to handle the situation. */ + target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); } - target->backoff.count = 0; + target->backoff.next_attempt = timeval_ms() + target->backoff.interval; + LOG_TARGET_DEBUG(target, "target_poll() -> %d, next attempt in %dms", + retval, target->backoff.interval); - /* only poll target if we've got power and srst isn't asserted */ - if (!power_dropout && !srst_asserted) { - /* polling may fail silently until the target has been examined */ - retval = target_poll(target); + if (retval != ERROR_OK && examine_attempted) { + target_reset_examined(target); + retval = target_examine_one(target); if (retval != ERROR_OK) { - /* 100ms polling interval. Increase interval between polling up to 5000ms */ - if (target->backoff.times * polling_interval < 5000) - target->backoff.times = MIN(target->backoff.times * 2 + 1, - 5000 / polling_interval); - - /* Tell GDB to halt the debugger. This allows the user to - * run monitor commands to handle the situation. - */ - target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); - } - if (target->backoff.times > 0 && examine_attempted) { - LOG_DEBUG("[%s] Polling failed, trying to reexamine", target_name(target)); - target_reset_examined(target); - retval = target_examine_one(target); - if (retval != ERROR_OK) { - LOG_DEBUG("[%s] Examination failed, GDB will be halted. Polling again in %dms", - target_name(target), target->backoff.times * polling_interval); - return retval; - } + LOG_TARGET_DEBUG(target, "Examination failed, GDB will be halted. " + "Polling again in %dms", + target->backoff.interval); + return retval; } - - /* Since we succeeded, we reset backoff count */ - target->backoff.times = 0; } } diff --git a/src/target/target.h b/src/target/target.h index 4b494d8..726a14d 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -117,8 +117,8 @@ struct gdb_service { /* target back off timer */ struct backoff_timer { - int times; - int count; + int64_t next_attempt; + unsigned int interval; }; /* split target registers into multiple class */ @@ -199,6 +199,9 @@ struct target { struct rtos *rtos; /* Instance of Real Time Operating System support */ bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto" * and must be detected when symbols are offered */ + /* Track when next to poll(). If polling is failing, we don't want to + * poll too quickly because we'll just overwhelm the user with error + * messages. */ struct backoff_timer backoff; int smp; /* add some target attributes for smp support */ struct list_head *smp_targets; /* list all targets in this smp group/cluster |