--- ./gnu/dist/gdb6/gdb/config/i386/nbsdelf.mh.orig	2006-11-25 11:38:51.000000000 -0500
+++ ./gnu/dist/gdb6/gdb/config/i386/nbsdelf.mh	2010-04-19 12:07:20.000000000 -0400
@@ -1,6 +1,6 @@
 # Host: NetBSD/i386 ELF
 NATDEPFILES= fork-child.o inf-ptrace.o \
-	nbsd-nat.o i386bsd-nat.o i386nbsd-nat.o bsd-kvm.o
+	nbsd-nat.o i386bsd-nat.o i386nbsd-nat.o bsd-kvm.o nbsd-thread.o
 NAT_FILE= solib.h
 
 LOADLIBES= -lkvm
--- ./gnu/dist/gdb6/gdb/config/mips/nbsd.mh.orig	2006-12-06 13:25:29.000000000 -0500
+++ ./gnu/dist/gdb6/gdb/config/mips/nbsd.mh	2010-04-19 13:55:38.000000000 -0400
@@ -1,2 +1,2 @@
 # Host: NetBSD/mips
-NATDEPFILES= fork-child.o inf-ptrace.o nbsd-nat.o mipsnbsd-nat.o
+NATDEPFILES= fork-child.o inf-ptrace.o nbsd-nat.o mipsnbsd-nat.o nbsd-thread.o
--- ./gnu/dist/gdb6/gdb/mipsnbsd-nat.c.orig	2006-12-06 13:25:29.000000000 -0500
+++ ./gnu/dist/gdb6/gdb/mipsnbsd-nat.c	2010-04-19 13:58:25.000000000 -0400
@@ -23,6 +23,7 @@
 #include "inferior.h"
 #include "regcache.h"
 #include "target.h"
+#include "config.h"
 
 #include <sys/types.h>
 #include <sys/ptrace.h>
@@ -32,6 +33,7 @@
 #include "mips-tdep.h"
 #include "mipsnbsd-tdep.h"
 #include "inf-ptrace.h"
+#include "nbsd-thread.h"
 
 /* Determine if PT_GETREGS fetches this register.  */
 static int
@@ -48,7 +50,7 @@
       struct reg regs;
 
       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
-		  (PTRACE_TYPE_ARG3) &regs, 0) == -1)
+		  (PTRACE_TYPE_ARG3) &regs, TIDGET (inferior_ptid)) == -1)
 	perror_with_name (_("Couldn't get registers"));
       
       mipsnbsd_supply_reg ((char *) &regs, regno);
@@ -61,7 +63,7 @@
       struct fpreg fpregs;
 
       if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
-		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+		  (PTRACE_TYPE_ARG3) &fpregs, TIDGET (inferior_ptid)) == -1)
 	perror_with_name (_("Couldn't get floating point status"));
 
       mipsnbsd_supply_fpreg ((char *) &fpregs, regno);
@@ -76,13 +78,13 @@
       struct reg regs;
 
       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
-		  (PTRACE_TYPE_ARG3) &regs, 0) == -1)
+		  (PTRACE_TYPE_ARG3) &regs, TIDGET (inferior_ptid)) == -1)
 	perror_with_name (_("Couldn't get registers"));
 
       mipsnbsd_fill_reg ((char *) &regs, regno);
 
       if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), 
-		  (PTRACE_TYPE_ARG3) &regs, 0) == -1)
+		  (PTRACE_TYPE_ARG3) &regs, TIDGET (inferior_ptid)) == -1)
 	perror_with_name (_("Couldn't write registers"));
 
       if (regno != -1)
@@ -94,13 +96,13 @@
       struct fpreg fpregs; 
 
       if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
-		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+		  (PTRACE_TYPE_ARG3) &fpregs, TIDGET (inferior_ptid)) == -1)
 	perror_with_name (_("Couldn't get floating point status"));
 
       mipsnbsd_fill_fpreg ((char *) &fpregs, regno);
 
       if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
-		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+		  (PTRACE_TYPE_ARG3) &fpregs, TIDGET (inferior_ptid)) == -1)
 	perror_with_name (_("Couldn't write floating point status"));
     }
 }
@@ -115,6 +117,7 @@
   struct target_ops *t;
 
   t = inf_ptrace_target ();
+  init_nbsd_thread_ops (t);
   t->to_fetch_registers = mipsnbsd_fetch_inferior_registers;
   t->to_store_registers = mipsnbsd_store_inferior_registers;
   t->to_pid_to_exec_file = nbsd_pid_to_exec_file;
