This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] "info threads" queries for remote.c



I've checked in the attached patch to remote.c; it cleans up some
previous remote protocol code for asking the target for a list of
active threads, and adds a new (optional) query to ask the target
for a descriptive string for each thread.

The idea for this descriptive string is that the target OS can give
any info that the target implementer thinks is important (thread
attributes, name, state, etc.) and GDB will print the string in the
"info threads" display.

For the thread id query, since we can't know in advance whether the
thread list will fit into a single packet, the query is designed to 
be iterative.  GDB will keep asking until the target says "no more".

2000-03-20  Michael Snyder  <msnyder@cleaver.cygnus.com>

        * remote.c (remote_threads_extra_info): new function.
        Implement the extra thread info query for "info threads".
        (remote_threads_info): clean up a bit.
        (use_threadinfo_query, use_threadextra_query): new variables.
        Control whether GDB will use the new or old protocol for 
        thread info queries.
        (remote_open_1): initialize new variables.
        (remote_async_open_1): ditto.
        (remote_cisco_open): ditto.

Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.152
diff -c -r1.152 ChangeLog
*** ChangeLog	2000/03/20 22:15:58	1.152
--- ChangeLog	2000/03/20 23:01:30
***************
*** 1,3 ****
--- 1,15 ----
+ 2000-03-20  Michael Snyder  <msnyder@cleaver.cygnus.com>
+ 
+ 	* remote.c (remote_threads_extra_info): new function.
+ 	Implement the extra thread info query for "info threads".
+ 	(remote_threads_info): clean up a bit.
+ 	(use_threadinfo_query, use_threadextra_query): new variables.
+ 	Control whether GDB will use the new or old protocol for 
+ 	thread info queries.
+ 	(remote_open_1): initialize new variables.
+ 	(remote_async_open_1): ditto.
+ 	(remote_cisco_open): ditto.
+ 
  2000-03-20  Kevin Buettner  <kevinb@redhat.com>
  
  	* utils.c (floatformat_from_doublest): Don't assume that a long
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.5
diff -c -r1.5 remote.c
*** remote.c	2000/02/18 17:00:18	1.5
--- remote.c	2000/03/20 23:01:30
***************
*** 699,704 ****
--- 699,715 ----
  
  static struct packet_config remote_protocol_binary_download;
  
+ /* Should we try the 'ThreadInfo' query packet?
+ 
+    This variable (NOT available to the user: auto-detect only!)
+    determines whether GDB will use the new, simpler "ThreadInfo"
+    query or the older, more complex syntax for thread queries.
+    This is an auto-detect variable (set to true at each connect, 
+    and set to false when the target fails to recognize it).  */
+ 
+ static int use_threadinfo_query;
+ static int use_threadextra_query;
+ 
  static void
  set_remote_protocol_binary_download_cmd (char *args,
  					 int from_tty,
***************
*** 828,834 ****
  
  typedef int gdb_threadref;	/* internal GDB thread reference */
  
! /*  gdb_ext_thread_info is an internal GDB data structure which is
     equivalint to the reply of the remote threadinfo packet */
  
  struct gdb_ext_thread_info
--- 839,845 ----
  
  typedef int gdb_threadref;	/* internal GDB thread reference */
  
! /* gdb_ext_thread_info is an internal GDB data structure which is
     equivalint to the reply of the remote threadinfo packet */
  
  struct gdb_ext_thread_info
***************
*** 1558,1564 ****
      return oldpid;
  }
  
! /* Find new threads for info threads command.  */
  
  static void
  remote_find_new_threads ()
--- 1569,1577 ----
      return oldpid;
  }
  
! /* Find new threads for info threads command.  
!  * Original version, using John Metzler's thread protocol.  
!  */
  
  static void
  remote_find_new_threads ()
***************
*** 1569,1574 ****
--- 1582,1594 ----
      inferior_pid = remote_current_thread (inferior_pid);
  }
  
