This is the mail archive of the gdb-patches@sources.redhat.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]
Other format: [Raw text]

[COMMIT] Threads-support for inf-ttrace.c


This adds threads-support to the new inf-ttrace.c code.  It probably
still has some rough edges, but the testsuite already gives better
results with this code than with the old code.

I'm seriously considering switching over 32-bit HP-UX 11.x over to the
new code.

Mark


Index: ChangeLog
from  Mark Kettenis  <kettenis@gnu.org>
 
	* inf-ttrace.c: Include "gdbthread.h".
	(inf_ttrace_num_lwps): New variable.
	(inf_ttrace_num_lwps_in_syscall): Renamed from
	inf_ttrace_num_threads_in_syscall.
	(inf_ttrace_him): Track TTEVT_LWP_CREATE, TTEVT_LWP_EXIT and
	TTEVT_LWP_TERMINATE events.
	(inf_ttrace_create_inferior): Assert that INF_TTRACE_NUM_LWPS is
	zero.
	(inf_ttrace_mourn_inferior): Set INF_TTRACE_NUM_LWPS to zero.
	(inf_ttrace_attach): Assert that INF_TTRACE_NUM_LWPS is zero.
	Track TTEVT_LWP_CREATE, TTEVT_LWP_EXIT and TTEVT_LWP_TERMINATE
	events.
	(inf_ttrace_wait): Report status as TARGET_WAITKIND_SPURIOUS by
	default.  Handle TTEVT_LWP_CREATE, TTEVT_LWP_EXIT and
	TTEVT_LWP_TERMINATE events.
	(inf_ttrace_thread_alive, inf_ttrace_pid_to_str): New functions.
	(inf_ttrace_target): Set to_thread_alive and to_pid_to_str.
	* Makefile.in (inf-ttrace.o): Update dependencies.

Index: inf-ttrace.c
===================================================================
RCS file: /cvs/src/src/gdb/inf-ttrace.c,v
retrieving revision 1.2
diff -u -p -r1.2 inf-ttrace.c
--- inf-ttrace.c 3 Dec 2004 22:20:00 -0000 1.2
+++ inf-ttrace.c 7 Dec 2004 19:53:25 -0000
@@ -27,6 +27,7 @@
 
 #include "command.h"
 #include "gdbcore.h"
+#include "gdbthread.h"
 #include "inferior.h"
 #include "observer.h"
 #include "target.h"
@@ -43,6 +44,19 @@
 static struct target_ops *ttrace_ops_hack;
 
 
+/* HP-UX uses a threading model where each user-space thread
+   corresponds to a kernel thread.  These kernel threads are called
+   lwps.  The ttrace(2) interface gives us almost full control over
+   the threads, which makes it very easy to support them in GDB.  We
+   identify the threads by process ID and lwp ID.  The ttrace(2) also
+   provides us with a thread's user ID (in the `tts_user_tid' member
+   of `ttstate_t') but we don't use that (yet) as it isn't necessary
+   to uniquely label the thread.  */
+
+/* Number of active lwps.  */
+static int inf_ttrace_num_lwps;
+
+
 /* On HP-UX versions that have the ttrace(2) system call, we can
    implement "hardware" watchpoints by fiddling with the protection of
    pages in the address space that contain the variable being watched.
@@ -65,8 +79,8 @@ struct inf_ttrace_page_dict
   int count;			/* Number of pages in this dictionary.  */
 } inf_ttrace_page_dict;
 
-/* Number of threads that are currently in a system call.  */
-static int inf_ttrace_num_threads_in_syscall;
+/* Number of lwps that are currently in a system call.  */
+static int inf_ttrace_num_lwps_in_syscall;
 
 /* Flag to indicate whether we should re-enable page protections after
    the next wait.  */