--- ./gnu/dist/gdb6/gdb/nbsd-thread.c.orig	2010-04-19 11:43:05.000000000 -0400
+++ ./gnu/dist/gdb6/gdb/nbsd-thread.c	2010-04-22 10:57:53.000000000 -0400
@@ -0,0 +1,714 @@
+/* Threads support for NetBSD 5.0.
+
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   Contributed by Paul Koning, Dell, inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "defs.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "inferior.h"
+#include "gdbthread.h"
+#include "regcache.h"
+#include "config.h"
+#include "nbsd-thread.h"
+
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Data structure used to track NetBSD thread state.  There is a 
+   vector of these, in ascending order of LWP ID.  */
+
+struct lwp_info
+{
+  /* The process ID of the LWP.  This is a combination of the process
+     ID and the LWP ID.  */
+  ptid_t ptid;
+  
+  /* Non-zero if we this LWP was reported as having been signalled
+     by the PT_LWPINFO ptrace() call.  */
+  int signalled;
+  
+  /* The waitstatus for this LWP's last event.  */
+  struct target_waitstatus waitstatus;
+};
+
+/* The lwp_info buffer and its control variables.  */
+static struct lwp_info *lwp_buffer;
+static int lwp_count;
+static int lwp_bufsize;
+
+/* Count of signals still pending delivery to GDB.  These are threads
+   that were found to be stopped and not breakpoints.  For threads that
+   hit a breakpoint, we simply push back the thread so it will hit the
+   break again (if it isn't removed before then) but for other signals,
+   for example faults, the signal remains pending, the "to_resume" that
+   resumes the whole process is skipped, and then the "to_wait" returns
+   the information about one of the pending signals instead.  */
+static int pending_sigs;
+
+/* The LWP ID of the thread being stepped, or 0 if none.  */
+static int step_lwpid;
+
+/* Flag to indicate whether last resume was a resume all threads or
+   a resume single thread.  */
+static int resume_all;
+
+/* Non-zero if the netbsd-thread layer is active.  */
+static int nbsd_thread_active = 0;
+
+/* The netbsd-thread target_ops structure.  */
+static struct target_ops nbsd_thread_ops;
+
+int debug_nbsd_thread;
+static void
+show_debug_nbsd_thread (struct ui_file *file, int from_tty,
+		      struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Debugging of NetBSD thread module is %s.\n"),
+		    value);
+}
+
+
+/* Activate thread support if appropriate.  Do nothing if thread
+   support is already active.  */
+
+static void
+enable_nbsd_thread (void)
+{
+  struct minimal_symbol *msym;
+  void* caller_context;
+  int status;
+
+  /* If already active, nothing more to do.  */
+  if (nbsd_thread_active)
+    return;
+
+  if (lwp_buffer != NULL)
+    {
+      xfree (lwp_buffer);
+      lwp_buffer = NULL;
+      lwp_count = lwp_bufsize = 0;
+    }
+  
+  /* push_target (&nbsd_thread_ops); */
+  nbsd_thread_active = 1;
+}
+
+/* Deactivate thread support.  Do nothing is thread support is
+   already inactive.  */
+
+#if 0
+static void
+disable_nbsd_thread (void)
+{
+  if (!nbsd_thread_active)
+    return;
+
+  unpush_target (&nbsd_thread_ops);
+  nbsd_thread_active = 0;
+}
+#endif
+
+/* Update our lwp_info buffer, and tell GDB about adds or deletes.
+
+   By doing the thread add and thread delete operations here as we
+   learn about threads, we allow users to run thread-specific commands
+   without needing to run "info threads" first. 
+
+   The argument is a pointer to the waitstatus struct, which
+   is copied into the waitstatus for the thread we find as the signalled
+   thread.  */
+
+static void
+update_lwpbuf (struct target_waitstatus *status)
+{
+  int pi;
+  lwpid_t lwp_id, sig_lwpid;
+  struct ptrace_lwpinfo pt_info;
+  ptid_t ptid;
+  
+  /* Accumulate an array of NetBSD threads, in descending order of LWP id.
+
+     The reason for using descending order is that this is the order
+     in which LWPs are returned by the ptrace() PT_LWPINFO function,
+     because it returns them in the order in which they exist in the
+     p_lwps list for the process, and new entries are assigned ascending
+     LWP IDs and are added to the head of that list.  */
+
+  lwp_id = sig_lwpid = 0;
+  pi = 0;
+  
+  while (1)
+    {
+      pt_info.pl_lwpid = lwp_id;
+      errno = 0;
+      if (ptrace (PT_LWPINFO, PIDGET (inferior_ptid),
+		  &pt_info, sizeof (pt_info)) == -1)
+	{
+	  if (errno == ESRCH)
+	    break;
+	  else if (errno != 0)
+	    perror_with_name (_("Couldn't get thread information"));
+	}
+
+      if (debug_nbsd_thread)
+	fprintf_unfiltered (gdb_stdlog,
+			    "NTUP: lwpinfo on %d returns lwp %d, pl_event %d\n",
+			    lwp_id, pt_info.pl_lwpid, pt_info.pl_event);
+	  
+      /* Retrieve the LWP ID that was found.  This also sets the ID to
+	 start from the next time around the loop.  */
+      lwp_id = pt_info.pl_lwpid;
+
+      /* LWP id 0 is end of list.  */
+      if (lwp_id == 0)
+	break;
+      
+      /* If the LWP we found has an ID less than the ID of the current
+	 buffer entry, then the current buffer entry is a deleted thread.
+	 Tell GDB about its demise, then remove it from the buffer. 
+	  
+	 We have to do this in a loop until we run out of threads
+	 to be removed.  */
+      while (pi < lwp_count && lwp_id < TIDGET (lwp_buffer[pi].ptid))
+	{
+	  if (debug_nbsd_thread)
+	    fprintf_unfiltered (gdb_stdlog,
+				"NTUP: thread ptid %d,%ld has disappeared\n",
+				PIDGET (lwp_buffer[pi].ptid),
+				TIDGET (lwp_buffer[pi].ptid));
+
+	  /* Tell GDB.  */
+	  delete_thread (lwp_buffer[pi].ptid);
+
+	  /* Remove the deleted entry.  */
+	  if (pi < lwp_count)
+	    memmove (lwp_buffer + pi + 1, lwp_buffer + pi, 
+		     (lwp_count - pi) * sizeof (struct lwp_info));
+	  lwp_count--;
+	}
+
+      /* If we're now at the end of the current buffer, or the LWP found
+	 has an LWP ID greater than the current entry in the buffer, this
+	 is a new thread.  Allocate more buffer space if need be,
+	 make room for this entry, and store it.  Then tell GDB about
+	 the new thread.  */
+      if (pi >= lwp_count || lwp_id > TIDGET (lwp_buffer[pi].ptid))
+	{
+	  /* Allocate more space, if we need it.  */
+	  if (lwp_count == lwp_bufsize)
+	    {
+	      if (lwp_bufsize)
+		lwp_bufsize *= 2;
+	      else
+		lwp_bufsize = 1;
+	      lwp_buffer = (struct lwp_info *) xrealloc (lwp_buffer, 
+							 lwp_bufsize * sizeof (struct lwp_info));
+	    }
+
+	  /* Push current and later entries, if any, over.  */
+	  if (pi < lwp_count)
+	    memmove (lwp_buffer + pi + 1, lwp_buffer + pi, 
+		     (lwp_count - pi) * sizeof (struct lwp_info));
+
+	  /* Update the count of LWPs.  */
+	  lwp_count++;
+
+	  /* Initialize the new entry.  */
+	  lwp_buffer[pi].ptid = MERGEPID (PIDGET (inferior_ptid), lwp_id);
+	  if (pt_info.pl_event == PL_EVENT_SIGNAL)
+	    {
+	      lwp_buffer[pi].signalled = 1;
+	      lwp_buffer[pi].waitstatus = *status;
+	      sig_lwpid = lwp_id;
+	    }
+	  else
+	    lwp_buffer[pi].signalled = 0;
+
+	  /* Advance the LWP buffer pointer.  */
+	  pi++;
+	  
+	  /* Tell GDB about the new thread.  */
+	  if (lwp_count == 1)
+	    {
+	      /* See if GDB still has TID zero, if so set the TID.  */
+	      if (TIDGET (inferior_ptid) == 0)
+		{
+		  struct thread_info *tp;
+		  
+		  ptid = MERGEPID (PIDGET (inferior_ptid), lwp_id);
+		  /* thread_change_ptid (inferior_ptid, ptid); */
+		  tp = find_thread_pid (inferior_ptid);
+		  if (tp != NULL)
+		    {
+		      tp->ptid = ptid;
+		      inferior_ptid = ptid;
+		  
+		      if (debug_nbsd_thread)
+			fprintf_unfiltered (gdb_stdlog,
+					    "NTUP: setting main thread ptid to %d,%ld\n",
+					    PIDGET (ptid), TIDGET (ptid));
+		    }
+		  else
+		    {
+		      /* New thread (first thread), add it to GDB.  */
+		      inferior_ptid = ptid;
+		      if (debug_nbsd_thread)
+			fprintf_unfiltered (gdb_stdlog,
+					    "NTUP: adding first thread ptid %d,%d\n",
+					    PIDGET (inferior_ptid), lwp_id);
+		      add_thread (ptid);
+		    }
+		}
+	    }
+	  else
+	    {
+	      /* New thread but not the first, add it to GDB.  */
+	      if (debug_nbsd_thread)
+		fprintf_unfiltered (gdb_stdlog,
+				    "NTUP: adding new thread ptid %d,%d\n",
+				    PIDGET (inferior_ptid), lwp_id);
+	      add_thread (MERGEPID (PIDGET (inferior_ptid), lwp_id));
+	    }
+	}
+      else
+	{
+	  /* Found an existing thread.  Update its status in the buffer.
+	     Note that we clear the signalled flag if this is the first
+	     call and this thread wasn't the signalled thread, but we 
+	     leave it alone on subsequent calls.  That way the subsequent
+	     calls will accumulate the set of signalled threads.  */
+	  if (pt_info.pl_event == PL_EVENT_SIGNAL)
+	    {
+	      lwp_buffer[pi].signalled = 1;
+	      lwp_buffer[pi].waitstatus = *status;
+	      sig_lwpid = lwp_id;
+	    }
+	  
+	  /* Advance the LWP buffer pointer.  */
+	  pi++;
+	}
+    }
+  if (debug_nbsd_thread)
+    fprintf_unfiltered (gdb_stdlog,
+			"NTUP: signalled thread lwpid is %d\n", sig_lwpid);
+
+}
+
+#if 0
+/* The "to_detach" method of the nbsd_thread_ops.  */
+
+static void
+nbsd_thread_detach (char *args, int from_tty)
+{   
+  struct target_ops *beneath = find_target_beneath (&nbsd_thread_ops);
+
+  disable_nbsd_thread ();
+  beneath->to_detach (args, from_tty);
+}
+#endif
+
+/* Resume execution of thread PTID, or all threads if PTID is -1.  If
+   STEP is nonzero, single-step it.  If SIGNAL is nonzero, give it
+   that signal.  */
+
+static void
+nbsd_thread_resume (ptid_t ptid, int step, enum target_signal signal)
+{
+  pid_t pid;
+  int request;
+  
+  /* A specific PTID means `step only this process id'.  */
+  if (ptid_equal (minus_one_ptid, ptid) || TIDGET (ptid) <= 0)
+    {
+      resume_all = 1;
+      ptid = inferior_ptid;
+    }
+  else
+    resume_all = 0;
+  
+  pid = ptid_get_pid (ptid);
+
+#if 0
+  if (catch_syscall_enabled () > 0)
+    request = PT_SYSCALL;
+  else
+#endif
+    request = PT_CONTINUE;
+
+#ifdef PT_STEP
+  if (step)
+    {
+      /* If this system does not support PT_STEP, a higher level
+         function will have called single_step() to transmute the step
+         request into a continue request (by setting breakpoints on
+         all possible successor instructions), so we don't have to
+         worry about that here.  */
+      request = PT_STEP;
+    }
+#endif
+
+  /* An address of (PTRACE_TYPE_ARG3)1 tells ptrace to continue from
+     where it was.  If GDB wanted it to start some other way, we have
+     already written a new program counter value to the child.  */
+  errno = 0;
+  if (debug_nbsd_thread)
+    fprintf_unfiltered (gdb_stdlog,
+			"NTR: %s ptid %d,%ld, %s, signal %d\n",
+			(step ? "stepping" : "resuming"),
+			PIDGET (ptid), TIDGET (ptid),
+			(resume_all ? "all threads" : "single thread"),
+			signal);
+
+  /* Assume not stepping some LWP ID.  */
+  step_lwpid = 0;
+  if (step)
+    {
+      step_lwpid = TIDGET (ptid);
+      if (step_lwpid < 0)
+	step_lwpid = -step_lwpid;
+    }	
+  
+  if (resume_all)
+    {
+      if (pending_sigs > 0)
+	{
+	  /* We have pending signals from the previous wait still 
+	     needing to be delivered.  So don't resume the process,
+	     instead take no action and we'll deliver one of those
+	     pending signals at the next wait.  */
+	  if (debug_nbsd_thread)
+	    fprintf_unfiltered (gdb_stdlog,
+				"NTR: ptid %d,%ld has %d pending signals, skipping resume\n",
+				PIDGET (ptid), TIDGET (ptid), pending_sigs);
+	  return;
+	}
+      if (step)
+	ptrace (request, pid, (void *) 1, TIDGET (ptid));
+      else
+	ptrace (request, pid, (void *) 1,
+		target_signal_to_host (signal));
+    }
+  else
+    ptrace (request, pid, (void *) 1, -TIDGET (ptid));
+  
+  if (errno != 0)
+    perror_with_name (("ptrace"));
+}
+
+/* Wait for the child specified by PTID to do something.  Return the
+   process ID of the child, or MINUS_ONE_PTID in case of error; store
+   the status in *OURSTATUS.  */
+
+static ptid_t
+nbsd_thread_wait2 (ptid_t ptid,
+		   struct target_waitstatus *ourstatus, int options)
+{
+  pid_t pid;
+  int status, save_errno;
+
+  do
+    {
+      set_sigint_trap ();
+
+      do
+	{
+	  if (debug_nbsd_thread)
+	    fprintf_unfiltered (gdb_stdlog,
+				"NTW2: waiting for ptid %d,%ld, opt %d\n",
+				PIDGET (ptid), TIDGET (ptid), options);
+
+	  pid = waitpid (ptid_get_pid (ptid), &status, options);
+	  save_errno = errno;
+	  if (debug_nbsd_thread)
+	    fprintf_unfiltered (gdb_stdlog,
+				"NTW2: waitpid errno is %d, pid %d, status %x\n",
+				save_errno, pid, status);
+	}
+      while (pid == -1 && save_errno == EINTR);
+
+      clear_sigint_trap ();
+
+      /* If nothing found in the no wait case, report that.  */
+      if (options == WNOHANG && pid == 0)
+	return pid_to_ptid (-1);
+      
+      if (pid == -1)
+	{
+	  fprintf_unfiltered (gdb_stderr,
+			      _("Child process unexpectedly missing: %s.\n"),
+			      safe_strerror (save_errno));
+
+	  /* If first wait, claim it exited with unknown signal; 
+	     else claim there is nothing left to wait for.  */
+	  if (options == WNOHANG)
+	    return pid_to_ptid (-1);
+	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+	  return inferior_ptid;
+	}
+
+      /* Ignore terminated detached child processes.  */
+      if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
+	pid = -1;
+    }
+  while (pid == -1);
+
+  store_waitstatus (ourstatus, status);
+  return pid_to_ptid (pid);
+}
+
+static int
+nbsd_thread_cancel_breakpoint (struct lwp_info *lp)
+{
+  /* Arrange for a breakpoint to be hit again later.  We don't keep
+     the SIGTRAP status and don't forward the SIGTRAP signal to the
+     LWP.  We will handle the current event, eventually we will resume
+     this LWP, and this breakpoint will trap again.
+
+     If we do not do this, then we run the risk that the user will
+     delete or disable the breakpoint, but the LWP will have already
+     tripped on it.  */
+
+  if (lp->waitstatus.kind  == TARGET_WAITKIND_STOPPED
+      && lp->waitstatus.value.sig == SIGTRAP
+      && breakpoint_inserted_here_p (read_pc_pid (lp->ptid) -
+				     DECR_PC_AFTER_BREAK))
+    {
+      if (debug_nbsd_thread)
+	fprintf_unfiltered (gdb_stdlog,
+			    "NTCB: Push back breakpoint for ptid %d,%ld\n",
+			    PIDGET (lp->ptid), TIDGET (lp->ptid));
+
+      /* Back up the PC if necessary.  */
+      if (DECR_PC_AFTER_BREAK)
+	write_pc_pid (read_pc_pid (lp->ptid) - DECR_PC_AFTER_BREAK, lp->ptid);
+
+      /* We no longer have a pending signal for this thread.  */
+      lp->signalled = 0;
+
+      /* Not a pending signal anymore.  */
+      return 1;
+    }
+  return 0;
+}
+
+/* The "to_wait" method of the nbsd_thread_ops.  */
+
+static ptid_t
+nbsd_thread_wait (ptid_t ptid, struct target_waitstatus *status)
+{
+  ptid_t active_ptid;
+  struct lwp_info *sel_thread;
+  int sig_threads, i;
+  struct target_waitstatus tstatus;
+
+  /* If there were pending signals and a resume all threads was done,
+     the process wasn't actually resumed so don't wait on it.  Just
+     go on to pick a thread to report on.  */
+  if (!(pending_sigs > 0 && resume_all))
+    {
+      ptid = nbsd_thread_wait2 (ptid, &tstatus, 0);
+
+      /* Default status returned is the one we just got.  */
+      *status = tstatus;
+      
+      /* The ptid returned by the target beneath us is the ptid of the process.
+	 We need to find which thread is currently active and return 
+	 its ptid.  */
+      update_lwpbuf (&tstatus);
+  
+      /* Loop checking for additional threads that are waiting, and gather
+	 up their status.  */
+      while (1)
+	{
+	  ptid = nbsd_thread_wait2 (ptid, &tstatus, WNOHANG);
+	  if (PIDGET (ptid) == -1)
+	    break;
+	  update_lwpbuf (&tstatus);
+	}
+    }
+  
+  /* Find a suitable signalled thread.  Pick the stepped one, if there
+     is one; otherwise pick a random one.  */
+  sel_thread = NULL;
+  sig_threads = 0;
+  
+  for (i = 0; i < lwp_count; i++)
+    {
+      if (lwp_buffer[i].signalled)
+	{
+	  sig_threads++;
+	  if (TIDGET (lwp_buffer[i].ptid) == step_lwpid)
+	    {
+	      /* If there is a stepped thread, pick that one.  */
+	      sel_thread = &lwp_buffer[i];
+	      if (debug_nbsd_thread)
+		fprintf_unfiltered (gdb_stdlog,
+				    "NTW: Picking ptid %d,%ld because it is stepped\n",
+				    PIDGET (sel_thread->ptid),
+				    TIDGET (sel_thread->ptid));
+	      break;
+	    }
+	  /* Randomly pick this one or keep the previous choice,
+	     such that all of the signalled threads have an equal
+	     probability of being picked.  */
+	  if (sel_thread == NULL || 
+	      (((double) rand ()) / (RAND_MAX + 1.0)) < (1.0 / sig_threads))
+	    {
+	      sel_thread = &lwp_buffer[i];
+	      if (debug_nbsd_thread)
+		fprintf_unfiltered (gdb_stdlog,
+				    "NTW: Picking ptid %d,%ld out of %d\n",
+				    PIDGET (sel_thread->ptid),
+				    TIDGET (sel_thread->ptid), sig_threads);
+	    }
+	}
+    }
+  
+  /* Scan the LWP table again.  For each signalled LWP other than the
+     chosen one, back it up to the breakpoint if it was stopped by a
+     breakpoint and mark it as not signalled (it will re-break next
+     time we run the whole process).  Other LWPs (those with signals
+     other than breakpoint stop) are counted but not backed up; if we
+     find any of those then those will be delivered next.  */
+  pending_sigs = 0;
+  if (sig_threads > 1)
+    {
+      for (i = 0; i < lwp_count; i++)
+	{
+	  /* Skip the selected LWP.  */
+	  if (&lwp_buffer[i] == sel_thread)
+	    continue;
+	  
+	  if (lwp_buffer[i].signalled)
+	    {
+	      if (WIFSTOPPED (lwp_buffer[i].waitstatus))
+		{
+		  if (!nbsd_thread_cancel_breakpoint (&lwp_buffer[i]))
+		    pending_sigs++;
+		}
+	      else
+		pending_sigs++;
+	    }
+	}
+    }
+  
+  ptid = inferior_ptid;
+  if (sel_thread != NULL)
+    {
+      ptid =  MERGEPID (PIDGET (ptid), TIDGET (sel_thread->ptid));
+      *status = tstatus;
+      
+      /* The signal for this thread is now being reported, so clear
+	 the flag that says it hasn't been reported yet.  */
+      sel_thread->signalled = 0;
+    }
+  else if (debug_nbsd_thread)
+    fprintf_unfiltered (gdb_stdlog,
+			"NTW: no signalled thread\n");
+
+  if (debug_nbsd_thread)
+    fprintf_unfiltered (gdb_stdlog,
+			"NTW: returning ptid %d,%ld\n",
+			PIDGET (ptid), TIDGET (ptid));
+
+  return ptid;
+}
+
+/* The "to_mourn_inferior" method of the nbsd_thread_ops.  */
+
+static void
+nbsd_thread_mourn_inferior (void)
+{
+  int status;
+
+  /* Wait just one more time to collect the inferior's exit status.
+     Do not check whether this succeeds though, since we may be
+     dealing with a process that we attached to.  Such a process will
+     only report its exit status to its original parent.  */
+  waitpid (ptid_get_pid (inferior_ptid), &status, WNOHANG);
+
+  generic_mourn_inferior ();
+
+  /* if (!have_inferiors ()) */
+    unpush_target (&nbsd_thread_ops);
+}
+
+
+/* The "to_thread_alive" method of the nbsd_thread_ops.  */
+static int
+nbsd_thread_thread_alive (ptid_t ptid)
+{
+  /* The thread list maintained by GDB is up to date, since we update
+     it everytime we stop.   So check this list.  */
+  return in_thread_list (ptid);
+}
+
+/* The "to_pid_to_str" method of the nbsd_thread_ops.  */
+
+static char *
+nbsd_thread_pid_to_str (ptid_t ptid)
+{
+  if (TIDGET (ptid) == 0)
+    {
+      return normal_pid_to_str (ptid);
+    }
+  return xstrprintf (_("Thread %ld"), TIDGET (ptid));
+}
+
+/* Update the target_ops with our thread machinery.  */
+
+void
+init_nbsd_thread_ops (struct target_ops *t)
+{
+  /* t->to_detach             = nbsd_thread_detach; */
+  t->to_resume             = nbsd_thread_resume;
+  t->to_wait               = nbsd_thread_wait;
+  t->to_mourn_inferior     = nbsd_thread_mourn_inferior;
+  t->to_thread_alive       = nbsd_thread_thread_alive;
+  t->to_pid_to_str         = nbsd_thread_pid_to_str;
+
+  enable_nbsd_thread ();
+}
+
+void
+_initialize_nbsd_thread (void)
+{
+#if 0
+  init_nbsd_thread_ops ();
+  add_target (&nbsd_thread_ops);
+#endif
+
+  add_setshow_zinteger_cmd ("nbsd-thread", class_maintenance,
+			    &debug_nbsd_thread, _("\
+Set debugging of NetBSD thread module."), _("\
+Show debugging of NetBSD thread module."), _("\
+Enables printf debugging output."),
+			    NULL,
+			    show_debug_nbsd_thread,
+			    &setdebuglist, &showdebuglist);
+}
--- ./gnu/dist/gdb6/gdb/nbsd-thread.h.orig	2010-04-19 11:43:05.000000000 -0400
+++ ./gnu/dist/gdb6/gdb/nbsd-thread.h	2010-04-19 11:43:05.000000000 -0400
@@ -0,0 +1,25 @@
+/* Threads support for NetBSD 5.0.
+
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   Contributed by Paul Koning, Dell, inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+extern void init_nbsd_thread_ops (struct target_ops *t);
+
--- ./gnu/dist/gdb6/gdb/i386bsd-nat.c.orig	2007-02-24 08:05:18.000000000 -0500
+++ ./gnu/dist/gdb6/gdb/i386bsd-nat.c	2010-04-19 12:45:01.000000000 -0400
@@ -90,7 +90,7 @@
 
 /* Supply the general-purpose registers in GREGS, to REGCACHE.  */
 
