aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2022-09-27 10:13:12 -0700
committerGitHub <noreply@github.com>2022-09-27 10:13:12 -0700
commit23df83e830f355fbe7aebd3a06a75bd4421746ff (patch)
treeb695bc69a59742966fd63c519989f78190e34c97
parente53fd14f50ea9e2073c099d61010129bb1744aef (diff)
parent3c5be531dfe40d67199ffbb57c28b7bd96651923 (diff)
downloadriscv-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.
-rw-r--r--src/target/target.c62
-rw-r--r--src/target/target.h7
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