@@ -80,7 +94,7 @@ inf_ttrace_enable_syscall_events (pid_t 
   ttevent_t tte;
   ttstate_t tts;
 
-  gdb_assert (inf_ttrace_num_threads_in_syscall == 0);
+  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
 
   if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
 	      (uintptr_t)&tte, sizeof tte, 0) == -1)
@@ -97,7 +111,7 @@ inf_ttrace_enable_syscall_events (pid_t 
     perror_with_name ("ttrace");
 
   if (tts.tts_flags & TTS_INSYSCALL)
-    inf_ttrace_num_threads_in_syscall++;
+    inf_ttrace_num_lwps_in_syscall++;
 
   /* FIXME: Handle multiple threads.  */
 }
@@ -121,7 +135,7 @@ inf_ttrace_disable_syscall_events (pid_t
 	      (uintptr_t)&tte, sizeof tte, 0) == -1)
     perror_with_name ("ttrace");
 
-  inf_ttrace_num_threads_in_syscall = 0;
+  inf_ttrace_num_lwps_in_syscall = 0;
 }
 
 /* Get information about the page at address ADDR for process PID from
@@ -191,7 +205,7 @@ inf_ttrace_add_page (pid_t pid, CORE_ADD
       if (inf_ttrace_page_dict.count == 1)
 	inf_ttrace_enable_syscall_events (pid);
 
-      if (inf_ttrace_num_threads_in_syscall == 0)
+      if (inf_ttrace_num_lwps_in_syscall == 0)
 	{
 	  if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
 		      addr, pagesize, prot & ~PROT_WRITE) == -1)
@@ -231,7 +245,7 @@ inf_ttrace_remove_page (pid_t pid, CORE_
 
   if (page->refcount == 0)
     {
-      if (inf_ttrace_num_threads_in_syscall == 0)
+      if (inf_ttrace_num_lwps_in_syscall == 0)
 	{
 	  if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
 		      addr, pagesize, page->prot) == -1)
@@ -449,7 +463,8 @@ inf_ttrace_him (int pid)
 
   /* Set the initial event mask.  */
   memset (&tte, 0, sizeof (tte));
-  tte.tte_events = TTEVT_EXEC | TTEVT_EXIT;
+  tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT;
+  tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
   tte.tte_opts = TTEO_NOSTRCCHLD;
   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
 	      (uintptr_t)&tte, sizeof tte, 0) == -1)
@@ -484,8 +499,9 @@ static void
 inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env,
 			    int from_tty)
 {
+  gdb_assert (inf_ttrace_num_lwps == 0);
+  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
   gdb_assert (inf_ttrace_page_dict.count == 0);
-  gdb_assert (inf_ttrace_num_threads_in_syscall == 0);
   gdb_assert (inf_ttrace_reenable_page_protections == 0);
 
   fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
@@ -518,7 +534,8 @@ inf_ttrace_mourn_inferior (void)
   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
   int bucket;
 
-  inf_ttrace_num_threads_in_syscall = 0;
+  inf_ttrace_num_lwps = 0;
+  inf_ttrace_num_lwps_in_syscall = 0;
 
   for (bucket = 0; bucket < num_buckets; bucket++)
     {
@@ -572,14 +589,17 @@ inf_ttrace_attach (char *args, int from_
       gdb_flush (gdb_stdout);
     }
 
+  gdb_assert (inf_ttrace_num_lwps == 0);
+  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
+
   if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
     perror_with_name ("ttrace");
   attach_flag = 1;
 
   /* Set the initial event mask.  */
-  gdb_assert (inf_ttrace_num_threads_in_syscall == 0);
   memset (&tte, 0, sizeof (tte));
-  tte.tte_events = TTEVT_EXEC | TTEVT_EXIT;
+  tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT;
+  tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
   tte.tte_opts = TTEO_NOSTRCCHLD;
   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
 	      (uintptr_t)&tte, sizeof tte, 0) == -1)