-static void
+void
 i386bsd_supply_gregset (struct regcache *regcache, const void *gregs)
 {
   const char *regs = gregs;
@@ -109,7 +109,7 @@
    GREGS.  If REGNUM is -1, collect and store all appropriate
    registers.  */
 
-static void
+void
 i386bsd_collect_gregset (const struct regcache *regcache,
 			 void *gregs, int regnum)
 {
--- ./gnu/dist/gdb6/gdb/i386bsd-nat.h.orig	2006-07-02 16:14:15.000000000 -0400
+++ ./gnu/dist/gdb6/gdb/i386bsd-nat.h	2010-04-19 11:43:05.000000000 -0400
@@ -27,4 +27,11 @@
 
 extern struct target_ops *i386bsd_target (void);
 
+extern void i386bsd_supply_gregset (struct regcache *regcache, 
+                                    const void *gregs);
+
+extern void i386bsd_collect_gregset (const struct regcache *regcache,
+                                     void *gregs, int regnum);
+
+
 #endif /* i386bsd-nat.h */
--- ./gnu/dist/gdb6/gdb/i386nbsd-nat.c.orig	2008-01-25 07:35:48.000000000 -0500
+++ ./gnu/dist/gdb6/gdb/i386nbsd-nat.c	2010-04-19 14:35:16.000000000 -0400
@@ -20,22 +20,29 @@
    Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
+#include "inferior.h"
 #include "gdbcore.h"
 #include "regcache.h"
 #include "target.h"
 
 #include "i386-tdep.h"
+#include "i387-tdep.h"
 #include "i386bsd-nat.h"
+#include "nbsd-thread.h"
 
 /* Support for debugging kernel virtual memory images.  */
 
 #include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
 #include <machine/frame.h>
 #include <machine/pcb.h>
 
 #include "nbsd-nat.h"
 #include "bsd-kvm.h"
 
+extern int debug_nbsd_thread;
+
 static int
 i386nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 {
@@ -99,6 +106,159 @@
 }
 
 
+
+/* Macro to determine if a register is fetched with PT_GETREGS.  */
+#define GETREGS_SUPPLIES(regnum) \
+  ((0 <= (regnum) && (regnum) <= 15))
+
+#ifdef HAVE_PT_GETXMMREGS
+/* Set to 1 if the kernel supports PT_GETXMMREGS.  Initialized to -1
+   so that we try PT_GETXMMREGS the first time around.  */
+static int have_ptrace_xmmregs = -1;
+#endif
+ 
+ 
+/* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
+   for all registers (including the floating point registers).  */
+
+static void
+i386nbsd_fetch_inferior_registers (int regnum)
+{
+  if (regnum == -1 || GETREGS_SUPPLIES (regnum))
+    {
+      struct reg regs;
+
+      if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
+		  (PTRACE_TYPE_ARG3) &regs, TIDGET (inferior_ptid)) == -1)
+	perror_with_name (_("Couldn't get registers"));
+
+      if (debug_nbsd_thread)
+	{
+	  if (regnum == -1)
+	    fprintf_unfiltered (gdb_stdlog,
+				"NFIR: ptid %d,%ld, regnum %d\n",
+				PIDGET (inferior_ptid), TIDGET (inferior_ptid),
+				regnum);
+	  else
+	    fprintf_unfiltered (gdb_stdlog,
+				"NFIR: ptid %d,%ld, regnum %d: %x\n",
+				PIDGET (inferior_ptid), TIDGET (inferior_ptid),
+				regnum, ((int *) &regs)[regnum]);
+	}
+
+      i386bsd_supply_gregset (current_regcache, &regs);
+      if (regnum != -1)
+	return;
+    }
+
+  if (regnum == -1 || regnum >= I386_ST0_REGNUM)
+    {
+      struct fpreg fpregs;
+#ifdef HAVE_PT_GETXMMREGS
+      char xmmregs[512];
+
+      if (have_ptrace_xmmregs != 0
+	  && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
+		    (PTRACE_TYPE_ARG3) xmmregs, TIDGET (inferior_ptid)) == 0)
+	{
+	  have_ptrace_xmmregs = 1;
+	  i387_supply_fxsave (current_regcache, -1, xmmregs);
+	}
+      else
+	{
+          if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
+		      (PTRACE_TYPE_ARG3) &fpregs, TIDGET (inferior_ptid)) == -1)
+	    perror_with_name (_("Couldn't get floating point status"));
+
+	  i387_supply_fsave (current_regcache, -1, &fpregs);
+	}
+#else
+      if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
+		  (PTRACE_TYPE_ARG3) &fpregs, TIDGET (inferior_ptid)) == -1)
+	perror_with_name (_("Couldn't get floating point status"));
+
+      i387_supply_fsave (current_regcache, -1, &fpregs);
+#endif
+    }
+}
+
+/* Store register REGNUM back into the inferior.  If REGNUM is -1, do
+   this for all registers (including the floating point registers).  */
+
+static void
+i386nbsd_store_inferior_registers (int regnum)
+{
+  if (regnum == -1 || GETREGS_SUPPLIES (regnum))
+    {
+      struct reg regs;
+
+      if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
+                  (PTRACE_TYPE_ARG3) &regs, TIDGET (inferior_ptid)) == -1)
+        perror_with_name (_("Couldn't get registers"));
+
+      i386bsd_collect_gregset (current_regcache, &regs, regnum);
+
+      if (debug_nbsd_thread)
+	{
+	  if (regnum == -1)
+	    fprintf_unfiltered (gdb_stdlog,
+				"NSIR: ptid %d,%ld, regnum %d\n",
+				PIDGET (inferior_ptid), TIDGET (inferior_ptid),
+				regnum);
+	  else
+	    fprintf_unfiltered (gdb_stdlog,
+				"NSIR: ptid %d,%ld, regnum %d: %x\n",
+				PIDGET (inferior_ptid), TIDGET (inferior_ptid),
+				regnum, ((int *) &regs)[regnum]);
+	}
+      
+      if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
+	          (PTRACE_TYPE_ARG3) &regs, TIDGET (inferior_ptid)) == -1)
+        perror_with_name (_("Couldn't write registers"));
+
+      if (regnum != -1)
+	return;
+    }
+
+  if (regnum == -1 || regnum >= I386_ST0_REGNUM)
+    {
+      struct fpreg fpregs;
+#ifdef HAVE_PT_GETXMMREGS
+      char xmmregs[512];
+
+      if (have_ptrace_xmmregs != 0
+	  && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
+		    (PTRACE_TYPE_ARG3) xmmregs, TIDGET (inferior_ptid)) == 0)
+	{
+	  have_ptrace_xmmregs = 1;
+
+	  i387_collect_fxsave (current_regcache, regnum, xmmregs);
+
+	  if (ptrace (PT_SETXMMREGS, PIDGET (inferior_ptid),
+		      (PTRACE_TYPE_ARG3) xmmregs, TIDGET (inferior_ptid)) == -1)
+            perror_with_name (_("Couldn't write XMM registers"));
+	}
+      else
+	{
+	  have_ptrace_xmmregs = 0;
+#endif
+          if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
+		      (PTRACE_TYPE_ARG3) &fpregs, TIDGET (inferior_ptid)) == -1)
+	    perror_with_name (_("Couldn't get floating point status"));
+
+          i387_collect_fsave (current_regcache, regnum, &fpregs);
+
+          if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
+		      (PTRACE_TYPE_ARG3) &fpregs, TIDGET (inferior_ptid)) == -1)
+	    perror_with_name (_("Couldn't write floating point status"));
+#ifdef HAVE_PT_GETXMMREGS
+        }
+#endif
+    }
+}
+
+
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 void _initialize_i386nbsd_nat (void);
 