+ /*
+  * Find all threads for info threads command.
+  * Uses new thread protocol contributed by Cisco.
+  * Falls back and attempts to use the older method (above)
+  * if the target doesn't respond to the new method.
+  */
+ 
  static void
  remote_threads_info (void)
  {
***************
*** 1579,1607 ****
    if (remote_desc == 0)		/* paranoia */
      error ("Command can only be used when connected to the remote target.");
  
!   putpkt ("qfThreadInfo");
!   bufp = buf;
!   getpkt (bufp, PBUFSIZ, 0);
!   if (bufp[0] == '\0')		/* q packet not recognized! */
!     {				/* try old jmetzler method  */
!       remote_find_new_threads ();
!       return;
      }
!   else				/* try new 'q' method */
!     while (*bufp++ == 'm')	/* reply contains one or more TID */
        {
! 	do
  	  {
! 	    tid = strtol (bufp, &bufp, 16);
! 	    if (tid != 0 && !in_thread_list (tid))
! 	      add_thread (tid);
  	  }
- 	while (*bufp++ == ',');	/* comma-separated list */
- 	putpkt ("qsThreadInfo");
- 	bufp = buf;
- 	getpkt (bufp, PBUFSIZ, 0);
        }
  }
  
  
  /*  Restart the remote side; this is an extended protocol operation.  */
--- 1599,1706 ----
    if (remote_desc == 0)		/* paranoia */
      error ("Command can only be used when connected to the remote target.");
  
!   if (use_threadinfo_query)
!     {
!       putpkt ("qfThreadInfo");
!       bufp = buf;
!       getpkt (bufp, PBUFSIZ, 0);
!       if (bufp[0] != '\0')		/* q packet recognized */
! 	{	
! 	  while (*bufp++ == 'm')	/* reply contains one or more TID */
! 	    {
! 	      do
! 		{
! 		  tid = strtol (bufp, &bufp, 16);
! 		  if (tid != 0 && !in_thread_list (tid))
! 		    add_thread (tid);
! 		}
! 	      while (*bufp++ == ',');	/* comma-separated list */
! 	      putpkt ("qsThreadInfo");
! 	      bufp = buf;
! 	      getpkt (bufp, PBUFSIZ, 0);
! 	    }
! 	  return;	/* done */
! 	}
      }
! 
!   /* Else fall back to old method based on jmetzler protocol. */
!   use_threadinfo_query = 0;
!   remote_find_new_threads ();
!   return;
! }
! 
! /* 
!  * Collect a descriptive string about the given thread.
!  * The target may say anything it wants to about the thread
!  * (typically info about its blocked / runnable state, name, etc.).
!  * This string will appear in the info threads display.
!  * 
!  * Optional: targets are not required to implement this function.
!  */
! 
! static char *
! remote_threads_extra_info (struct thread_info *tp)
! {
!   int result;
!   int set;
!   threadref id;
!   struct gdb_ext_thread_info threadinfo;
!   static char display_buf[100];	/* arbitrary... */
!   char *bufp = alloca (PBUFSIZ);
!   int n = 0;                    /* position in display_buf */
! 
!   if (remote_desc == 0)		/* paranoia */
!     internal_error ("remote_threads_extra_info");
! 
!   if (use_threadextra_query)
!     {
!       sprintf (bufp, "qfThreadExtraInfo,%x", tp->pid);
!       putpkt (bufp);
!       getpkt (bufp, PBUFSIZ, 0);
!       if (bufp[0] != 0)
! 	{
! 	  char *p;
! 
! 	  for (p = display_buf; 
! 	       p < display_buf + sizeof(display_buf) - 1 &&
! 		 bufp[0] != 0 &&
! 		 bufp[1] != 0;
! 	       p++, bufp+=2)
! 	    {
! 	      *p = fromhex (bufp[0]) * 16 + fromhex (bufp[1]);
! 	    }
! 	  *p = 0;
! 	  return display_buf;
! 	}
!     }
! 
!   /* If the above query fails, fall back to the old method.  */
!   use_threadextra_query = 0;
!   set = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME
!     | TAG_MOREDISPLAY | TAG_DISPLAY;
!   int_to_threadref (&id, tp->pid);
!   if (remote_get_threadinfo (&id, set, &threadinfo))
!     if (threadinfo.active)
        {
! 	if (*threadinfo.shortname)
! 	  n += sprintf(&display_buf[0], " Name: %s,", threadinfo.shortname);
! 	if (*threadinfo.display)
! 	  n += sprintf(&display_buf[n], " State: %s,", threadinfo.display);
! 	if (*threadinfo.more_display)
! 	  n += sprintf(&display_buf[n], " Priority: %s",
! 		       threadinfo.more_display);
! 
! 	if (n > 0)
  	  {
! 	    /* for purely cosmetic reasons, clear up trailing commas */
! 	    if (',' == display_buf[n-1])
! 	      display_buf[n-1] = ' ';
! 	    return display_buf;
  	  }
        }
+   return NULL;
  }
