Author: cem
Date: Mon Aug 19 22:57:03 2019
New Revision: 351238
URL: https://svnweb.freebsd.org/changeset/base/351238

Log:
  gdb(4): Pack 'info threads' responses into fewer packets
  
  We suffer at least one round trip ACK latency every command / packet that
  GDB has to send and receive, and the response format for 'info threads'
  supports packing many threads IDs into a single packet, so do so.
  
  Adds and uses a new API, gdb_txbuf_has_capacity(), which checks for a
  certain number of bytes available in the outgoing txbuf.
  
  On an example amd64 VM, the number of RTTs to transmit this list is reduced
  by a factor of 110x.  This is especially beneficial with recent GDB, which
  seems to request the list at least twice during attach.

Modified:
  head/sys/gdb/gdb_int.h
  head/sys/gdb/gdb_main.c
  head/sys/gdb/gdb_packet.c

Modified: head/sys/gdb/gdb_int.h
==============================================================================
--- head/sys/gdb/gdb_int.h      Mon Aug 19 22:53:05 2019        (r351237)
+++ head/sys/gdb/gdb_int.h      Mon Aug 19 22:57:03 2019        (r351238)
@@ -62,6 +62,7 @@ void gdb_tx_begin(char);
 int gdb_tx_end(void);
 int gdb_tx_mem(const unsigned char *, size_t);
 void gdb_tx_reg(int);
+bool gdb_txbuf_has_capacity(size_t);
 int gdb_rx_bindata(unsigned char *data, size_t datalen, size_t *amt);
 int gdb_search_mem(const unsigned char *addr, size_t size,
     const unsigned char *pat, size_t patlen, const unsigned char **found);

Modified: head/sys/gdb/gdb_main.c
==============================================================================
--- head/sys/gdb/gdb_main.c     Mon Aug 19 22:53:05 2019        (r351237)
+++ head/sys/gdb/gdb_main.c     Mon Aug 19 22:57:03 2019        (r351238)
@@ -123,6 +123,45 @@ gdb_do_mem_search(void)
                gdb_tx_err(EIO);
 }
 
+static void
+gdb_do_threadinfo(struct thread **thr_iter)
+{
+       static struct thread * const done_sentinel = (void *)(uintptr_t)1;
+       static const size_t tidsz_hex = sizeof(lwpid_t) * 2;
+       size_t tds_sent;
+
+       if (*thr_iter == NULL) {
+               gdb_tx_err(ENXIO);
+               return;
+       }
+
+       if (*thr_iter == done_sentinel) {
+               gdb_tx_begin('l');
+               *thr_iter = NULL;
+               goto sendit;
+       }
+
+       gdb_tx_begin('m');
+
+       for (tds_sent = 0;
+           *thr_iter != NULL && gdb_txbuf_has_capacity(tidsz_hex + 1);
+           *thr_iter = kdb_thr_next(*thr_iter), tds_sent++) {
+               if (tds_sent > 0)
+                       gdb_tx_char(',');
+               gdb_tx_varhex((*thr_iter)->td_tid);
+       }
+
+       /*
+        * Can't send EOF and "some" in same packet, so set a sentinel to send
+        * EOF when GDB asks us next.
+        */
+       if (*thr_iter == NULL && tds_sent > 0)
+               *thr_iter = done_sentinel;
+
+sendit:
+       gdb_tx_end();
+}
+
 static int
 gdb_trap(int type, int code)
 {
@@ -268,23 +307,9 @@ gdb_trap(int type, int code)
                case 'q':       /* General query. */
                        if (gdb_rx_equal("fThreadInfo")) {
                                thr_iter = kdb_thr_first();
-                               gdb_tx_begin('m');
-                               gdb_tx_hex((long)thr_iter->td_tid, 8);
-                               gdb_tx_end();
+                               gdb_do_threadinfo(&thr_iter);
                        } else if (gdb_rx_equal("sThreadInfo")) {
-                               if (thr_iter == NULL) {
-                                       gdb_tx_err(ENXIO);
-                                       break;
-                               }
-                               thr_iter = kdb_thr_next(thr_iter);
-                               if (thr_iter != NULL) {
-                                       gdb_tx_begin('m');
-                                       gdb_tx_hex((long)thr_iter->td_tid, 8);
-                                       gdb_tx_end();
-                               } else {
-                                       gdb_tx_begin('l');
-                                       gdb_tx_end();
-                               }
+                               gdb_do_threadinfo(&thr_iter);
                        } else if (gdb_rx_equal("Search:memory:")) {
                                gdb_do_mem_search();
                        } else if (!gdb_cpu_query())

Modified: head/sys/gdb/gdb_packet.c
==============================================================================
--- head/sys/gdb/gdb_packet.c   Mon Aug 19 22:53:05 2019        (r351237)
+++ head/sys/gdb/gdb_packet.c   Mon Aug 19 22:57:03 2019        (r351238)
@@ -327,6 +327,12 @@ gdb_tx_reg(int regnum)
                gdb_tx_mem(regp, regsz);
 }
 
+bool
+gdb_txbuf_has_capacity(size_t req)
+{
+       return (((char *)gdb_txbuf + sizeof(gdb_txbuf) - gdb_txp) >= req);
+}
+
 /* Read binary data up until the end of the packet or until we have datalen 
decoded bytes */
 int
 gdb_rx_bindata(unsigned char *data, size_t datalen, size_t *amt)
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to