@@ -109,7 +269,10 @@
 
   /* Add some extra features to the common *BSD/i386 target.  */
   t = i386bsd_target ();
+  init_nbsd_thread_ops (t);
   t->to_pid_to_exec_file = nbsd_pid_to_exec_file;
+  t->to_fetch_registers = i386nbsd_fetch_inferior_registers;
+  t->to_store_registers = i386nbsd_store_inferior_registers;  
   add_target (t);
 
   /* Support debugging kernel virtual memory images.  */
--- ./gnu/usr.bin/gdb6/arch/i386/defs.mk.orig	2006-11-25 11:38:51.000000000 -0500
+++ ./gnu/usr.bin/gdb6/arch/i386/defs.mk	2010-04-19 13:45:11.000000000 -0400
@@ -3,5 +3,5 @@
 # Generated from: NetBSD: mknative.common,v 1.8 2006/05/26 19:17:21 mrg Exp 
 #
 G_INTERNAL_CFLAGS=     -I. -I${GNUHOSTDIST}/gdb -I${GNUHOSTDIST}/gdb/config -DLOCALEDIR="\"/usr/share/locale\"" -DHAVE_CONFIG_H -I${GNUHOSTDIST}/gdb/../include/opcode -I${GNUHOSTDIST}/gdb/../readline/..  -I../bfd -I${GNUHOSTDIST}/gdb/../bfd -I${GNUHOSTDIST}/gdb/../include  -I../intl -I${GNUHOSTDIST}/gdb/../intl  -DMI_OUT=1 -DTUI=1 -Wimplicit -Wreturn-type -Wcomment -Wtrigraphs -Wformat -Wparentheses -Wpointer-arith -Wformat-nonliteral -Wunused-label -Wunused-function -Wno-pointer-sign 