@@ -616,7 +636,8 @@ inf_ttrace_detach (char *args, int from_
   if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
     perror_with_name ("ttrace");
 
-  inf_ttrace_num_threads_in_syscall = 0;
+  inf_ttrace_num_lwps = 0;
+  inf_ttrace_num_lwps_in_syscall = 0;
 
   unpush_target (ttrace_ops_hack);
   inferior_ptid = null_ptid;
@@ -655,7 +676,7 @@ inf_ttrace_wait (ptid_t ptid, struct tar
   ttstate_t tts;
 
   /* Until proven otherwise.  */
-  ourstatus->kind = TARGET_WAITKIND_IGNORE;
+  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
 
   if (pid == -1)
     pid = 0;
@@ -678,11 +699,13 @@ inf_ttrace_wait (ptid_t ptid, struct tar
   /* Now that we've waited, we can re-enable the page protections.  */
   if (inf_ttrace_reenable_page_protections)
     {
-      gdb_assert (inf_ttrace_num_threads_in_syscall == 0);
+      gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
       inf_ttrace_enable_page_protections (tts.tts_pid);
       inf_ttrace_reenable_page_protections = 0;
     }
 
+  ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
+
   switch (tts.tts_event)
     {
     case TTEVT_EXEC:
@@ -693,6 +716,40 @@ inf_ttrace_wait (ptid_t ptid, struct tar
 
     case TTEVT_EXIT:
       store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
+      inf_ttrace_num_lwps = 0;
+      break;
+
+    case TTEVT_LWP_CREATE:
+      lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
+      ptid = ptid_build (tts.tts_pid, lwpid, 0);
+      if (inf_ttrace_num_lwps == 0)
+	{
+	  /* Now that we're going to be multi-threaded, add the
+	     origional thread to the list first.  */
+	  add_thread (ptid_build (tts.tts_pid, tts.tts_lwpid, 0));
+	  inf_ttrace_num_lwps++;
+	}
+      printf_filtered ("[New %s]\n", target_pid_to_str (ptid));
+      add_thread (ptid);
+      inf_ttrace_num_lwps++;
+      ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
+      break;
+
+    case TTEVT_LWP_EXIT:
+      printf_filtered("[%s exited]\n", target_pid_to_str (ptid));
+      delete_thread (ptid);
+      inf_ttrace_num_lwps--;
+      /* If we don't return -1 here, core GDB will re-add the thread.  */
+      ptid = minus_one_ptid;
+      break;
+
+    case TTEVT_LWP_TERMINATE:
+      lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
+      ptid = ptid_build (tts.tts_pid, lwpid, 0);
+      printf_filtered("[%s has been terminated]\n", target_pid_to_str (ptid));
+      delete_thread (ptid);
+      inf_ttrace_num_lwps--;
+      ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
       break;
 
     case TTEVT_SIGNAL:
@@ -703,8 +760,8 @@ inf_ttrace_wait (ptid_t ptid, struct tar
 
     case TTEVT_SYSCALL_ENTRY:
       gdb_assert (inf_ttrace_reenable_page_protections == 0);
-      inf_ttrace_num_threads_in_syscall++;
-      if (inf_ttrace_num_threads_in_syscall == 1)
+      inf_ttrace_num_lwps_in_syscall++;
+      if (inf_ttrace_num_lwps_in_syscall == 1)
 	{
 	  /* A thread has just entered a system call.  Disable any
              page protections as the kernel can't deal with them.  */
@@ -715,19 +772,23 @@ inf_ttrace_wait (ptid_t ptid, struct tar
       break;
 
     case TTEVT_SYSCALL_RETURN:
-      if (inf_ttrace_num_threads_in_syscall > 0)
+      if (inf_ttrace_num_lwps_in_syscall > 0)
 	{
 	  /* If the last thread has just left the system call, this
 	     would be a logical place to re-enable the page
 	     protections, but that doesn't work.  We can't re-enable
 	     them until we've done another wait.  */
 	  inf_ttrace_reenable_page_protections = 
-	    (inf_ttrace_num_threads_in_syscall == 1);
-	  inf_ttrace_num_threads_in_syscall--;
+	    (inf_ttrace_num_lwps_in_syscall == 1);
+	  inf_ttrace_num_lwps_in_syscall--;
 	}
       ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
       ourstatus->value.syscall_id = tts.tts_scno;
       break;
+
+    default:
+      gdb_assert (!"Unexpected ttrace event");
+      break;
     }
 
   /* Make sure all threads within the process are stopped.  */
@@ -737,9 +798,9 @@ inf_ttrace_wait (ptid_t ptid, struct tar
   /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
      process isn't recognized as a new thread.  */
   if (ptid_get_lwp (inferior_ptid) == 0)
-    inferior_ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, tts.tts_user_tid);
+    inferior_ptid = ptid;
 
-  return ptid_build (tts.tts_pid, tts.tts_lwpid, tts.tts_user_tid);
+  return ptid;
 }
 
 /* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
@@ -805,6 +866,28 @@ inf_ttrace_files_info (struct target_ops
 		     attach_flag ? "attached" : "child",
 		     target_pid_to_str (inferior_ptid));
 }
+
+static int
+inf_ttrace_thread_alive (ptid_t ptid)
+{
+  return 1;
+}
+
+static char *
+inf_ttrace_pid_to_str (ptid_t ptid)
+{
+  if (inf_ttrace_num_lwps > 0)
+    {
+      pid_t pid = ptid_get_pid (ptid);
+      lwpid_t lwpid = ptid_get_lwp (ptid);
+      static char buf[80];
+
+      sprintf (buf, "process %ld, lwp %ld", (long)pid, (long)lwpid);
+      return buf;
+    }
+
+  return normal_pid_to_str (ptid);
+}
 
 
 struct target_ops *
@@ -821,6 +904,8 @@ inf_ttrace_target (void)
   t->to_wait = inf_ttrace_wait;
   t->to_xfer_partial = inf_ttrace_xfer_partial;
   t->to_files_info = inf_ttrace_files_info;
+  t->to_thread_alive = inf_ttrace_thread_alive;
+  t->to_pid_to_str = inf_ttrace_pid_to_str;
   t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
   t->to_region_size_ok_for_hw_watchpoint =
     inf_ttrace_region_size_ok_for_hw_watchpoint;
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.674
diff -u -p -r1.674 Makefile.in
--- Makefile.in 23 Nov 2004 21:14:32 -0000 1.674
+++ Makefile.in 7 Dec 2004 19:53:29 -0000
@@ -2088,9 +2088,9 @@ inflow.o: inflow.c $(defs_h) $(frame_h) 
 inf-ptrace.o: inf-ptrace.c $(defs_h) $(command_h) $(inferior_h) $(inflow_h) \
 	$(gdbcore_h) $(observer_h) $(gdb_string_h) $(gdb_ptrace_h) \
 	$(gdb_wait_h) $(inf_child_h)
-inf-ttrace.o: inf-ttrace.c $(defs_h) $(command_h) $(inferior_h) \
-	$(observer_h) $(target_h) $(gdb_assert_h) $(gdb_string_h) \
-	$(inf_child_h) $(inf_ttrace_h)
+inf-ttrace.o: inf-ttrace.c $(defs_h) $(command_h) $(gdbcore_h) \
+	$(gdbthread_h)$(inferior_h) $(observer_h) $(target_h) \
+	$(gdb_assert_h) $(gdb_string_h) $(inf_child_h) $(inf_ttrace_h)
 infptrace.o: infptrace.c $(defs_h) $(command_h) $(frame_h) $(gdbcore_h) \
 	$(inferior_h) $(regcache_h) $(target_h) $(gdb_assert_h) \
 	$(gdb_wait_h) $(gdb_string_h) $(gdb_dirent_h) $(gdb_ptrace_h)


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