* breakpoint.c (breakpoint_thread_match break_command_1):
authorStu Grossman <grossman@cygnus>
Sat, 16 Oct 1993 06:42:02 +0000 (06:42 +0000)
committerStu Grossman <grossman@cygnus>
Sat, 16 Oct 1993 06:42:02 +0000 (06:42 +0000)
Thread-specific breakpoint support.
* breakpoint.h (struct breakpoint):  Add thread id field.
* fork-child.c (fork_inferior):  Move call to init_thread_list()
back a bit so that init_trace_fun can do thread functions.
* hppa-tdep.c (restore_pc_queue):  Add pid to call to target_wait.
* hppab-nat.c (child_resume):  Handle default pid.
* hppah-nat.c (child_resume):  Handle default pid.
* i386lynx-nat.c (child_wait):  New arg pid.
* inflow.c (kill_command):  Reset thread list.
* infptrace.c (child_resume):  Handle default pid.
* infrun.c:  Thread-specific breakpoint support.
* inftarg.c (child_wait):  Add pid arg.
* osfsolib.c (solib_create_inferior_hook):  Add pid to call to
target_resume.
* procfs.c:  Multi-thread support.
* remote-bug.c (bug_wait):  Add pid arg.
* remote-hms.c (hms_wait):  Add pid arg.
* remote-mips.c (mips_wait):  Add pid arg.
* remote-mon.c (monitor_wait):  Add pid arg.
* remote-nindy.c (nindy_wait):  Add pid arg.
* remote-sim.c (gdbsim_wait):  Add pid arg.
* remote-udi.c (udi_wait):  Add pid arg.
* remote-vx.c (vx_wait):  Add pid arg.
* remote-z8k.c (sim_wait):  Add pid arg.
* remote.c (remote_wait):  Add pid arg.
* solib.c (solib_create_inferior_hook):  Add pid to call to
target_resume.
* target.h (struct target_ops):  Add pid arg to to_wait and
to_notice_signals.
* thread.c (valid_thread_id):  New func to validate thread #s.
* (pid_to_thread_id):  New func to do the obvious.
* thread.h:  Prototypes for above.

* coff-solib.c (coff_solib_add):  Use nameoffset field to locate
filename.

22 files changed:
gdb/ChangeLog
gdb/coff-solib.c
gdb/fork-child.c
gdb/hppa-tdep.c
gdb/hppab-nat.c
gdb/hppah-nat.c
gdb/i386lynx-nat.c
gdb/infrun.c
gdb/inftarg.c
gdb/osfsolib.c
gdb/procfs.c
gdb/remote-bug.c
gdb/remote-hms.c
gdb/remote-mips.c
gdb/remote-mon.c
gdb/remote-nindy.c
gdb/remote-sim.c
gdb/remote-udi.c
gdb/remote-vx.c
gdb/remote-z8k.c
gdb/thread.c
gdb/thread.h

index fcb792cca0808727b2ebb89f9d6b1b0fd3b1492e..61ed445ab0c1ecf41d643367237e0610c7637c8c 100644 (file)
@@ -1,3 +1,42 @@
+Fri Oct 15 22:46:07 1993  Stu Grossman  (grossman at cygnus.com)
+
+       * breakpoint.c (breakpoint_thread_match break_command_1):
+       Thread-specific breakpoint support.
+       * breakpoint.h (struct breakpoint):  Add thread id field.
+       * fork-child.c (fork_inferior):  Move call to init_thread_list()
+       back a bit so that init_trace_fun can do thread functions.
+       * hppa-tdep.c (restore_pc_queue):  Add pid to call to target_wait.
+       * hppab-nat.c (child_resume):  Handle default pid.
+       * hppah-nat.c (child_resume):  Handle default pid.
+       * i386lynx-nat.c (child_wait):  New arg pid.
+       * inflow.c (kill_command):  Reset thread list.
+       * infptrace.c (child_resume):  Handle default pid.
+       * infrun.c:  Thread-specific breakpoint support.
+       * inftarg.c (child_wait):  Add pid arg.
+       * osfsolib.c (solib_create_inferior_hook):  Add pid to call to
+       target_resume.
+       * procfs.c:  Multi-thread support.
+       * remote-bug.c (bug_wait):  Add pid arg.
+       * remote-hms.c (hms_wait):  Add pid arg.
+       * remote-mips.c (mips_wait):  Add pid arg.
+       * remote-mon.c (monitor_wait):  Add pid arg.
+       * remote-nindy.c (nindy_wait):  Add pid arg.
+       * remote-sim.c (gdbsim_wait):  Add pid arg.
+       * remote-udi.c (udi_wait):  Add pid arg.
+       * remote-vx.c (vx_wait):  Add pid arg.
+       * remote-z8k.c (sim_wait):  Add pid arg.
+       * remote.c (remote_wait):  Add pid arg.
+       * solib.c (solib_create_inferior_hook):  Add pid to call to
+       target_resume.
+       * target.h (struct target_ops):  Add pid arg to to_wait and
+       to_notice_signals.
+       * thread.c (valid_thread_id):  New func to validate thread #s.
+       * (pid_to_thread_id):  New func to do the obvious.
+       * thread.h:  Prototypes for above.
+
+       * coff-solib.c (coff_solib_add):  Use nameoffset field to locate
+       filename.
+
 Fri Oct 15 21:29:40 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
 
        * h8300-tdep.c, h8500-tdep.c: Define sim_load only, but not
index a4bf6c4ebf770110b160e9cd5e65b80edb85a04a..01ffc9c6347f7c216d3c97ae4cc282d17e41e7e2 100644 (file)
@@ -62,8 +62,7 @@ coff_solib_add (arg_string, from_tty, target)
       struct libent
        {
          bfd_byte len[4];
-         bfd_byte unk[4];
-         char filename[1];
+         bfd_byte nameoffset[4];
        };
 
       libsize = bfd_section_size (exec_bfd, libsect);
@@ -76,16 +75,21 @@ coff_solib_add (arg_string, from_tty, target)
        {
          struct libent *ent;
          struct objfile *objfile;
-         int len;
+         int len, nameoffset;
+         char *filename;
 
          ent = (struct libent *)lib;
 
          len = bfd_get_32 (exec_bfd, ent->len);
 
+         nameoffset = bfd_get_32 (exec_bfd, ent->nameoffset);
+
          if (len <= 0)
            break;
 
-         objfile = symbol_file_add (ent->filename, from_tty,
+         filename = (char *)ent + nameoffset * 4;
+
+         objfile = symbol_file_add (filename, from_tty,
                                     0, /* addr */
                                     0, /* not mainline */
                                     0, /* not mapped */
index e982864ccf1aa3a189c9ebf17dd715f326c82b48..9aa3cfef016439024cccfce955225339d5b0e091 100644 (file)
@@ -238,11 +238,15 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun)
   /* Restore our environment in case a vforked child clob'd it.  */
   environ = save_our_env;
 
+  init_thread_list();
+
   /* Now that we have a child process, make it our target, and
      initialize anything target-vector-specific that needs initializing.  */
   (*init_trace_fun)(pid);
 
-  init_thread_list();
+#ifdef CREATE_INFERIOR_HOOK
+  CREATE_INFERIOR_HOOK (pid);
+#endif  
 
   /* The process was started by the fork that created it,
      but it will have stopped one instruction after execing the shell.
index 7ebe97d5d635b43356367390a8965bdab16d102f..058c8741503923217a0e09e9aaaae96a6b436a40 100644 (file)
@@ -869,7 +869,7 @@ restore_pc_queue (fsr)
   for (insn_count = 0; insn_count < 3; insn_count++)
     {
       resume (1, 0);
-      target_wait(&w);
+      target_wait(inferior_pid, &w);
 
       if (!WIFSTOPPED (w))
         {
index b45af8462c1660cf8f605d218a291f3456ec4ba5..5f3cdf724dc7a6d1d45d0af7971aa11a1d153d6d 100644 (file)
@@ -261,6 +261,9 @@ child_resume (pid, step, signal)
 {
   errno = 0;
 
+  if (pid == -1)
+    pid = inferior_pid;
+
   /* An address of (PTRACE_ARG3_TYPE) 1 tells ptrace to continue from where
      it was. (If GDB wanted it to start some other way, we have already
      written a new PC value to the child.)  */
index 7c0459368d6413d8108660a6fb83c840913ca76e..60942dfd64f5e92a86bade180df9dfb8cb4c3a01 100644 (file)
@@ -212,6 +212,9 @@ child_resume (pid, step, signal)
 {
   errno = 0;
 
+  if (pid == -1)
+    pid = inferior_pid;
+
   /* An address of (PTRACE_ARG3_TYPE) 1 tells ptrace to continue from where
      it was. (If GDB wanted it to start some other way, we have already
      written a new PC value to the child.)  */
index 5d3fb211a6f2d1faefd03b5be80c0eeb295af701..4153a47f8a6511e08c7b79ac5e9fad3eac39e81c 100644 (file)
@@ -187,10 +187,10 @@ store_inferior_registers (regno)
    of error; store status through argument pointer STATUS.  */
 
 int
-child_wait (status)
+child_wait (pid, status)
+     int pid;
      int *status;
 {
-  int pid;
   int save_errno;
   int thread;
 
index e32d70574a3101f0cbcbed3dbf6e17da7484ba51..c4e58ce949b87a377b8277fac8ad3d5460ed6df5 100644 (file)
@@ -306,7 +306,7 @@ resume (step, sig)
   /* Install inferior's terminal modes.  */
   target_terminal_inferior ();
 
-  target_resume (inferior_pid, step, sig);
+  target_resume (-1, step, sig);
   discard_cleanups (old_cleanups);
 }
 
@@ -503,7 +503,7 @@ wait_for_inferior ()
       flush_cached_frames ();
       registers_changed ();
 
-      pid = target_wait (&w);
+      pid = target_wait (-1, &w);
 
 #ifdef SIGTRAP_STOP_AFTER_LOAD
 
@@ -559,7 +559,41 @@ wait_for_inferior ()
 #endif
          break;
        }
-      
+
+      stop_signal = WSTOPSIG (w);
+
+      if (pid != inferior_pid)
+       {
+         int save_pid = inferior_pid;
+
+         inferior_pid = pid;   /* Setup for target memory/regs */
+         registers_changed ();
+         stop_pc = read_pc ();
+         inferior_pid = save_pid;
+         registers_changed ();
+       }
+      else
+       stop_pc = read_pc ();
+
+      if (stop_signal == SIGTRAP
+         && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+       if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
+         {
+           /* Saw a breakpoint, but it was hit by the wrong thread.  Just continue. */
+           if (breakpoints_inserted)
+             {
+               remove_breakpoints ();
+               target_resume (pid, 1, 0); /* Single step */
+               target_wait (pid, NULL);
+               insert_breakpoints ();
+             }
+           target_resume (-1, 0, 0);
+           continue;
+         }
+       else
+         if (pid != inferior_pid)
+           goto switch_thread;
+
       if (pid != inferior_pid)
        {
          int printed = 0;
@@ -569,13 +603,11 @@ wait_for_inferior ()
              fprintf (stderr, "[New %s]\n", target_pid_to_str (pid));
              add_thread (pid);
 
-             target_resume (pid, 0, 0);
+             target_resume (-1, 0, 0);
              continue;
            }
          else
            {
-             stop_signal = WSTOPSIG (w);
-
              if (stop_signal >= NSIG || signal_print[stop_signal])
                {
                  char *signame;
@@ -593,8 +625,11 @@ wait_for_inferior ()
                  fflush (stdout);
                }
 
-             if (stop_signal >= NSIG || signal_stop[stop_signal])
+             if (stop_signal == SIGTRAP
+                 || stop_signal >= NSIG
+                 || signal_stop[stop_signal])
                {
+switch_thread:
                  inferior_pid = pid;
                  printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
 
@@ -624,12 +659,14 @@ wait_for_inferior ()
                  if (signal_program[stop_signal] == 0)
                    stop_signal = 0;
 
-                 target_resume (pid, 0, stop_signal);
+                 target_resume (-1, 0, stop_signal);
                  continue;
                }
            }
        }
 
+same_pid:
+
 #ifdef NO_SINGLE_STEP
       if (one_stepped)
        single_step (0);        /* This actually cleans up the ss */
@@ -644,7 +681,6 @@ wait_for_inferior ()
          continue;
        }
 
-      stop_pc = read_pc ();
       set_current_frame ( create_new_frame (read_fp (), stop_pc));
 
       stop_frame_address = FRAME_FP (get_current_frame ());
@@ -674,8 +710,6 @@ wait_for_inferior ()
         3) set random_signal to 1, and the decision between 1 and 2
         will be made according to the signal handling tables.  */
       
