This is an automated email from Gerrit.

"Antonio Borneo <borneo.anto...@gmail.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6841

-- gerrit

commit f19b1dfc890423a64f8195381f8ee9e4be70dd28
Author: Antonio Borneo <borneo.anto...@gmail.com>
Date:   Thu Feb 3 18:24:20 2022 +0100

    keep-alive: manage deadline per connection
    
    A GDB connection that is exchanging several messages will not need
    any keep-alive and calls kept_alive() to delay next keep-alive.
    
    If another GDB connection is present and is idle, it would need a
    keep-alive, but the keep-alive will not arrive due to the other
    connection calling kept_alive().
    
    When two or more GDB connections are present, we cannot use a
    single deadline 'last_time' for all the connections.
    
    Use a per-connection 'last_time'.
    Let kept_alive() to update only the connection 'last_time'.
    When server doesn't need to send keep-alive, update 'last_time' as
    if the keep-alive was done.
    Implement a method to retrieve the oldest 'last_time' to compute
    the next keep-alive event.
    
    Change-Id: I3bb5aebe929273569e6f1d2613d6385b84a4e2ed
    Signed-off-by: Antonio Borneo <borneo.anto...@gmail.com>

diff --git a/src/helper/log.c b/src/helper/log.c
index 106d22867..6eee3d5b7 100644
--- a/src/helper/log.c
+++ b/src/helper/log.c
@@ -438,36 +438,50 @@ void keep_alive(void)
        int64_t current_time = timeval_ms();
        int64_t delta_time = current_time - last_time;
 
-       if (delta_time > KEEP_ALIVE_TIMEOUT_MS) {
-               last_time = current_time;
+       if (delta_time <= KEEP_ALIVE_KICK_TIME_MS)
+               return;
 
+       if (delta_time > KEEP_ALIVE_TIMEOUT_MS)
                gdb_timeout_warning(delta_time);
-       }
 
-       if (delta_time > KEEP_ALIVE_KICK_TIME_MS) {
+       /* some server could have been self-kept-alive */
+       last_time = server_older_kept_alive_time();
+       if (last_time > current_time) {
+               /* INT64_MAX: no connection requires keep-alive, retry later */
                last_time = current_time;
+               return;
+       }
+       delta_time = current_time - last_time;
+       if (delta_time <= KEEP_ALIVE_KICK_TIME_MS)
+               return;
 
-               /* this will keep the GDB connection alive */
-               server_keep_clients_alive();
+       /* this will keep the GDB connection alive */
+       server_keep_clients_alive();
 
-               /* DANGER!!!! do not add code to invoke e.g. target event 
processing,
-                * jim timer processing, etc. it can cause infinite recursion +
-                * jim event callbacks need to happen at a well defined time,
-                * not anywhere keep_alive() is invoked.
-                *
-                * These functions should be invoked at a well defined spot in 
server.c
-                */
-       }
+       /* some connection could have failed keep-alive, get status */
+       last_time = server_older_kept_alive_time();
+       if (last_time > current_time)
+               last_time = current_time;
+
+       /* DANGER!!!! do not add code to invoke e.g. target event processing,
+        * jim timer processing, etc. it can cause infinite recursion +
+        * jim event callbacks need to happen at a well defined time,
+        * not anywhere keep_alive() is invoked.
+        *
+        * These functions should be invoked at a well defined spot in server.c
+        */
 }
 
-/* reset keep alive timer without sending message */
-void kept_alive(void)
+/* reset connection's keep alive timer without sending message
+ * argument's value can be INT64_MAX
+ */
+void kept_alive(int64_t *last_kept_alive_time)
 {
        int64_t current_time = timeval_ms();
 
-       int64_t delta_time = current_time - last_time;
+       int64_t delta_time = current_time - *last_kept_alive_time;
 
-       last_time = current_time;
+       *last_kept_alive_time = current_time;
 
        if (delta_time > KEEP_ALIVE_TIMEOUT_MS)
                gdb_timeout_warning(delta_time);
diff --git a/src/helper/log.h b/src/helper/log.h
index f0378ae79..5c4d1f7e0 100644
--- a/src/helper/log.h
+++ b/src/helper/log.h
@@ -78,7 +78,7 @@ int set_log_output(struct command_context *cmd_ctx, FILE 
*output);
 int log_register_commands(struct command_context *cmd_ctx);
 
 void keep_alive(void);
-void kept_alive(void);
+void kept_alive(int64_t *last_kept_alive_time);
 
 void alive_sleep(uint64_t ms);
 void busy_sleep(uint64_t ms);
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 0944db4d3..0751cbab9 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -534,7 +534,7 @@ int gdb_put_packet(struct connection *connection, char 
*buffer, int len)
        gdb_con->busy = false;
 
        /* we sent some data, reset timer for keep alive messages */
-       kept_alive();
+       kept_alive(&connection->last_kept_alive_time);
 
        return retval;
 }
@@ -3665,6 +3665,7 @@ static void gdb_keep_client_alive(struct connection 
*connection)
        switch (gdb_con->output_flag) {
        case GDB_OUTPUT_NO:
                /* no need for keep-alive */
+               kept_alive(&connection->last_kept_alive_time);
                break;
        case GDB_OUTPUT_ALL:
                /* send an empty O packet */
diff --git a/src/server/server.c b/src/server/server.c
index 1bd84e47e..542662f83 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -78,6 +78,7 @@ static int add_connection(struct service *service, struct 
command_context *cmd_c
        c->cmd_ctx = copy_command_context(cmd_ctx);
        c->service = service;
        c->input_pending = false;
+       c->last_kept_alive_time = INT64_MAX;
        c->priv = NULL;
        c->next = NULL;
 
@@ -429,6 +430,19 @@ void server_keep_clients_alive(void)
                                s->keep_client_alive(c);
 }
 
+int64_t server_older_kept_alive_time(void)
+{
+       int64_t older = INT64_MAX;
+
+       for (struct service *s = services; s; s = s->next)
+               if (s->keep_client_alive)
+                       for (struct connection *c = s->connections; c; c = 
c->next)
+                               if (c->last_kept_alive_time && older > 
c->last_kept_alive_time)
+                                       older = c->last_kept_alive_time;
+
+       return older;
+}
+
 int server_loop(struct command_context *command_context)
 {
        struct service *service;
diff --git a/src/server/server.h b/src/server/server.h
index e8b5e5ac0..d8cf01e8f 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -52,6 +52,7 @@ struct connection {
        struct service *service;
        bool input_pending;
        void *priv;
+       int64_t last_kept_alive_time;
        struct connection *next;
 };
 
@@ -107,6 +108,7 @@ void server_free(void);
 void exit_on_signal(int sig);
 
 void server_keep_clients_alive(void);
+int64_t server_older_kept_alive_time(void);
 
 int server_loop(struct command_context *command_context);
 

-- 

Reply via email to