-G_LIBGDB_OBS=i386-tdep.o i387-tdep.o i386bsd-tdep.o i386nbsd-tdep.o nbsd-tdep.o  corelow.o solib.o solib-svr4.o ser-base.o ser-unix.o ser-pipe.o ser-tcp.o fork-child.o inf-ptrace.o  nbsd-nat.o i386bsd-nat.o i386nbsd-nat.o bsd-kvm.o  remote.o dcache.o remote-utils.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o  cli-dump.o  cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o  cli-logging.o  cli-interp.o mi-out.o mi-console.o  mi-cmds.o mi-cmd-env.o mi-cmd-var.o mi-cmd-break.o mi-cmd-stack.o  mi-cmd-file.o mi-cmd-disas.o mi-symbol-cmds.o  mi-interp.o  mi-main.o mi-parse.o mi-getopt.o mi-common.o posix-hdep.o tui-command.o  tui-data.o  tui-disasm.o  tui-file.o tui.o  tui-hooks.o  tui-interp.o  tui-io.o  tui-layout.o  tui-out.o  tui-regs.o  tui-source.o  tui-stack.o  tui-win.o  tui-windata.o  tui-wingeneral.o  tui-winsource.o c-exp.o  cp-name-parser.o  objc-exp.o  ada-exp.o  jv-exp.o  f-exp.o m2-exp.o p-exp.o  version.o  annotate.o  auxv.o  bfd-target.o  blockframe.o breakpoint.o findvar.o regcache.o  charset.o disasm.o dummy-frame.o  source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o  block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o  infcall.o  infcmd.o infrun.o  expprint.o environ.o stack.o thread.o  exceptions.o  inf-child.o  interps.o  main.o  macrotab.o macrocmd.o macroexp.o macroscope.o  event-loop.o event-top.o inf-loop.o completer.o  gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o  memattr.o mem-break.o target.o parse.o language.o buildsym.o  std-regs.o  signals.o  kod.o kod-cisco.o  gdb-events.o  exec.o bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o  dbxread.o coffread.o coff-pe-read.o elfread.o  dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o  dwarf2expr.o dwarf2loc.o dwarf2-frame.o  ada-lang.o c-lang.o f-lang.o objc-lang.o  ui-out.o cli-out.o  varobj.o wrapper.o  jv-lang.o jv-valprint.o jv-typeprint.o  m2-lang.o p-lang.o p-typeprint.o p-valprint.o  scm-exp.o scm-lang.o scm-valprint.o  sentinel-frame.o  complaints.o typeprint.o  ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o  ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o  nlmread.o serial.o mdebugread.o top.o utils.o  ui-file.o  user-regs.o  frame.o frame-unwind.o doublest.o  frame-base.o  gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o  cp-namespace.o  reggroups.o regset.o  trad-frame.o  tramp-frame.o  solib.o solib-null.o  prologue-value.o inflow.o    init.o
+G_LIBGDB_OBS=i386-tdep.o i387-tdep.o i386bsd-tdep.o i386nbsd-tdep.o nbsd-tdep.o  corelow.o solib.o solib-svr4.o ser-base.o ser-unix.o ser-pipe.o ser-tcp.o fork-child.o inf-ptrace.o  nbsd-nat.o nbsd-thread.o i386bsd-nat.o i386nbsd-nat.o bsd-kvm.o  remote.o dcache.o remote-utils.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o  cli-dump.o  cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o  cli-logging.o  cli-interp.o mi-out.o mi-console.o  mi-cmds.o mi-cmd-env.o mi-cmd-var.o mi-cmd-break.o mi-cmd-stack.o  mi-cmd-file.o mi-cmd-disas.o mi-symbol-cmds.o  mi-interp.o  mi-main.o mi-parse.o mi-getopt.o mi-common.o posix-hdep.o tui-command.o  tui-data.o  tui-disasm.o  tui-file.o tui.o  tui-hooks.o  tui-interp.o  tui-io.o  tui-layout.o  tui-out.o  tui-regs.o  tui-source.o  tui-stack.o  tui-win.o  tui-windata.o  tui-wingeneral.o  tui-winsource.o c-exp.o  cp-name-parser.o  objc-exp.o  ada-exp.o  jv-exp.o  f-exp.o m2-exp.o p-exp.o  version.o  annotate.o  auxv.o  bfd-target.o  blockframe.o breakpoint.o findvar.o regcache.o  charset.o disasm.o dummy-frame.o  source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o  block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o  infcall.o  infcmd.o infrun.o  expprint.o environ.o stack.o thread.o  exceptions.o  inf-child.o  interps.o  main.o  macrotab.o macrocmd.o macroexp.o macroscope.o  event-loop.o event-top.o inf-loop.o completer.o  gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o  memattr.o mem-break.o target.o parse.o language.o buildsym.o  std-regs.o  signals.o  kod.o kod-cisco.o  gdb-events.o  exec.o bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o  dbxread.o coffread.o coff-pe-read.o elfread.o  dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o  dwarf2expr.o dwarf2loc.o dwarf2-frame.o  ada-lang.o c-lang.o f-lang.o objc-lang.o  ui-out.o cli-out.o  varobj.o wrapper.o  jv-lang.o jv-valprint.o jv-typeprint.o  m2-lang.o p-lang.o p-typeprint.o p-valprint.o  scm-exp.o scm-lang.o scm-valprint.o  sentinel-frame.o  complaints.o typeprint.o  ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o  ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o  nlmread.o serial.o mdebugread.o top.o utils.o  ui-file.o  user-regs.o  frame.o frame-unwind.o doublest.o  frame-base.o  gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o  cp-namespace.o  reggroups.o regset.o  trad-frame.o  tramp-frame.o  solib.o solib-null.o  prologue-value.o inflow.o    init.o
 G_SIM_OBS=