-      stop_signal = WSTOPSIG (w);
-      
       /* First, distinguish signals caused by the debugger from signals
         that have to do with the program's own actions.
         Note that breakpoint insns may cause SIGTRAP or SIGILL
@@ -1598,7 +1632,7 @@ handle_command (args, from_tty)
       argv++;
     }
 
-  target_notice_signals();
+  target_notice_signals(inferior_pid);
 
   if (from_tty)
     {
index e357c0ebbe62779b62b00dc4628587a2566e15f1..3270fa687bbe3ac35633ebe6640d91fc86d95034 100644 (file)
@@ -24,23 +24,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "target.h"
 #include "wait.h"
 #include "gdbcore.h"
-#include "ieee-float.h"                /* Required by REGISTER_CONVERT_TO_XXX */
-#include "terminal.h"          /* For #ifdef TIOCGPGRP and new_tty */
 
 #include <signal.h>
 
-#ifdef SET_STACK_LIMIT_HUGE
-#include <sys/time.h>
-#include <sys/resource.h>
-
-extern int original_stack_limit;
-#endif /* SET_STACK_LIMIT_HUGE */
-
 static void
 child_prepare_to_store PARAMS ((void));
 
+#ifndef CHILD_WAIT
 static int
 child_wait PARAMS ((int *));
+#endif /* CHILD_WAIT */
 
 static void
 child_open PARAMS ((char *, int));
@@ -54,6 +47,12 @@ child_detach PARAMS ((char *, int));
 static void
 child_attach PARAMS ((char *, int));
 
+static void
+ptrace_me PARAMS ((void));
+
+static void
+ptrace_him PARAMS ((int));
+
 static void
 child_create_inferior PARAMS ((char *, char *, char **));
 
@@ -68,31 +67,41 @@ extern char **environ;
 /* Forward declaration */
 extern struct target_ops child_ops;
 
+#ifndef CHILD_WAIT
+
 /* Wait for child to do something.  Return pid of child, or -1 in case
    of error; store status through argument pointer STATUS.  */
 
 static int
-child_wait (status)
+child_wait (pid, status)
+     int pid;
      int *status;
 {
-  int pid;
+  int save_errno;
 
   do {
-#ifdef USE_PROC_FS
-    pid = proc_wait (status);
-#else
+    if (attach_flag)
+      set_sigint_trap();       /* Causes SIGINT to be passed on to the
+                                  attached process. */
     pid = wait (status);
-#endif
-    if (pid == -1)             /* No more children to wait for */
+    save_errno = errno;
+
+    if (attach_flag)
+      clear_sigint_trap();
+
+    if (pid == -1)
       {
-       fprintf (stderr, "Child process unexpectedly missing.\n");
+       if (save_errno == EINTR)
+         continue;
+       fprintf (stderr, "Child process unexpectedly missing: %s.\n",
+                safe_strerror (save_errno));
        *status = 42;   /* Claim it exited with signal 42 */
         return -1;
       }
   } while (pid != inferior_pid); /* Some other child died or stopped */
   return pid;
 }
-
+#endif /* CHILD_WAIT */
 
 /* Attach to process PID, then initialize for debugging it.  */
 
@@ -120,9 +129,9 @@ child_attach (args, from_tty)
       exec_file = (char *) get_exec_file (0);
 
       if (exec_file)
-       printf ("Attaching program `%s', pid %d\n", exec_file, pid);
+       printf ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
       else
-       printf ("Attaching pid %d\n", pid);
+       printf ("Attaching to %s\n", target_pid_to_str (pid));
 
       fflush (stdout);
     }
@@ -155,8 +164,8 @@ child_detach (args, from_tty)
       char *exec_file = get_exec_file (0);
       if (exec_file == 0)
        exec_file = "";
-      printf ("Detaching program: %s pid %d\n",
-             exec_file, inferior_pid);
+      printf ("Detaching from program: %s %s\n", exec_file,
+             target_pid_to_str (inferior_pid));
       fflush (stdout);
     }
   if (args)
@@ -190,8 +199,8 @@ static void
 child_files_info (ignore)
      struct target_ops *ignore;
 {
-  printf ("\tUsing the running image of %s process %d.\n",
-         attach_flag? "attached": "child", inferior_pid);
+  printf ("\tUsing the running image of %s %s.\n",
+         attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
 }
 
 /* ARGSUSED */
@@ -203,224 +212,40 @@ child_open (arg, from_tty)
   error ("Use the \"run\" command to start a Unix child process.");
 }
 
+/* Stub function which causes the inferior that runs it, to be ptrace-able
+   by its parent process.  */
+
+static void
+ptrace_me ()
+{
+  /* "Trace me, Dr. Memory!" */
+  call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
+}
+
+/* Stub function which causes the GDB that runs it, to start ptrace-ing
+   the child process.  */
+
+static void
+ptrace_him (pid)
+     int pid;
+{
+  push_target (&child_ops);
+}
+
 /* Start an inferior Unix child process and sets inferior_pid to its pid.
    EXEC_FILE is the file to run.
    ALLARGS is a string containing the arguments to the program.
    ENV is the environment vector to pass.  Errors reported with error().  */
 