+ 
  
  
  /*  Restart the remote side; this is an extended protocol operation.  */
***************
*** 1967,1972 ****
--- 2066,2075 ----
       binary downloading. */
    init_packet_config (&remote_protocol_binary_download);
  
+   /* Probe for ability to use "ThreadInfo" query, as required.  */
+   use_threadinfo_query = 1;
+   use_threadextra_query = 1;
+ 
    /* Without this, some commands which require an active target (such
       as kill) won't work.  This variable serves (at least) double duty
       as both the pid of the target process (if it has such), and as a
***************
*** 2052,2057 ****
--- 2155,2164 ----
       binary downloading. */
    init_packet_config (&remote_protocol_binary_download);
  
+   /* Probe for ability to use "ThreadInfo" query, as required.  */
+   use_threadinfo_query = 1;
+   use_threadextra_query = 1;
+ 
    /* Without this, some commands which require an active target (such
       as kill) won't work.  This variable serves (at least) double duty
       as both the pid of the target process (if it has such), and as a
***************
*** 4898,4903 ****
--- 5005,5011 ----
    remote_ops.to_mourn_inferior = remote_mourn;
    remote_ops.to_thread_alive = remote_thread_alive;
    remote_ops.to_find_new_threads = remote_threads_info;
+   remote_ops.to_extra_thread_info = remote_threads_extra_info;
    remote_ops.to_stop = remote_stop;
    remote_ops.to_query = remote_query;
    remote_ops.to_rcmd = remote_rcmd;
***************
*** 5034,5039 ****
--- 5142,5151 ----
       binary downloading. */
    init_packet_config (&remote_protocol_binary_download);
  
+   /* Probe for ability to use "ThreadInfo" query, as required.  */
+   use_threadinfo_query = 1;
+   use_threadextra_query = 1;
+   
    /* Without this, some commands which require an active target (such
       as kill) won't work.  This variable serves (at least) double duty
       as both the pid of the target process (if it has such), and as a
***************
*** 5309,5314 ****
--- 5421,5427 ----
    remote_cisco_ops.to_mourn_inferior = remote_cisco_mourn;
    remote_cisco_ops.to_thread_alive = remote_thread_alive;
    remote_cisco_ops.to_find_new_threads = remote_threads_info;
+   remote_ops.to_extra_thread_info = remote_threads_extra_info;
    remote_cisco_ops.to_stratum = process_stratum;
    remote_cisco_ops.to_has_all_memory = 1;
    remote_cisco_ops.to_has_memory = 1;
***************
*** 5397,5402 ****
--- 5510,5516 ----
    remote_async_ops.to_mourn_inferior = remote_async_mourn;
    remote_async_ops.to_thread_alive = remote_thread_alive;
    remote_async_ops.to_find_new_threads = remote_threads_info;
+   remote_ops.to_extra_thread_info = remote_threads_extra_info;
    remote_async_ops.to_stop = remote_stop;
    remote_async_ops.to_query = remote_query;
    remote_async_ops.to_rcmd = remote_rcmd;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]