aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/server.c12
-rw-r--r--src/target/target.c36
-rw-r--r--src/target/target.h9
3 files changed, 42 insertions, 15 deletions
diff --git a/src/server/server.c b/src/server/server.c
index 6f0b23c..64acd36 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -437,6 +437,8 @@ int server_loop(struct command_context *command_context)
/* used in accept() */
int retval;
+ int64_t next_event = timeval_ms() + polling_period;
+
#ifndef _WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
@@ -478,7 +480,12 @@ int server_loop(struct command_context *command_context)
retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
} else {
/* Every 100ms, can be changed with "poll_period" command */
- tv.tv_usec = polling_period * 1000;
+ int timeout_ms = next_event - timeval_ms();
+ if (timeout_ms < 0)
+ timeout_ms = 0;
+ else if (timeout_ms > polling_period)
+ timeout_ms = polling_period;
+ tv.tv_usec = timeout_ms * 1000;
/* Only while we're sleeping we'll let others run */
openocd_sleep_prelude();
kept_alive();
@@ -511,7 +518,8 @@ int server_loop(struct command_context *command_context)
if (retval == 0) {
/* We only execute these callbacks when there was nothing to do or we timed
*out */
- target_call_timer_callbacks();
+ target_call_timer_callbacks_now();
+ next_event = target_timer_next_event();
process_jim_events(command_context);
FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */
diff --git a/src/target/target.c b/src/target/target.c
index cf1873c..a677120 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -154,9 +154,10 @@ static struct target_type *target_types[] = {
struct target *all_targets;
static struct target_event_callback *target_event_callbacks;
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 = 100;
+static const int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL;
static const struct jim_nvp nvp_assert[] = {
{ .name = "assert", NVP_ASSERT },
@@ -1733,8 +1734,8 @@ int target_register_timer_callback(int (*callback)(void *priv),
(*callbacks_p)->time_ms = time_ms;
(*callbacks_p)->removed = false;
- gettimeofday(&(*callbacks_p)->when, NULL);
- timeval_add_time(&(*callbacks_p)->when, 0, time_ms * 1000);
+ (*callbacks_p)->when = timeval_ms() + time_ms;
+ target_timer_next_event_value = MIN(target_timer_next_event_value, (*callbacks_p)->when);
(*callbacks_p)->priv = priv;
(*callbacks_p)->next = NULL;
@@ -1868,15 +1869,14 @@ int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data
}
static int target_timer_callback_periodic_restart(
- struct target_timer_callback *cb, struct timeval *now)
+ struct target_timer_callback *cb, int64_t *now)
{
- cb->when = *now;
- timeval_add_time(&cb->when, 0, cb->time_ms * 1000L);
+ cb->when = *now + cb->time_ms;
return ERROR_OK;
}
static int target_call_timer_callback(struct target_timer_callback *cb,
- struct timeval *now)
+ int64_t *now)
{
cb->callback(cb->priv);
@@ -1898,8 +1898,12 @@ static int target_call_timer_callbacks_check_time(int checktime)
keep_alive();
- struct timeval now;
- gettimeofday(&now, NULL);
+ int64_t now = timeval_ms();
+
+ /* Initialize to a default value that's a ways into the future.
+ * The loop below will make it closer to now if there are
+ * callbacks that want to be called sooner. */
+ target_timer_next_event_value = now + 1000;
/* Store an address of the place containing a pointer to the
* next item; initially, that's a standalone "root of the
@@ -1915,11 +1919,14 @@ static int target_call_timer_callbacks_check_time(int checktime)
bool call_it = (*callback)->callback &&
((!checktime && (*callback)->type == TARGET_TIMER_TYPE_PERIODIC) ||
- timeval_compare(&now, &(*callback)->when) >= 0);
+ now >= (*callback)->when);
if (call_it)
target_call_timer_callback(*callback, &now);
+ if (!(*callback)->removed && (*callback)->when < target_timer_next_event_value)
+ target_timer_next_event_value = (*callback)->when;
+
callback = &(*callback)->next;
}
@@ -1927,17 +1934,22 @@ static int target_call_timer_callbacks_check_time(int checktime)
return ERROR_OK;
}
-int target_call_timer_callbacks(void)
+int target_call_timer_callbacks()
{
return target_call_timer_callbacks_check_time(1);
}
/* invoke periodic callbacks immediately */
-int target_call_timer_callbacks_now(void)
+int target_call_timer_callbacks_now()
{
return target_call_timer_callbacks_check_time(0);
}
+int64_t target_timer_next_event(void)
+{
+ return target_timer_next_event_value;
+}
+
/* Prints the working area layout for debug purposes */
static void print_wa_layout(struct target *target)
{
diff --git a/src/target/target.h b/src/target/target.h
index 18a9516..1e19434 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -333,7 +333,7 @@ struct target_timer_callback {
unsigned int time_ms;
enum target_timer_type type;
bool removed;
- struct timeval when;
+ int64_t when; /* output of timeval_ms() */
void *priv;
struct target_timer_callback *next;
};
@@ -407,6 +407,11 @@ int target_call_timer_callbacks(void);
* a synchronous command completes.
*/
int target_call_timer_callbacks_now(void);
+/**
+ * Returns when the next registered event will take place. Callers can use this
+ * to go to sleep until that time occurs.
+ */
+int64_t target_timer_next_event(void);
struct target *get_target_by_num(int num);
struct target *get_current_target(struct command_context *cmd_ctx);
@@ -790,4 +795,6 @@ int target_profiling_default(struct target *target, uint32_t *samples, uint32_t
extern bool get_target_reset_nag(void);
+#define TARGET_DEFAULT_POLLING_INTERVAL 100
+
#endif /* OPENOCD_TARGET_TARGET_H */