-#ifndef SHELL_FILE
-#define SHELL_FILE "/bin/sh"
-#endif
-
 static void
 child_create_inferior (exec_file, allargs, env)
      char *exec_file;
      char *allargs;
      char **env;
 {
-  int pid;
-  char *shell_command;
-  char *shell_file;
-  static char default_shell_file[] = SHELL_FILE;
-  int len;
-  int pending_execs;
-  /* Set debug_fork then attach to the child while it sleeps, to debug. */
-  static int debug_fork = 0;
-  /* This is set to the result of setpgrp, which if vforked, will be visible
-     to you in the parent process.  It's only used by humans for debugging.  */
-  static int debug_setpgrp = 657473;
-  char **save_our_env;
-
-  /* If no exec file handed to us, get it from the exec-file command -- with
-     a good, common error message if none is specified.  */
-  if (exec_file == 0)
-    exec_file = get_exec_file(1);
-
-  /* The user might want tilde-expansion, and in general probably wants
-     the program to behave the same way as if run from
-     his/her favorite shell.  So we let the shell run it for us.
-     FIXME, this should probably search the local environment (as
-     modified by the setenv command), not the env gdb inherited.  */
-  shell_file = getenv ("SHELL");
-  if (shell_file == NULL)
-    shell_file = default_shell_file;
-  
-  len = 5 + strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop*/ 10;
-  /* If desired, concat something onto the front of ALLARGS.
-     SHELL_COMMAND is the result.  */
-#ifdef SHELL_COMMAND_CONCAT
-  shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + len);
-  strcpy (shell_command, SHELL_COMMAND_CONCAT);
-#else
-  shell_command = (char *) alloca (len);
-  shell_command[0] = '\0';
-#endif
-  strcat (shell_command, "exec ");
-  strcat (shell_command, exec_file);
-  strcat (shell_command, " ");
-  strcat (shell_command, allargs);
-
-  /* exec is said to fail if the executable is open.  */
-  close_exec_file ();
-
-  /* Retain a copy of our environment variables, since the child will
-     replace the value of  environ  and if we're vforked, we have to 
-     restore it.  */
-  save_our_env = environ;
-
-  /* Tell the terminal handling subsystem what tty we plan to run on;
-     it will just record the information for later.  */
-
-  new_tty_prefork (inferior_io_terminal);
-
-  /* It is generally good practice to flush any possible pending stdio
-     output prior to doing a fork, to avoid the possibility of both the
-     parent and child flushing the same data after the fork. */
-
-  fflush (stdout);
-  fflush (stderr);
-
-#if defined(USG) && !defined(HAVE_VFORK)
-  pid = fork ();
-#else
-  if (debug_fork)
-    pid = fork ();
-  else
-    pid = vfork ();
-#endif
-
-  if (pid < 0)
-    perror_with_name ("vfork");
-
-  if (pid == 0)
-    {
-      if (debug_fork) 
-       sleep (debug_fork);
-
-#ifdef TIOCGPGRP
-      /* Run inferior in a separate process group.  */
-#ifdef NEED_POSIX_SETPGID
-      debug_setpgrp = setpgid (0, 0);
-#else
-#if defined(USG) && !defined(SETPGRP_ARGS)
-      debug_setpgrp = setpgrp ();
-#else
-      debug_setpgrp = setpgrp (getpid (), getpid ());
-#endif /* USG */
-#endif /* NEED_POSIX_SETPGID */
-      if (debug_setpgrp == -1)
-        perror("setpgrp failed in child");
-#endif /* TIOCGPGRP */
-
-#ifdef SET_STACK_LIMIT_HUGE
-      /* Reset the stack limit back to what it was.  */
-      {
-       struct rlimit rlim;
-
-       getrlimit (RLIMIT_STACK, &rlim);
-       rlim.rlim_cur = original_stack_limit;
-       setrlimit (RLIMIT_STACK, &rlim);
-      }
-#endif /* SET_STACK_LIMIT_HUGE */
-
-      /* Ask the tty subsystem to switch to the one we specified earlier
-        (or to share the current terminal, if none was specified).  */
-
-      new_tty ();
-
-      /* Changing the signal handlers for the inferior after
-        a vfork can also change them for the superior, so we don't mess
-        with signals here.  See comments in
-        initialize_signals for how we get the right signal handlers
-        for the inferior.  */
-
-#ifdef USE_PROC_FS
-      /* Use SVR4 /proc interface */
-      proc_set_exec_trap ();
-#else
-      /* "Trace me, Dr. Memory!" */
-      call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
-#endif
-
-      /* There is no execlpe call, so we have to set the environment
-        for our child in the global variable.  If we've vforked, this
-        clobbers the parent, but environ is restored a few lines down
-        in the parent.  By the way, yes we do need to look down the
-        path to find $SHELL.  Rich Pixley says so, and I agree.  */
-      environ = env;
-      execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
-
-      fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
-              safe_strerror (errno));
-      fflush (stderr);
-      _exit (0177);
-    }
-
-  /* Restore our environment in case a vforked child clob'd it.  */
-  environ = save_our_env;
-
-  /* Now that we have a child process, make it our target.  */
-  push_target (&child_ops);
-
-#ifdef CREATE_INFERIOR_HOOK
-  CREATE_INFERIOR_HOOK (pid);
-#endif  
-
-/* The process was started by the fork that created it,
-   but it will have stopped one instruction after execing the shell.
-   Here we must get it up to actual execution of the real program.  */
-
-  inferior_pid = pid;          /* Needed for wait_for_inferior stuff below */
-
-  clear_proceed_status ();
-
-  /* We will get a trace trap after one instruction.
-     Continue it automatically.  Eventually (after shell does an exec)
-     it will get another trace trap.  Then insert breakpoints and continue.  */
-
-#ifdef START_INFERIOR_TRAPS_EXPECTED
-  pending_execs = START_INFERIOR_TRAPS_EXPECTED;
-#else
-  pending_execs = 2;
-#endif
-
-  init_wait_for_inferior ();
-
-  /* Set up the "saved terminal modes" of the inferior
-     based on what modes we are starting it with.  */
-  target_terminal_init ();
-
-  /* Install inferior's terminal modes.  */
-  target_terminal_inferior ();
-
-  while (1)
-    {
-      stop_soon_quietly = 1;   /* Make wait_for_inferior be quiet */
-      wait_for_inferior ();
-      if (stop_signal != SIGTRAP)
-       {
-         /* Let shell child handle its own signals in its own way */
-         /* FIXME, what if child has exit()ed?  Must exit loop somehow */
-         resume (0, stop_signal);
-       }
-      else
-       {
-         /* We handle SIGTRAP, however; it means child did an exec.  */
-         if (0 == --pending_execs)
-           break;
-         resume (0, 0);                /* Just make it go on */
-       }
-    }
-  stop_soon_quietly = 0;
-
-  /* We are now in the child process of interest, having exec'd the
-     correct program, and are poised at the first instruction of the
-     new program.  */
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
-  SOLIB_CREATE_INFERIOR_HOOK (pid);
-#endif
-
-  /* Pedal to the metal.  Away we go.  */
+  fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him);
+  /* We are at the first instruction we care about.  */
+  /* Pedal to the metal... */
   proceed ((CORE_ADDR) -1, 0, 0);
 }
 
