Received: from mnm [127.0.0.1]
	by localhost with POP3 (fetchmail-5.9.0)
	for akpm@localhost (single-drop); Thu, 08 Jan 2004 18:10:40 -0800 (PST)
Received: from fire-1.osdl.org (air1.pdx.osdl.net [172.20.0.5])
	by mail.osdl.org (8.11.6/8.11.6) with ESMTP id i0929qo20750
	for <akpm@osdl.org>; Thu, 8 Jan 2004 18:09:52 -0800
Received: from sccrmhc13.comcast.net (sccrmhc13.comcast.net [204.127.202.64])
	by fire-1.osdl.org (8.12.8/8.12.8) with ESMTP id i0929qAv031470
	for <akpm@osdl.org>; Thu, 8 Jan 2004 18:09:52 -0800
Received: from h00e098094f32.ne.client2.attbi.com ([24.60.234.83])
          by comcast.net (sccrmhc13) with ESMTP
          id <2004010902094601600ni0oje>; Fri, 9 Jan 2004 02:09:46 +0000
Received: by h00e098094f32.ne.client2.attbi.com (Postfix, from userid 500)
	id 6DA02C60FC; Thu,  8 Jan 2004 21:09:20 -0500 (EST)
From: Jim Houston <jhouston@new.localdomain>
To: Andrew Morton <akpm@osdl.org>
Subject: gdb-thread-skip-frame.patch
Message-Id: <20040109020920.6DA02C60FC@h00e098094f32.ne.client2.attbi.com>
Date: Thu,  8 Jan 2004 21:09:20 -0500 (EST)
X-MIMEDefang-Filter: osdl$Revision: 1.45 $
X-Scanned-By: MIMEDefang 2.36
X-Spam-Checker-Version: SpamAssassin 2.60 (1.212-2003-09-23-exp) on mnm
X-Spam-Level: 
X-Spam-Status: No, hits=-4.9 required=2.0 tests=BAYES_00 autolearn=ham 
	version=2.60


Hi Andrew,

In the i386 kgdb_stub, George Anzinger has code to find the first
stack frame which is not in the scheduler.  He returns the register
information for this frame so the "info thread" command will
display an interesting frame.

Doing this on the x86_64 was not as easy because frame pointers
are not used consistently.  The attached patch adds an option to 
gdb to skip over frames which are executing function listed in the
option.

Use:
	set skip-frame thread_return,schedule_timeout

Jim Houston - Concurrent Computer Corp.

--

--- old/gdb-6.0/gdb/thread.c	2004-01-06 12:34:14.786496352 -0500
+++ new/gdb-6.0/gdb/thread.c	2004-01-06 12:34:28.804365312 -0500
@@ -404,6 +404,43 @@
     }
 }
 
+/*
+ * When using gdb as a kernel debugger, its really boring to
+ * see every thread is blocked in schedule.  By setting a
+ * list of functions with "set skip-frame schedule,thread_return" 
+ * we can display the frame that called into the scheduler.
+ */
+static char *skip_frame_string;
+
+int
+skip_frame(struct frame_info *fi)
+{
+  struct minimal_symbol *msym;
+  CORE_ADDR pc;
+  char *name;
+  char *s, *r;
+  int n;
+
+  pc = get_frame_pc (fi);
+  msym = lookup_minimal_symbol_by_pc_section(pc, NULL);
+  if (!msym)
+    return 0;
+  name = SYMBOL_LINKAGE_NAME(msym);
+
+  for (s = skip_frame_string; s && *s ; ) {
+    if ((r = strchr(s, ',')))
+      n = r - s - 1;
+    else
+      n = strlen(s);
+    if (n && strncmp(s, name, n) == 0)
+      return 1;
+    if (!r)
+      break;
+    s = r + 1;
+  }
+  return 0;
+}
+
 /* Print information about currently known threads 
 
  * Note: this has the drawback that it _really_ switches
@@ -416,7 +453,7 @@
 {
   struct thread_info *tp;
   ptid_t current_ptid;
-  struct frame_info *cur_frame;
+  struct frame_info *cur_frame, *fi;
   int saved_frame_level = frame_relative_level (get_selected_frame ());
   int counter;
   char *extra_info;
@@ -448,6 +485,18 @@
       puts_filtered ("  ");
 
       switch_to_thread (tp->ptid);
+
+      if (skip_frame_string) {
+	/* skip up the stack to an interesting frame. */
+        fi = get_selected_frame ();
+        while (fi) {
+          if (!skip_frame(fi))
+            break;
+          fi = get_prev_frame(fi);
+  	  if (fi)
+            select_frame(fi);
+        }
+      }
       print_stack_frame (get_selected_frame (), -1, 0);
     }
 
@@ -740,4 +789,12 @@
 
   if (!xdb_commands)
     add_com_alias ("t", "thread", class_run, 1);
+
+  add_show_from_set (add_set_cmd ("skip-frame", class_obscure,
+    var_string_noescape, (char *)&skip_frame_string, "\
+Set list of functions to skip when choosing the frame to display\n\
+for a info-thread command.  When gdb is used for kernel debug this option\n\
+allows the frame which calls the scheduler to be displayed rather than\n\
+having all blocked threads showing the same function in the scheduler.",
+    &setlist), &showlist);
 }