This is an automated email from Gerrit.

Tim Newsome ([email protected]) just uploaded a new patch set to Gerrit, which 
you can find at http://openocd.zylin.com/6363

-- gerrit

commit 90559b9072c75babdb9929fc1a63e729ac637f72
Author: Tim Newsome <[email protected]>
Date:   Fri Jul 9 12:58:07 2021 -0700

    Call poll at a fixed interval.
    
    The existing implementation blocks in select() for a fixed amount of
    time. This change tracks when the next event (likely poll()) wants to be
    run, and uses a shorter timeout in select() if necessary.
    
    Also track all these timeouts using milliseconds as returned by
    timeval_ms() instead of `struct timeval` to simplify the code.
    
    This feature is helpful if poll() wants to do something like sample PCs
    or memory values for basically the entire time that otherwise OpenOCD
    would be hung in select(). See
    https://github.com/riscv/riscv-openocd/pull/541 for an example of that.
    The RISC-V code using this change will be upstreamed some day, too.
    
    Signed-off-by: Tim Newsome <[email protected]>
    Change-Id: I67104a7cf69ed07c8399c14aa55963fc5116a67d

diff --git a/src/helper/command.c b/src/helper/command.c
index 8ea805b..5938470 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -982,7 +982,7 @@ static int jim_command_dispatch(Jim_Interp *interp, int 
argc, Jim_Obj * const *a
        if (!command_can_run(cmd_ctx, c, Jim_GetString(argv[0], NULL)))
                return JIM_ERR;
 
-       target_call_timer_callbacks_now();
+       target_call_timer_callbacks_now(NULL);
 
        /*
         * Black magic of overridden current target:
@@ -1177,7 +1177,7 @@ COMMAND_HANDLER(handle_sleep_command)
        if (!busy) {
                int64_t then = timeval_ms();
                while (timeval_ms() - then < (int64_t)duration) {
-                       target_call_timer_callbacks_now();
+                       target_call_timer_callbacks_now(NULL);
                        usleep(1000);
                }
        } else
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 9ac982f..abb1608 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -2599,13 +2599,13 @@ static int gdb_query_packet(struct connection 
*connection,
 
                        /* We want to print all debug output to GDB connection 
*/
                        log_add_callback(gdb_log_callback, connection);
-                       target_call_timer_callbacks_now();
+                       target_call_timer_callbacks_now(NULL);
                        /* some commands need to know the GDB connection, make 
note of current
                         * GDB connection. */
                        current_gdb_connection = gdb_connection;
                        command_run_line(cmd_ctx, cmd);
                        current_gdb_connection = NULL;
-                       target_call_timer_callbacks_now();
+                       target_call_timer_callbacks_now(NULL);
                        log_remove_callback(gdb_log_callback, connection);
                        free(cmd);
                }
diff --git a/src/server/server.c b/src/server/server.c
index ebf8898..f6dc414 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,7 @@ 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(&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 476986c..675ff0c 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -156,7 +156,7 @@ static struct target_event_callback *target_event_callbacks;
 static struct target_timer_callback *target_timer_callbacks;
 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 },
@@ -692,7 +692,7 @@ static int target_process_reset(struct command_invocation 
*cmd, enum target_rese
        }
 
        /* We want any events to be processed before the prompt */
-       retval = target_call_timer_callbacks_now();
+       retval = target_call_timer_callbacks_now(NULL);
 
        for (target = all_targets; target; target = target->next) {
                target->type->check_reset(target);
@@ -1733,8 +1733,7 @@ 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;
 
        (*callbacks_p)->priv = priv;
        (*callbacks_p)->next = NULL;
@@ -1868,15 +1867,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);
 
@@ -1886,7 +1884,7 @@ static int target_call_timer_callback(struct 
target_timer_callback *cb,
        return target_unregister_timer_callback(cb->callback, cb->priv);
 }
 
-static int target_call_timer_callbacks_check_time(int checktime)
+static int target_call_timer_callbacks_check_time(int64_t *next_event, int 
checktime)
 {
        static bool callback_processing;
 
@@ -1898,8 +1896,9 @@ static int target_call_timer_callbacks_check_time(int 
checktime)
 
        keep_alive();
 
-       struct timeval now;
-       gettimeofday(&now, NULL);
+       int64_t now = timeval_ms();
+       if (next_event)
+               *next_event = 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 +1914,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 (next_event && (*callback)->when < *next_event)
+                       *next_event = (*callback)->when;
+
                callback = &(*callback)->next;
        }
 
@@ -1927,15 +1929,19 @@ static int target_call_timer_callbacks_check_time(int 
checktime)
        return ERROR_OK;
 }
 
-int target_call_timer_callbacks(void)
+/**
+ * This function updates *next_event with the time (according to timeval_ms())
+ * that it would next need to be called in order to run all callbacks on time.
+ */
+int target_call_timer_callbacks(int64_t *next_event)
 {
-       return target_call_timer_callbacks_check_time(1);
+       return target_call_timer_callbacks_check_time(next_event, 1);
 }
 
 /* invoke periodic callbacks immediately */
-int target_call_timer_callbacks_now(void)
+int target_call_timer_callbacks_now(int64_t *next_event)
 {
-       return target_call_timer_callbacks_check_time(0);
+       return target_call_timer_callbacks_check_time(next_event, 0);
 }
 
 /* Prints the working area layout for debug purposes */
diff --git a/src/target/target.h b/src/target/target.h
index 18a9516..acf5b37 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;
 };
@@ -401,12 +401,12 @@ int target_call_trace_callbacks(struct target *target, 
size_t len, uint8_t *data
 int target_register_timer_callback(int (*callback)(void *priv),
                unsigned int time_ms, enum target_timer_type type, void *priv);
 int target_unregister_timer_callback(int (*callback)(void *priv), void *priv);
-int target_call_timer_callbacks(void);
+int target_call_timer_callbacks(int64_t *next_event);
 /**
  * Invoke this to ensure that e.g. polling timer callbacks happen before
  * a synchronous command completes.
  */
-int target_call_timer_callbacks_now(void);
+int target_call_timer_callbacks_now(int64_t *next_event);
 
 struct target *get_target_by_num(int num);
 struct target *get_current_target(struct command_context *cmd_ctx);
@@ -790,4 +790,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 */

-- 

Reply via email to