@@ -465,6 +290,7 @@ struct target_ops child_ops = {
   child_create_inferior,       /* to_create_inferior */
   child_mourn_inferior,                /* to_mourn_inferior */
   child_can_run,               /* to_can_run */
+  0,                           /* to_notice_signals */
   process_stratum,             /* to_stratum */
   0,                           /* to_next */
   1,                           /* to_has_all_memory */
index 549258adb3a0d7d37fb90d6214d46cd2858b8740..4006f172f8bbf88b4908327a0752fb39c74b1212 100644 (file)
@@ -742,7 +742,7 @@ solib_create_inferior_hook()
   stop_signal = 0;
   do
     {
-      target_resume (inferior_pid, 0, stop_signal);
+      target_resume (-1, 0, stop_signal);
       wait_for_inferior ();
     }
   while (stop_signal != SIGTRAP);
index 4c8ab5ccfe9d532b274b55f387fd30aeacd2dda3..04b3ae23707ace213e46cda6c339cb14625d2915 100644 (file)
@@ -39,6 +39,8 @@ regardless of whether or not the actual target has floating point hardware.
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
+#include <stropts.h>
+#include <poll.h>
 
 #include "inferior.h"
 #include "target.h"
@@ -74,10 +76,11 @@ CORE_ADDR kernel_u_addr;
     the inferior's procinfo information. */
 
 struct procinfo {
-  int valid;                   /* Nonzero if pid, fd, & pathname are valid */
+  struct procinfo *next;
   int pid;                     /* Process ID of inferior */
   int fd;                      /* File descriptor for /proc entry */
   char *pathname;              /* Pathname to /proc entry */
+  int had_event;               /* poll/select says something happened */
   int was_stopped;             /* Nonzero if was stopped prior to attach */
   int nopass_next_sigstop;     /* Don't pass a sigstop on next resume */
   prrun_t prrun;               /* Control state when it is run */
@@ -95,7 +98,14 @@ struct procinfo {
   sysset_t saved_entryset;     /* Saved traced system call entry set */
 };
 
-static struct procinfo pi;     /* Inferior's process information */
+/* List of inferior process information */
+static struct procinfo *procinfo_list = NULL;
+
+static struct pollfd *poll_list; /* pollfds used for waiting on /proc */
+
+static int num_poll_list = 0;  /* Number of entries in poll_list */
+
+static int last_resume_pid = -1; /* Last pid used with procfs_resume */
 
 /*  Much of the information used in the /proc interface, particularly for
     printing status information, is kept as tables of structures of the
@@ -360,7 +370,7 @@ static char *
 errnoname PARAMS ((int));
 
 static int
-proc_address_to_fd PARAMS ((CORE_ADDR, int));
+proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
 
 static int
 open_proc_file PARAMS ((int, struct procinfo *, int));
@@ -369,10 +379,10 @@ static void
 close_proc_file PARAMS ((struct procinfo *));
 
 static void
-unconditionally_kill_inferior PARAMS ((void));
+unconditionally_kill_inferior PARAMS ((struct procinfo *));
 
-static void
-proc_init_failed PARAMS ((char *));
+static NORETURN void
+proc_init_failed PARAMS ((struct procinfo *, char *));
 
 static void
 info_proc PARAMS ((char *, int));
@@ -417,7 +427,10 @@ static void
 procfs_create_inferior PARAMS ((char *, char *, char **));
 
 static void
-procfs_notice_signals PARAMS ((void));
+procfs_notice_signals PARAMS ((pid_t pid));
+
+static struct procinfo *
+find_procinfo PARAMS ((pid_t pid, int okfail));
 
 /* External function prototypes that can't be easily included in any
    header file because the args are typedefs in system include files. */
@@ -436,6 +449,117 @@ fill_fpregset PARAMS ((fpregset_t *, int));
 
 /*
 
+LOCAL FUNCTION
+
+       find_procinfo -- convert a process id to a struct procinfo
+
+SYNOPSIS
+
+       static struct procinfo * find_procinfo (pid_t pid, int okfail);
+
+DESCRIPTION
+       
+       Given a process id, look it up in the procinfo chain.  Returns
+       a struct procinfo *.  If can't find pid, then call error(),
+       unless okfail is set, in which case, return NULL;
+ */
+
+static struct procinfo *
+find_procinfo (pid, okfail)
+     pid_t pid;
+     int okfail;
+{
+  struct procinfo *procinfo;
+
+  for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+    if (procinfo->pid == pid)
+      return procinfo;
+
+  if (okfail)
+    return NULL;
+
+  error ("procfs (find_procinfo):  Couldn't locate pid %d", pid);
+}
+
+/*
+
+LOCAL FUNCTION
+
+       add_fd -- Add the fd to the poll/select list
+
+SYNOPSIS
+
+       static void add_fd (struct procinfo *);
+
+DESCRIPTION
+       
+       Add the fd of the supplied procinfo to the list of fds used for
+       poll/select operations.
+ */
+
+static void
+add_fd (pi)
+     struct procinfo *pi;
+{
+  if (num_poll_list <= 0)
+    poll_list = (struct pollfd *) xmalloc (sizeof (struct pollfd));
+  else
+    poll_list = (struct pollfd *) xrealloc (poll_list,
+                                           (num_poll_list + 1)
+                                           * sizeof (struct pollfd));
+  poll_list[num_poll_list].fd = pi->fd;
+  poll_list[num_poll_list].events = POLLPRI;
+
+  num_poll_list++;
+}
+
+static void
+remove_fd (pi)
+     struct procinfo *pi;
+{
+  int i;
+
+  for (i = 0; i < num_poll_list; i++)
+    {
+      if (poll_list[i].fd == pi->fd)
+       {
+         if (i != num_poll_list - 1)
+           memcpy (poll_list, poll_list + i + 1,
+                   (num_poll_list - i - 1) * sizeof (struct pollfd));
+
+         num_poll_list--;
+
+         if (num_poll_list == 0)
+           free (poll_list);
+         else
+           poll_list = (struct pollfd *) xrealloc (poll_list,
+                                                   num_poll_list
+                                                   * sizeof (struct pollfd));
+         return;
+       }
+    }
+}
+
+/*
+
+LOCAL MACRO
+
+       current_procinfo -- convert inferior_pid to a struct procinfo
+
+SYNOPSIS
+
+       static struct procinfo * current_procinfo;
+
+DESCRIPTION
+       
+       Looks up inferior_pid in the procinfo chain.  Always returns a
+       struct procinfo *.  If process can't be found, we error() out.
+ */
+
+#define current_procinfo find_procinfo (inferior_pid, 0)
+
+/*
+
 LOCAL FUNCTION
 
        lookupdesc -- translate a value to a summary desc string
@@ -1011,6 +1135,9 @@ init_syscall_table ()
 #if defined (SYS_seteuid)
   syscall_table[SYS_seteuid] = "seteuid";
 #endif
+#if defined (SYS_sproc)
+  syscall_table[SYS_sproc] = "sproc";
+#endif
 }
 
 /*
@@ -1068,11 +1195,12 @@ NOTES
 static void
 procfs_kill_inferior ()
 {
-  if (inferior_pid != 0)
-    {
-      unconditionally_kill_inferior ();
-      target_mourn_inferior ();
-    }
+  struct procinfo *pi;
+
+  for (pi = procinfo_list; pi; pi = pi->next)
+    unconditionally_kill_inferior (pi);
+
+  target_mourn_inferior ();
 }
 
 /*
@@ -1083,30 +1211,39 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static void unconditionally_kill_inferior (void)
+       static void unconditionally_kill_inferior (struct procinfo *)
 
 DESCRIPTION
 
-       Kill the current inferior.  Should not be called until it
-       is at least tested that there is an inferior.
+       Kill the specified inferior.
 
 NOTE
 
        A possibly useful enhancement would be to first try sending
        the inferior a terminate signal, politely asking it to commit
-       suicide, before we murder it.
+       suicide, before we murder it (we could call that
+       politely_kill_inferior()).
 
 */
 
 static void
-unconditionally_kill_inferior ()
+unconditionally_kill_inferior (pi)
+     struct procinfo *pi;
 {
   int signo;
+  int ppid;
   
+  ppid = pi->prstatus.pr_ppid;
+
   signo = SIGKILL;
-  ioctl (pi.fd, PIOCKILL, &signo);
-  close_proc_file (&pi);
-  wait ((int *) 0);
+  ioctl (pi->fd, PIOCKILL, &signo);
+  close_proc_file (pi);
+
+/* Only wait() for our direct children.  Our grandchildren zombies are killed
+   by the death of their parents.  */
+
+  if (ppid == getpid())
+    wait ((int *) 0);
 }
 
 /*
@@ -1145,16 +1282,19 @@ procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
      struct target_ops *target; /* ignored */
 {
   int nbytes = 0;
+  struct procinfo *pi;
 
-  if (lseek (pi.fd, (off_t) memaddr, 0) == (off_t) memaddr)
+  pi = current_procinfo;
+
+  if (lseek(pi->fd, (off_t) memaddr, 0) == (off_t) memaddr)
     {
       if (dowrite)
        {
-         nbytes = write (pi.fd, myaddr, len);
+         nbytes = write (pi->fd, myaddr, len);
        }
       else
        {
-         nbytes = read (pi.fd, myaddr, len);
+         nbytes = read (pi->fd, myaddr, len);
        }
       if (nbytes < 0)
        {
@@ -1206,12 +1346,16 @@ static void
 procfs_store_registers (regno)
      int regno;
 {
+  struct procinfo *pi;
+
+  pi = current_procinfo;
+
   if (regno != -1)
     {
-      ioctl (pi.fd, PIOCGREG, &pi.gregset);
+      ioctl (pi->fd, PIOCGREG, &pi->gregset);
     }
-  fill_gregset (&pi.gregset, regno);
-  ioctl (pi.fd, PIOCSREG, &pi.gregset);
+  fill_gregset (&pi->gregset, regno);
+  ioctl (pi->fd, PIOCSREG, &pi->gregset);
 
 #if defined (FP0_REGNUM)
 
@@ -1221,10 +1365,10 @@ procfs_store_registers (regno)
 
   if (regno != -1)
     {
-      ioctl (pi.fd, PIOCGFPREG, &pi.fpregset);
+      ioctl (pi->fd, PIOCGFPREG, &pi->fpregset);
     }
-  fill_fpregset (&pi.fpregset, regno);
-  ioctl (pi.fd, PIOCSFPREG, &pi.fpregset);
+  fill_fpregset (&pi->fpregset, regno);
+  ioctl (pi->fd, PIOCSFPREG, &pi->fpregset);
 
 #endif /* FP0_REGNUM */
 
@@ -1234,7 +1378,64 @@ procfs_store_registers (regno)
 
 LOCAL FUNCTION
 
-       procfs_init_inferior - initialize access to a /proc entry
+       create_procinfo - initialize access to a /proc entry
+
+SYNOPSIS
+
+       void create_procinfo (int pid)
+
+DESCRIPTION
+
+       Allocate a procinfo structure, open the /proc file and then sets up
+       the set of signals and faults that are to be traced.
+
+NOTES
+
+       If proc_init_failed ever gets called, control returns to the command
+       processing loop via the standard error handling code.
+
+ */
+
+static void
+create_procinfo (pid)
+     int pid;
+{
+  struct procinfo *pi;
+
+  if (find_procinfo (pid, 1))
+    return;                    /* All done!  It already exists */
+
+  pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+
+  if (!open_proc_file (pid, pi, O_RDWR))
+    proc_init_failed (pi, "can't open process file");
+
+  /* Add new process to process info list */
+
+  pi->next = procinfo_list;
+  procinfo_list = pi;
+
+  add_fd (pi);                 /* Add to list for poll/select */
+
+  memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
+  prfillset (&pi->prrun.pr_trace);
+  procfs_notice_signals (pid);
+  prfillset (&pi->prrun.pr_fault);
+  prdelset (&pi->prrun.pr_fault, FLTPAGE);
+
+  if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
+    proc_init_failed (pi, "PIOCWSTOP failed");
+
+  if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
+    proc_init_failed (pi, "PIOCSFAULT failed");
+}
+
+/*
+
+LOCAL FUNCTION
+
+       procfs_init_inferior - initialize target vector and access to a
+       /proc entry
 
 SYNOPSIS
 
@@ -1259,29 +1460,10 @@ static void
 procfs_init_inferior (pid)
      int pid;
 {
-
   push_target (&procfs_ops);
 
-  if (!open_proc_file (pid, &pi, O_RDWR))
-    {
-      proc_init_failed ("can't open process file");
-    }
-  else
-    {
-      memset ((char *) &pi.prrun, 0, sizeof (pi.prrun));
-      prfillset (&pi.prrun.pr_trace);
-      procfs_notice_signals ();
-      prfillset (&pi.prrun.pr_fault);
-      prdelset (&pi.prrun.pr_fault, FLTPAGE);
-      if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0)
-       {
-         proc_init_failed ("PIOCWSTOP failed");
-       }
-      else if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault) < 0)
-       {
-         proc_init_failed ("PIOCSFAULT failed");
-       }
-    }
+  create_procinfo (pid);
+  add_thread (pid);            /* Setup initial thread */
 }
 
 /*
@@ -1292,7 +1474,7 @@ GLOBAL FUNCTION
 
 SYNOPSIS
 
-       static void procfs_notice_signals (void);
+       static void procfs_notice_signals (pid_t pid);
 
 DESCRIPTION
 
@@ -1310,30 +1492,31 @@ DESCRIPTION
  */
 
 static void
-procfs_notice_signals ()
+procfs_notice_signals (pid)
+     pid_t pid;
 {
   int signo;
+  struct procinfo *pi;
 
-  if (pi.valid)
+  pi = find_procinfo (pid, 0);
+
+  for (signo = 0; signo < NSIG; signo++)
     {
-      for (signo = 0; signo < NSIG; signo++)
+      if (signal_stop_state (signo) == 0 &&
+         signal_print_state (signo) == 0 &&
+         signal_pass_state (signo) == 1)
        {
-         if (signal_stop_state (signo) == 0 &&
-             signal_print_state (signo) == 0 &&
-             signal_pass_state (signo) == 1)
-           {
-             prdelset (&pi.prrun.pr_trace, signo);
-           }
-         else
-           {
-             praddset (&pi.prrun.pr_trace, signo);
-           }
+         prdelset (&pi->prrun.pr_trace, signo);
        }
-      if (ioctl (pi.fd, PIOCSTRACE, &pi.prrun.pr_trace))
+      else
        {
-         print_sys_errmsg ("PIOCSTRACE failed", errno);
+         praddset (&pi->prrun.pr_trace, signo);
        }
     }
+  if (ioctl (pi->fd, PIOCSTRACE, &pi->prrun.pr_trace))
+    {
+      print_sys_errmsg ("PIOCSTRACE failed", errno);
+    }
 }
 
 /*
@@ -1464,15 +1647,18 @@ proc_iterate_over_mappings (func)
   int funcstat = 0;
   struct prmap *prmaps;
   struct prmap *prmap;
+  struct procinfo *pi;
+
+  pi = current_procinfo;
 
-  if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
+  if (ioctl (pi->fd, PIOCNMAP, &nmap) == 0)
     {
       prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
-      if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
+      if (ioctl (pi->fd, PIOCMAP, prmaps) == 0)
        {
          for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
            {
-             fd = proc_address_to_fd ((CORE_ADDR) prmap -> pr_vaddr, 0);
+             fd = proc_address_to_fd (pi, (CORE_ADDR) prmap -> pr_vaddr, 0);
              funcstat = (*func) (fd, (CORE_ADDR) prmap -> pr_vaddr);
              close (fd);
            }
@@ -1511,11 +1697,14 @@ proc_base_address (addr)
   struct prmap *prmaps;
   struct prmap *prmap;
   CORE_ADDR baseaddr = 0;
+  struct procinfo *pi;
 
-  if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
+  pi = current_procinfo;
+
+  if (ioctl (pi->fd, PIOCNMAP, &nmap) == 0)
     {
       prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
-      if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
+      if (ioctl (pi->fd, PIOCMAP, prmaps) == 0)
        {
          for (prmap = prmaps; prmap -> pr_size; ++prmap)
            {
@@ -1541,7 +1730,7 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       int proc_address_to_fd (CORE_ADDR addr, complain)
+       int proc_address_to_fd (struct procinfo *pi, CORE_ADDR addr, complain)
 
 DESCRIPTION
 
@@ -1554,21 +1743,19 @@ DESCRIPTION
 */
 
 static int
-proc_address_to_fd (addr, complain)
+proc_address_to_fd (pi, addr, complain)
+     struct procinfo *pi;
      CORE_ADDR addr;
      int complain;
 {
   int fd = -1;
 
-  if (pi.valid)
+  if ((fd = ioctl (pi->fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
     {
-      if ((fd = ioctl (pi.fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
+      if (complain)
        {
-         if (complain)
-           {
-             print_sys_errmsg (pi.pathname, errno);
-             warning ("can't find mapped file for address 0x%x", addr);
-           }
+         print_sys_errmsg (pi->pathname, errno);
+         warning ("can't find mapped file for address 0x%x", addr);
        }
     }
   return (fd);
@@ -1707,30 +1894,41 @@ do_attach (pid)
      int pid;
 {
   int result;
+  struct procinfo *pi;
+
+  pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
 
-  if (!open_proc_file (pid, &pi, O_RDWR))
+  if (!open_proc_file (pid, pi, O_RDWR))
     {
-      perror_with_name (pi.pathname);
+      free (pi);
+      perror_with_name (pi->pathname);
       /* NOTREACHED */
     }
   
+  /* Add new process to process info list */
+
+  pi->next = procinfo_list;
+  procinfo_list = pi;
+
+  add_fd (pi);                 /* Add to list for poll/select */
+
   /*  Get current status of process and if it is not already stopped,
       then stop it.  Remember whether or not it was stopped when we first
       examined it. */
   
-  if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
+  if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
     {
-      print_sys_errmsg (pi.pathname, errno);
-      close_proc_file (&pi);
+      print_sys_errmsg (pi->pathname, errno);
+      close_proc_file (pi);
       error ("PIOCSTATUS failed");
     }
-  if (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+  if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
     {
-      pi.was_stopped = 1;
+      pi->was_stopped = 1;
     }
   else
     {
-      pi.was_stopped = 0;
+      pi->was_stopped = 0;
       if (1 || query ("Process is currently running, stop it? "))
        {
          /* Make it run again when we close it.  */
@@ -1738,26 +1936,26 @@ do_attach (pid)
          {
              long pr_flags;
              pr_flags = PR_RLC;
-             result = ioctl (pi.fd, PIOCSET, &pr_flags);
+             result = ioctl (pi->fd, PIOCSET, &pr_flags);
          }
 #else
 #if defined (PIOCSRLC) /* Original method */
-         result = ioctl (pi.fd, PIOCSRLC, 0);
+         result = ioctl (pi->fd, PIOCSRLC, 0);
 #endif
 #endif
          if (result < 0)
            {
-             print_sys_errmsg (pi.pathname, errno);
-             close_proc_file (&pi);
+             print_sys_errmsg (pi->pathname, errno);
+             close_proc_file (pi);
              error ("PIOCSRLC or PIOCSET failed");
            }
-         if (ioctl (pi.fd, PIOCSTOP, &pi.prstatus) < 0)
+         if (ioctl (pi->fd, PIOCSTOP, &pi->prstatus) < 0)
            {
-             print_sys_errmsg (pi.pathname, errno);
-             close_proc_file (&pi);
+             print_sys_errmsg (pi->pathname, errno);
+             close_proc_file (pi);
              error ("PIOCSTOP failed");
            }
-         pi.nopass_next_sigstop = 1;
+         pi->nopass_next_sigstop = 1;
        }
       else
        {
@@ -1768,24 +1966,24 @@ do_attach (pid)
   /*  Remember some things about the inferior that we will, or might, change
       so that we can restore them when we detach. */
   
-  ioctl (pi.fd, PIOCGTRACE, &pi.saved_trace);
-  ioctl (pi.fd, PIOCGHOLD, &pi.saved_sighold);
-  ioctl (pi.fd, PIOCGFAULT, &pi.saved_fltset);
-  ioctl (pi.fd, PIOCGENTRY, &pi.saved_entryset);
-  ioctl (pi.fd, PIOCGEXIT, &pi.saved_exitset);
+  ioctl (pi->fd, PIOCGTRACE, &pi->saved_trace);
+  ioctl (pi->fd, PIOCGHOLD, &pi->saved_sighold);
+  ioctl (pi->fd, PIOCGFAULT, &pi->saved_fltset);
+  ioctl (pi->fd, PIOCGENTRY, &pi->saved_entryset);
+  ioctl (pi->fd, PIOCGEXIT, &pi->saved_exitset);
   
   /* Set up trace and fault sets, as gdb expects them. */
   
-  memset (&pi.prrun, 0, sizeof (pi.prrun));
-  prfillset (&pi.prrun.pr_trace);
-  procfs_notice_signals ();
-  prfillset (&pi.prrun.pr_fault);
-  prdelset (&pi.prrun.pr_fault, FLTPAGE);
-  if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault))
+  memset (&pi->prrun, 0, sizeof (pi->prrun));
+  prfillset (&pi->prrun.pr_trace);
+  procfs_notice_signals (pid);
+  prfillset (&pi->prrun.pr_fault);
+  prdelset (&pi->prrun.pr_fault, FLTPAGE);
+  if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault))
     {
       print_sys_errmsg ("PIOCSFAULT failed", errno);
     }
-  if (ioctl (pi.fd, PIOCSTRACE, &pi.prrun.pr_trace))
+  if (ioctl (pi->fd, PIOCSTRACE, &pi->prrun.pr_trace))
     {
       print_sys_errmsg ("PIOCSTRACE failed", errno);
     }
@@ -1827,52 +2025,55 @@ do_detach (signal)
      int signal;
 {
   int result;
+  struct procinfo *pi;
+
+  pi = current_procinfo;
 
   if (signal)
     {
-      set_proc_siginfo (&pi, signal);
+      set_proc_siginfo (pi, signal);
     }
-  if (ioctl (pi.fd, PIOCSEXIT, &pi.saved_exitset) < 0)
+  if (ioctl (pi->fd, PIOCSEXIT, &pi->saved_exitset) < 0)
     {
-      print_sys_errmsg (pi.pathname, errno);
+      print_sys_errmsg (pi->pathname, errno);
       printf ("PIOCSEXIT failed.\n");
     }
-  if (ioctl (pi.fd, PIOCSENTRY, &pi.saved_entryset) < 0)
+  if (ioctl (pi->fd, PIOCSENTRY, &pi->saved_entryset) < 0)
     {
-      print_sys_errmsg (pi.pathname, errno);
+      print_sys_errmsg (pi->pathname, errno);
       printf ("PIOCSENTRY failed.\n");
     }
-  if (ioctl (pi.fd, PIOCSTRACE, &pi.saved_trace) < 0)
+  if (ioctl (pi->fd, PIOCSTRACE, &pi->saved_trace) < 0)
     {
-      print_sys_errmsg (pi.pathname, errno);
+      print_sys_errmsg (pi->pathname, errno);
       printf ("PIOCSTRACE failed.\n");
     }
-  if (ioctl (pi.fd, PIOCSHOLD, &pi.saved_sighold) < 0)
+  if (ioctl (pi->fd, PIOCSHOLD, &pi->saved_sighold) < 0)
     {
-      print_sys_errmsg (pi.pathname, errno);
+      print_sys_errmsg (pi->pathname, errno);
       printf ("PIOSCHOLD failed.\n");
     }
-  if (ioctl (pi.fd, PIOCSFAULT, &pi.saved_fltset) < 0)
+  if (ioctl (pi->fd, PIOCSFAULT, &pi->saved_fltset) < 0)
     {
-      print_sys_errmsg (pi.pathname, errno);
+      print_sys_errmsg (pi->pathname, errno);
       printf ("PIOCSFAULT failed.\n");
     }
-  if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
+  if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
     {
-      print_sys_errmsg (pi.pathname, errno);
+      print_sys_errmsg (pi->pathname, errno);
       printf ("PIOCSTATUS failed.\n");
     }
   else
     {
-      if (signal || (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+      if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
        {
-         if (signal || !pi.was_stopped ||
+         if (signal || !pi->was_stopped ||
              query ("Was stopped when attached, make it runnable again? "))
            {
              /* Clear any fault that might have stopped it.  */
-             if (ioctl (pi.fd, PIOCCFAULT, 0))
+             if (ioctl (pi->fd, PIOCCFAULT, 0))
                {
-                 print_sys_errmsg (pi.pathname, errno);
+                 print_sys_errmsg (pi->pathname, errno);
                  printf ("PIOCCFAULT failed.\n");
                }
 
@@ -1881,22 +2082,22 @@ do_detach (signal)
              {
                  long pr_flags;
                  pr_flags = PR_RLC;
-                 result = ioctl (pi.fd, PIOCSET, &pr_flags);
+                 result = ioctl (pi->fd, PIOCSET, &pr_flags);
              }
 #else
 #if defined (PIOCSRLC) /* Original method */
-             result = ioctl (pi.fd, PIOCSRLC, 0);
+             result = ioctl (pi->fd, PIOCSRLC, 0);
 #endif
 #endif
              if (result)
                {
-                 print_sys_errmsg (pi.pathname, errno);
+                 print_sys_errmsg (pi->pathname, errno);
                  printf ("PIOCSRLC or PIOCSET failed.\n");
                }
            }
        }
     }
-  close_proc_file (&pi);
+  close_proc_file (pi);
   attach_flag = 0;
 }
 
@@ -1911,7 +2112,7 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       int procfs_wait (int *statloc)
+       int procfs_wait (int pid, int *statloc)
 
 DESCRIPTION
 
@@ -1941,7 +2142,8 @@ NOTES
  */
 
 static int
-procfs_wait (statloc)
+procfs_wait (pid, statloc)
+     int pid;
      int *statloc;
 {
   short what;
@@ -1949,24 +2151,73 @@ procfs_wait (statloc)
   int statval = 0;
   int checkerr = 0;
   int rtnval = -1;
-  
-  if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
-    {
-      checkerr++;
-    }
-  else if (!(pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+  struct procinfo *pi;
+
+  if (pid != -1)               /* Non-specific process? */
+    pi = NULL;
+  else
+    for (pi = procinfo_list; pi; pi = pi->next)
+      if (pi->had_event)
+       break;
+
+wait_again:
+
+  if (!pi)
     {
+      int num_fds;
+      int i;
+
       if (attach_flag)
        set_sigint_trap();      /* Causes SIGINT to be passed on to the
                                   attached process. */
 
-      if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0)
+      num_fds = poll (poll_list, num_poll_list, -1);
+  
+      if (attach_flag)
+       clear_sigint_trap();
+
+      if (num_fds <= 0)
        {
-         checkerr++;
+         print_sys_errmsg (pi->pathname, errno);
+         error ("poll failed, returned %d\n", num_fds);
        }
 
-      if (attach_flag)
-       clear_sigint_trap();
+      for (i = 0; i < num_poll_list && num_fds > 0; i++)
+       {
+         if ((poll_list[i].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL)) == 0)
+           continue;
+         for (pi = procinfo_list; pi; pi = pi->next)
+           {
+             if (poll_list[i].fd == pi->fd)
+               {
+                 if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
+                   checkerr++;
+                 /*                perror_with_name (pi->pathname);*/
+                 num_fds--;
+                 pi->had_event = 1;
+                 break;
+               }
+           }
+         if (!pi)
+           error ("procfs_wait: Couldn't find procinfo for fd %d\n",
+                  poll_list[i].fd);
+       }
+    }
+
+  if (pid != -1)
+    for (pi = procinfo_list; pi; pi = pi->next)
+      if (pi->pid == pid && pi->had_event)
+       break;
+
+  if (!pi && !checkerr)
+    goto wait_again;
+
+  if (!checkerr && !(pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+    {
+      if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
+       {
+         checkerr++;
+       }
     }    
   if (checkerr)
     {
@@ -1975,55 +2226,86 @@ procfs_wait (statloc)
          rtnval = wait (&statval);
          if (rtnval != inferior_pid)
            {
-             print_sys_errmsg (pi.pathname, errno);
+             print_sys_errmsg (pi->pathname, errno);
              error ("PIOCWSTOP, wait failed, returned %d", rtnval);
              /* NOTREACHED */
            }
        }
       else
        {
-         print_sys_errmsg (pi.pathname, errno);
+         print_sys_errmsg (pi->pathname, errno);
          error ("PIOCSTATUS or PIOCWSTOP failed.");
          /* NOTREACHED */
        }
     }
-  else if (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+  else if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
     {
-      rtnval = pi.prstatus.pr_pid;
-      why = pi.prstatus.pr_why;
-      what = pi.prstatus.pr_what;
-      if (why == PR_SIGNALLED)
+      rtnval = pi->prstatus.pr_pid;
+      why = pi->prstatus.pr_why;
+      what = pi->prstatus.pr_what;
+
+      switch (why)
        {
+       case PR_SIGNALLED:
          statval = (what << 8) | 0177;
-       }
-      else if ((why == PR_SYSEXIT)
-              &&
-              (
+         break;
+       case PR_SYSEXIT:
+         switch (what)
+           {
 #ifdef SYS_exec
-               what == SYS_exec
-#else
-               0 == 0
+           case SYS_exec:
 #endif
 #ifdef SYS_execve
-               || what == SYS_execve
+           case SYS_execve:
 #endif
 #ifdef SYS_execv
-               || what == SYS_execv
+           case SYS_execv:
 #endif
-               ))
-       {
-         statval = (SIGTRAP << 8) | 0177;
-       }
-      else if (why == PR_REQUESTED)
-       {
+             statval = (SIGTRAP << 8) | 0177;
+             break;
+#ifdef SYS_sproc
+           case SYS_sproc:
+/* We've just detected the completion of an sproc system call.  Now we need to
+   setup a procinfo struct for this thread, and notify the thread system of the
+   new arrival.  */
+
+/* If sproc failed, then nothing interesting happened.  Continue the process and
+   go back to sleep. */
+
+             if (pi->prstatus.pr_errno != 0)
+               {
+                 pi->prrun.pr_flags &= PRSTEP;
+                 pi->prrun.pr_flags |= PRCFAULT;
+
+                 if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+                   perror_with_name (pi->pathname);
+
+                 goto wait_again;
+               }
+
+/* At this point, the new thread is stopped at it's first instruction, and
+   the parent is stopped at the exit from sproc.  */
+
+/* Notify the caller of the arrival of a new thread. */
+             create_procinfo (pi->prstatus.pr_rval1);
+
+             rtnval = pi->prstatus.pr_rval1;
+             statval = (SIGTRAP << 8) | 0177;
+
+             break;
+#endif /* SYS_sproc */
+
+           default:
+             error ("PIOCSTATUS (PR_SYSEXIT):  Unknown system call %d", what); 
+           }
+         break;
+       case PR_REQUESTED:
          statval = (SIGSTOP << 8) | 0177;
-       }
-      else if (why == PR_JOBCONTROL)
-       {
+         break;
+       case PR_JOBCONTROL:
          statval = (what << 8) | 0177;
-       }
-      else if (why == PR_FAULTED)
-       {
+         break;
+       case PR_FAULTED:
          switch (what)
            {
            case FLTPRIV:
@@ -2046,23 +2328,32 @@ procfs_wait (statloc)
              break;
            case FLTPAGE:               /* Recoverable page fault */
            default:
-             rtnval = -1;
              error ("PIOCWSTOP, unknown why %d, what %d", why, what);
-             /* NOTREACHED */
            }
-       }
-      else
-       {
-         rtnval = -1;
+         break;
+       default:
          error ("PIOCWSTOP, unknown why %d, what %d", why, what);
-         /* NOTREACHED */
        }
+/* Stop all the other threads when any of them stops.  */
+
+      {
+       struct procinfo *procinfo;
+
+       for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+         {
+           if (!procinfo->had_event)
+             if (ioctl (procinfo->fd, PIOCSTOP, &procinfo->prstatus) < 0)
+               {
+                 print_sys_errmsg (procinfo->pathname, errno);
+                 error ("PIOCSTOP failed");
+               }
+         }
+      }
     }
   else
     {
       error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x", 
-            pi.prstatus.pr_flags);
-         /* NOTREACHED */
+            pi->prstatus.pr_flags);
     }
 
   if (statloc)
@@ -2077,6 +2368,7 @@ procfs_wait (statloc)
       return rtnval;
     }
 
+  pi->had_event = 0;           /* Indicate that we've seen this one */
   return (rtnval);
 }
 
@@ -2126,27 +2418,24 @@ set_proc_siginfo (pip, signo)
   struct siginfo newsiginfo;
   struct siginfo *sip;
 
-  if (pip -> valid)
+  if (signo == pip -> prstatus.pr_info.si_signo)
     {
-      if (signo == pip -> prstatus.pr_info.si_signo)
-       {
-         sip = &pip -> prstatus.pr_info;
-       }
-      else
-       {
-         memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
-         sip = &newsiginfo;
-         sip -> si_signo = signo;
-         sip -> si_code = 0;
-         sip -> si_errno = 0;
-         sip -> si_pid = getpid ();
-         sip -> si_uid = getuid ();
-       }
-      if (ioctl (pip -> fd, PIOCSSIG, sip) < 0)
-       {
-         print_sys_errmsg (pip -> pathname, errno);
-         warning ("PIOCSSIG failed");
-       }
+      sip = &pip -> prstatus.pr_info;
+    }
+  else
+    {
+      memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+      sip = &newsiginfo;
+      sip -> si_signo = signo;
+      sip -> si_code = 0;
+      sip -> si_errno = 0;
+      sip -> si_pid = getpid ();
+      sip -> si_uid = getuid ();
+    }
+  if (ioctl (pip -> fd, PIOCSSIG, sip) < 0)
+    {
+      print_sys_errmsg (pip -> pathname, errno);
+      warning ("PIOCSSIG failed");
     }
 }
 
@@ -2161,9 +2450,12 @@ procfs_resume (pid, step, signo)
      int signo;
 {
   int signal_to_pass;
+  struct procinfo *pi, *procinfo;
+
+  pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
 
   errno = 0;
-  pi.prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
+  pi->prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
 
 #if 0
   /* It should not be necessary.  If the user explicitly changes the value,
@@ -2180,12 +2472,12 @@ procfs_resume (pid, step, signo)
    random garbage.  We have to rely on the fact that PC and nPC have been
    written previously via PIOCSREG during a register flush. */
 
-  pi.prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
-  pi.prrun.pr_flags != PRSVADDR;
+  pi->prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+  pi->prrun.pr_flags != PRSVADDR;
 #endif
 #endif
 
-  if (signo == SIGSTOP && pi.nopass_next_sigstop)
+  if (signo == SIGSTOP && pi->nopass_next_sigstop)
     /* When attaching to a child process, if we forced it to stop with
        a PIOCSTOP, then we will have set the nopass_next_sigstop flag.
        Upon resuming the first time after such a stop, we explicitly
@@ -2198,8 +2490,8 @@ procfs_resume (pid, step, signo)
        an inferior to continue running at the same time as gdb.  (FIXME?)  */
     signal_to_pass = 0;
   else if (signo == SIGTSTP
-          && pi.prstatus.pr_cursig == SIGTSTP
-          && pi.prstatus.pr_action.sa_handler == SIG_DFL)
+          && pi->prstatus.pr_cursig == SIGTSTP
+          && pi->prstatus.pr_action.sa_handler == SIG_DFL)
 
     /* We are about to pass the inferior a SIGTSTP whose action is
        SIG_DFL.  The SIG_DFL action for a SIGTSTP is to stop
@@ -2221,22 +2513,48 @@ procfs_resume (pid, step, signo)
 
   if (signal_to_pass)
     {
-      set_proc_siginfo (&pi, signal_to_pass);
+      set_proc_siginfo (pi, signal_to_pass);
     }
   else
     {
-      pi.prrun.pr_flags |= PRCSIG;
+      pi->prrun.pr_flags |= PRCSIG;
     }
-  pi.nopass_next_sigstop = 0;
+  pi->nopass_next_sigstop = 0;
   if (step)
     {
-      pi.prrun.pr_flags |= PRSTEP;
+      pi->prrun.pr_flags |= PRSTEP;
     }
-  if (ioctl (pi.fd, PIOCRUN, &pi.prrun) != 0)
+  if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
     {
-      perror_with_name (pi.pathname);
+      perror_with_name (pi->pathname);
       /* NOTREACHED */
     }
+
+  pi->had_event = 0;
+
+  /* Continue all the other threads that haven't had an event of
+     interest.  */
+
+  if (pid == -1)
+    for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+      {
+       if (pi != procinfo && !procinfo->had_event)
+         {
+           procinfo->prrun.pr_flags &= PRSTEP;
+           procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
+           ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus);
+           if (ioctl (procinfo->fd, PIOCRUN, &procinfo->prrun) < 0)
+             {
+               if (ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus) < 0)
+                 {
+                   fprintf(stderr, "PIOCSTATUS failed, errno=%d\n", errno);
+                 }
+               print_sys_errmsg (procinfo->pathname, errno);
+               error ("PIOCRUN failed");
+             }
+           ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus);
+         }
+      }
 }
 
 /*
@@ -2261,14 +2579,18 @@ static void
 procfs_fetch_registers (regno)
      int regno;
 {
-  if (ioctl (pi.fd, PIOCGREG, &pi.gregset) != -1)
+  struct procinfo *pi;
+
+  pi = current_procinfo;
+
+  if (ioctl (pi->fd, PIOCGREG, &pi->gregset) != -1)
     {
-      supply_gregset (&pi.gregset);
+      supply_gregset (&pi->gregset);
     }
 #if defined (FP0_REGNUM)
-  if (ioctl (pi.fd, PIOCGFPREG, &pi.fpregset) != -1)
+  if (ioctl (pi->fd, PIOCGFPREG, &pi->fpregset) != -1)
     {
-      supply_fpregset (&pi.fpregset);
+      supply_fpregset (&pi->fpregset);
     }
 #endif
 }
@@ -2277,11 +2599,12 @@ procfs_fetch_registers (regno)
 
 LOCAL FUNCTION
 
-       proc_init_failed - called whenever /proc access initialization fails
+       proc_init_failed - called whenever /proc access initialization
+fails
 
 SYNOPSIS
 
-       static void proc_init_failed (char *why)
+       static void proc_init_failed (struct procinfo *pi, char *why)
 
 DESCRIPTION
 
@@ -2292,12 +2615,13 @@ DESCRIPTION
  */
 
 static void
-proc_init_failed (why)
+proc_init_failed (pi, why)
+     struct procinfo *pi;
      char *why;
 {
-  print_sys_errmsg (pi.pathname, errno);
-  kill (pi.pid, SIGKILL);
-  close_proc_file (&pi);
+  print_sys_errmsg (pi->pathname, errno);
+  kill (pi->pid, SIGKILL);
+  close_proc_file (pi);
   error (why);
   /* NOTREACHED */
 }
@@ -2325,18 +2649,24 @@ static void
 close_proc_file (pip)
      struct procinfo *pip;
 {
-  pip -> pid = 0;
-  if (pip -> valid)
-    {
-      close (pip -> fd);
-    }
-  pip -> fd = -1;
-  if (pip -> pathname)
-    {
-      free (pip -> pathname);
-      pip -> pathname = NULL;
-    }
-  pip -> valid = 0;
+  struct procinfo *procinfo;
+
+  remove_fd (pip);             /* Remove fd from poll/select list */
+
+  close (pip -> fd);
+
+  free (pip -> pathname);
+
+  /* Unlink pip from the procinfo chain.  Note pip might not be on the list. */
+
+  if (procinfo_list == pip)
+    procinfo_list = pip->next;
+  else
+    for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+      if (procinfo->next == pip)
+       procinfo->next = pip->next;
+
+  free (pip);
 }
 
 /*
@@ -2369,22 +2699,16 @@ open_proc_file (pid, pip, mode)
      struct procinfo *pip;
      int mode;
 {
-  pip -> valid = 0;            /* FIXME, what is this? ?!  */
-  if (pip -> valid)
-    {
-      close (pip -> fd);
-    }
-  if (pip -> pathname == NULL)
-    {
-      pip -> pathname = xmalloc (32);
-    }
+  pip -> next = NULL;
+  pip -> had_event = 0;
+  pip -> pathname = xmalloc (32);
+  pip -> pid = pid;
+
   sprintf (pip -> pathname, PROC_NAME_FMT, pid);
-  if ((pip -> fd = open (pip -> pathname, mode)) >= 0)
-    {
-      pip -> valid = 1;
-      pip -> pid = pid;
-    }
-  return (pip -> valid);
+  if ((pip -> fd = open (pip -> pathname, mode)) < 0)
+    return 0;
+
+  return 1;
 }
 
 static char *
@@ -2874,7 +3198,6 @@ info_proc (args, from_tty)
      int from_tty;
 {
   int pid;
-  struct procinfo pii;
   struct procinfo *pip;
   struct cleanup *old_chain;
   char **argv;
@@ -2892,9 +3215,10 @@ info_proc (args, from_tty)
 
   old_chain = make_cleanup (null_cleanup, 0);
 
-  /* Default to using the current inferior if no pid specified */
+  /* Default to using the current inferior if no pid specified.  Note
+     that inferior_pid may be 0, hence we set okerr.  */
 
-  pip = &pi;
+  pip = find_procinfo (inferior_pid, 1);
 
   if (args != NULL)
     {
@@ -2952,11 +3276,12 @@ info_proc (args, from_tty)
              summary = 0;
              times = 1;
            }
-         else if ((pii.pid = atoi (*argv)) > 0)
+         else if ((pid = atoi (*argv)) > 0)
            {
-             pid = pii.pid;
-             pip = &pii;
-             memset (&pii, 0, sizeof (pii));
+             pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+             memset (pip, 0, sizeof (*pip));
+
+             pip->pid = pid;
              if (!open_proc_file (pid, pip, O_RDONLY))
                {
                  perror_with_name (pip -> pathname);
@@ -2975,7 +3300,7 @@ info_proc (args, from_tty)
   /* If we don't have a valid open process at this point, then we have no
      inferior or didn't specify a specific pid. */
 
-  if (!pip -> valid)
+  if (!pip)
     {
       error ("\
 No process.  Start debugging a program or specify an explicit process ID.");
@@ -3026,6 +3351,64 @@ No process.  Start debugging a program or specify an explicit process ID.");
   do_cleanups (old_chain);
 }
 
+/*
+
+LOCAL FUNCTION
+
+       procfs_set_sproc_trap -- arrange for exec'd child stop on sproc
+
+SYNOPSIS
+
+       void procfs_set_sproc_trap (void)
+
+DESCRIPTION
+
+       This function sets up a trap on sproc system call exits so that we can
+       detect the arrival of a new thread.  We are called with the child
+       stopped prior to it's first instruction.
+
+       Also note that we turn on the inherit-on-fork flag in the child process
+       so that any grand-children start with all tracing flags set.
+ */
+
+static void
+procfs_set_sproc_trap (pi)
+     struct procinfo *pi;
+{
+  sysset_t exitset;
+  
+  if (ioctl (pi->fd, PIOCGEXIT, &exitset) < 0)
+    {
+      print_sys_errmsg (pi->pathname, errno);
+      error ("PIOCGEXIT failed");
+    }
+
+#ifdef SYS_sproc
+  praddset (&exitset, SYS_sproc);
+#endif
+
+  if (ioctl (pi->fd, PIOCSEXIT, &exitset) < 0)
+    {
+      print_sys_errmsg (pi->pathname, errno);
+      error ("PIOCSEXIT failed");
+    }
+
+  /* Turn on inherit-on-fork flag so that all grand-children of gdb start with
+     tracing flags set. */
+
+#ifdef PIOCSET                 /* New method */
+  {
+      long pr_flags;
+      pr_flags = PR_FORK;
+      ioctl (pi->fd, PIOCSET, &pr_flags);
+  }
+#else
+#ifdef PIOCSFORK               /* Original method */
+  ioctl (pi->fd, PIOCSFORK, NULL);
+#endif
+#endif
+}
+
 /* Fork an inferior process, and start debugging it with /proc.  */
 
 static void
@@ -3038,6 +3421,11 @@ procfs_create_inferior (exec_file, allargs, env)
                 proc_set_exec_trap, procfs_init_inferior);
   /* We are at the first instruction we care about.  */
   /* Pedal to the metal... */
+
+  /* Setup traps on exit from sproc() */
+
+  procfs_set_sproc_trap(current_procinfo);
+
   proceed ((CORE_ADDR) -1, 0, 0);
 }
 
index 641895e6820f4e0d91a4be8eac2b7b63cd219dfc..e1f36036bbd4559f53e19e2ada4f633f062c946a 100644 (file)
@@ -273,7 +273,8 @@ static char *wait_strings[] = {
 };
 
 int
-bug_wait (status)
+bug_wait (pid, status)
+     int pid;
      WAITTYPE *status;
 {
   int old_timeout = sr_get_timeout();
index 212b0fce03f4c810d2db4fb20aa7c338f8c4efe7..32ca1c930b05d160273779e74905409fd0cb1a3b 100644 (file)
@@ -664,7 +664,8 @@ hms_resume (pid, step, sig)
    storing status in STATUS just as `wait' would.  */
 
 int
-hms_wait (status)
+hms_wait (pid, status)
+     int pid;
      WAITTYPE *status;
 {
   /* Strings to look for.  '?' means match any single character.
index f04f0e8b456adafdee456394d47800e22085c66c..6f60284edc421e52947cfb5f73c2549c1c55ee4c 100644 (file)
@@ -75,7 +75,7 @@ static void
 mips_resume PARAMS ((int pid, int step, int siggnal));
 
 static int
-mips_wait PARAMS ((WAITTYPE *status));
+mips_wait PARAMS ((int pid, WAITTYPE *status));
 
 static int
 mips_map_regno PARAMS ((int regno));
index db323d5e3ba8931937993aea095a33a7c32f23d9..56a90a77e737af8eb459ae640c02afadc42160b6 100644 (file)
@@ -461,7 +461,8 @@ monitor_resume (pid, step, sig)
  */
 
 static int
-monitor_wait (status)
+monitor_wait (pid, status)
+     int pid;
      WAITTYPE *status;
 {
   int old_timeout = timeout;
index 35365c1242d4d454bab0bdb2663c32dae79e1800..d6551fcfcaefa3aec875cfb7169778b5e3b9b09a 100644 (file)
@@ -299,7 +299,8 @@ You may need to reset the 80960 and/or reload your program.\n");
  */
 
 static int
-nindy_wait( status )
+nindy_wait( pid, status )
+    int pid;
     WAITTYPE *status;
 {
   fd_set fds;
index 83600e896a43eb83da1a74271c85da6f1235b7cc..dbecaa00f36cff2642cbb2f5dde57d1aaaca28f5 100644 (file)
@@ -345,7 +345,8 @@ gdbsim_resume (pid, step, siggnal)
    just as `wait' would.  */
 
 static int
-gdbsim_wait (status)
+gdbsim_wait (pid, status)
+     int pid;
      WAITTYPE *status;
 {
   if (sr_get_debug ())
index 27023265fb61dabd0bca45294ac3ce719f7dbc92..bfcbea101c55be9a46bda6431aac186b0e4b22a0 100644 (file)
@@ -406,7 +406,8 @@ udi_resume (pid, step, sig)
    storing status in STATUS just as `wait' would.  */
 
 static int
-udi_wait (status)
+udi_wait (pid, status)
+     int pid;
      WAITTYPE *status;
 {
   UDIInt32     MaxTime;
index cb67787463bf4e90900fcd8f6dc8ea7dbe5577c2..3aea4d1bfd42dee4ead04a1a0bc1c02c3bbea9ad 100644 (file)
@@ -583,6 +583,9 @@ vx_resume (pid, step, siggnal)
   Rptrace ptrace_in;
   Ptrace_return ptrace_out;
 
+  if (pid == -1)
+    pid = inferior_pid;
+
   if (siggnal != 0 && siggnal != stop_signal)
     error ("Cannot send signals to VxWorks processes");
 
@@ -855,7 +858,8 @@ sleep_ms (ms)
  */
 
 static int
-vx_wait (status)
+vx_wait (pid, status)
+     int pid;
      int *status;
 {
   register int pid;
index f93a2310bed1be5fffa7aff2bb9ed093f02387fe..6c1b286a593ff7917f643bb176ea3c4151713173 100644 (file)
@@ -210,7 +210,8 @@ sim_detach (args, from_tty)
    storing status in STATUS just as `wait' would.  */
 
 int
-sim_wait (status)
+sim_wait (pid, status)
+     int pid;
      WAITTYPE *status;
 {
   *status = sim_stop_signal ();
index fdc13bc9113289ab269c77084e616412f9daddaa..f14b41fc041c6c873d5dcefe263ec5ab072a6049 100644 (file)
@@ -51,6 +51,8 @@ static void prune_threads PARAMS ((void));
 
 static void thread_switch PARAMS ((int pid));
 
+static struct thread_info * find_thread_id PARAMS ((int num));
+
 void
 init_thread_list ()
 {
@@ -96,6 +98,32 @@ find_thread_id (num)
   return NULL;
 }
 
+int
+valid_thread_id (num)
+    int num;
+{
+  struct thread_info *tp;
+
+  for (tp = thread_list; tp; tp = tp->next)
+    if (tp->num == num)
+      return 1;
+
+  return 0;
+}
+
+int
+pid_to_thread_id (pid)
+    int pid;
+{
+  struct thread_info *tp;
+
+  for (tp = thread_list; tp; tp = tp->next)
+    if (tp->pid == pid)
+      return tp->num;
+
+  return 0;
+}
+
 int
 in_thread_list (pid)
     int pid;
index 36b003557b54f193acd646333ae8d53704b730e6..2ec94fc5c5e4ec1de9707aecd141811b25a77d95 100644 (file)
@@ -25,8 +25,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 extern void init_thread_list PARAMS ((void));
 
-extern void add_thread PARAMS ((int));
+extern void add_thread PARAMS ((int pid));
 
-extern int in_thread_list PARAMS ((int));
+extern int in_thread_list PARAMS ((int pid));
+
+extern int pid_to_thread_id PARAMS ((int pid));
+
+extern int valid_thread_id PARAMS ((int thread));
 
 #endif /* THREAD_H */