Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Aug 2019 22:57:03 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r351238 - head/sys/gdb
Message-ID:  <201908192257.x7JMv3UN089192@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908192257.x7JMv3UN089192>