Make poll backoff time based.
Requested in https://review.openocd.org/c/openocd/+/6964. I'm making the change here so I have a chance to test it properly before pushing it upstream. A nice effect of this change is that we avoid some unnecessary polling early on when gdb is connecting and we would poll once every time we send gdb a qXfer packet. Change-Id: I4bdb9f05839e8c1e01ff6dde49d6589595418095 Signed-off-by: Tim Newsome <tim@sifive.com>
This commit is contained in:
parent
911d68ef25
commit
639e68a621
|
@ -3046,45 +3046,42 @@ static int handle_target(void *priv)
|
||||||
is_jtag_poll_safe() && target;
|
is_jtag_poll_safe() && target;
|
||||||
target = target->next) {
|
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. */
|
||||||
|
if (!target->tap->enabled ||
|
||||||
|
power_dropout ||
|
||||||
|
srst_asserted ||
|
||||||
|
timeval_ms() + polling_interval / 2 < target->backoff.next_attempt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (target->backoff.times > target->backoff.count) {
|
|
||||||
/* do not poll this time as we failed previously */
|
|
||||||
target->backoff.count++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
target->backoff.count = 0;
|
|
||||||
|
|
||||||
/* 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 */
|
/* polling may fail silently until the target has been examined */
|
||||||
retval = target_poll(target);
|
retval = target_poll(target);
|
||||||
if (retval != ERROR_OK) {
|
if (retval == ERROR_OK) {
|
||||||
/* 100ms polling interval. Increase interval between polling up to 5000ms */
|
target->backoff.interval = polling_interval;
|
||||||
if (target->backoff.times * polling_interval < 5000)
|
} else {
|
||||||
target->backoff.times = MIN(target->backoff.times * 2 + 1,
|
/* Increase interval between polling up to 5000ms */
|
||||||
5000 / polling_interval);
|
target->backoff.interval = MAX(polling_interval,
|
||||||
|
MIN(target->backoff.interval * 2 + 1, 5000));
|
||||||
/* Tell GDB to halt the debugger. This allows the user to
|
/* Tell GDB to halt the debugger. This allows the user to run
|
||||||
* run monitor commands to handle the situation.
|
* monitor commands to handle the situation. */
|
||||||
*/
|
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
|
target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
|
||||||
}
|
}
|
||||||
if (target->backoff.times > 0 && examine_attempted) {
|
target->backoff.next_attempt = timeval_ms() + target->backoff.interval;
|
||||||
LOG_DEBUG("[%s] Polling failed, trying to reexamine", target_name(target));
|
LOG_TARGET_DEBUG(target, "target_poll() -> %d, next attempt in %dms",
|
||||||
|
retval, target->backoff.interval);
|
||||||
|
|
||||||
|
if (retval != ERROR_OK && examine_attempted) {
|
||||||
target_reset_examined(target);
|
target_reset_examined(target);
|
||||||
retval = target_examine_one(target);
|
retval = target_examine_one(target);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_DEBUG("[%s] Examination failed, GDB will be halted. Polling again in %dms",
|
LOG_TARGET_DEBUG(target, "Examination failed, GDB will be halted. "
|
||||||
target_name(target), target->backoff.times * polling_interval);
|
"Polling again in %dms",
|
||||||
|
target->backoff.interval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Since we succeeded, we reset backoff count */
|
|
||||||
target->backoff.times = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -117,8 +117,8 @@ struct gdb_service {
|
||||||
|
|
||||||
/* target back off timer */
|
/* target back off timer */
|
||||||
struct backoff_timer {
|
struct backoff_timer {
|
||||||
int times;
|
int64_t next_attempt;
|
||||||
int count;
|
unsigned int interval;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* split target registers into multiple class */
|
/* split target registers into multiple class */
|
||||||
|
@ -199,6 +199,9 @@ struct target {
|
||||||
struct rtos *rtos; /* Instance of Real Time Operating System support */
|
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"
|
bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
|
||||||
* and must be detected when symbols are offered */
|
* 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;
|
struct backoff_timer backoff;
|
||||||
int smp; /* add some target attributes for smp support */
|
int smp; /* add some target attributes for smp support */
|
||||||
struct list_head *smp_targets; /* list all targets in this smp group/cluster
|
struct list_head *smp_targets; /* list all targets in this smp group/cluster
|
||||||
|
|
Loading…
Reference in New Issue