Wed Jan 13 14:59:02 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
authorMichael Snyder <msnyder@vmware.com>
Wed, 13 Jan 1999 23:53:30 +0000 (23:53 +0000)
committerMichael Snyder <msnyder@vmware.com>
Wed, 13 Jan 1999 23:53:30 +0000 (23:53 +0000)
        * infrun.c (set/show scheduler-locking) New command.  Set a
          mode bit that will control how GDB attempts to control thread
          scheduling for step, continue, etc.  (resume): make use of
          the schedule-locking mode.
        * target.h (struct target_ops): new field to_has_thread_control.
        * sol-thread.c: initialize target_ops to_has_thread_control.
        * procfs.c: ditto.
        * target.c: ditto.
        * m3-nat.c: ditto.
        * remote.c: ditto.
        * hpux-thread.c: ditto.

gdb/hpux-thread.c
gdb/infrun.c
gdb/m3-nat.c
gdb/procfs.c
gdb/remote.c
gdb/sol-thread.c
gdb/target.c
gdb/target.h

index 82d8ea43d502b1a19ec841a20eecd679326580a9..15494ec22bc043dd7ba4b41122b64e2908ecc06f 100644 (file)
@@ -650,6 +650,7 @@ struct target_ops hpux_thread_ops = {
   1,                           /* to_has_stack */
   1,                           /* to_has_registers */
   1,                           /* to_has_execution */
+  tc_none,                     /* to_has_thread_control */
   0,                           /* sections */
   0,                           /* sections_end */
   OPS_MAGIC                    /* to_magic */
index 73efc2d004210605986370a974221b2051cf3ec9..0633c0383e5fd669c768b43ac0b38c4dc94084a8 100644 (file)
@@ -598,6 +598,28 @@ resume_cleanups (arg)
   normal_stop ();
 }
 
+static char schedlock_off[]    = "off";
+static char schedlock_on[]     = "on";
+static char schedlock_step[]   = "step";
+static char *scheduler_mode    = schedlock_off;
+static char *scheduler_enums[] = {schedlock_off, schedlock_on, schedlock_step};
+
+static void
+set_schedlock_func (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  if (c->type == set_cmd)
+    if (!target_can_lock_scheduler)
+      {
+       scheduler_mode = schedlock_off;
+       error ("Target '%s' cannot support this command.", 
+              target_shortname);
+      }
+}
+
+
 /* Resume the inferior, but allow a QUIT.  This is useful if the user
    wants to interrupt some lengthy single-stepping operation
    (for child processes, the SIGINT goes to the inferior, and so
@@ -714,11 +736,17 @@ resume (step, sig)
         }
       else
 #endif /* HPUXHPPA */
+       {
+         /* Vanilla resume. */
 
-        /* Vanilla resume. */
-        target_resume (-1, step, sig);
+         if ((scheduler_mode == schedlock_on) ||
+             (scheduler_mode == schedlock_step && step != 0))
+           target_resume (inferior_pid, step, sig);
+         else
+           target_resume (-1, step, sig);
+       }
     }
-    
+  
   discard_cleanups (old_cleanups);
 }
 
@@ -3555,7 +3583,7 @@ _initialize_infrun ()
 {
   register int i;
   register int numsigs;
-  struct cmd_list_element *  c;
+  struct cmd_list_element * c;
 
   add_info ("signals", signals_info,
            "What debugger does when program gets various signals.\n\
@@ -3688,4 +3716,18 @@ By default, the debugger will follow the parent process.",
   add_show_from_set (c, &showlist);
 
   set_follow_fork_mode_command ("parent", 0, NULL);
+
+  c = add_set_enum_cmd ("scheduler-locking", class_run, 
+                       scheduler_enums,        /* array of string names */
+                       (char *) &scheduler_mode,       /* current mode  */
+                       "Set mode for locking scheduler during execution.\n\
+off  == no locking (threads may preempt at any time)\n\
+on   == full locking (no thread except the current thread may run)\n\
+step == scheduler locked during every single-step operation.\n\
+       In this mode, no other thread may run during a step command.\n\
+       Other threads may run while stepping over a function call ('next').",
+                       &setlist);
+
+  c->function.sfunc = set_schedlock_func;      /* traps on target vector */
+  add_show_from_set (c, &showlist);
 }
index 01594e1e4cf3b89d8230db1efdb3eeea5d667dbb..e1f2851719c13323df0c50179b5ace98c64eb17e 100644 (file)
@@ -4595,6 +4595,7 @@ struct target_ops m3_ops = {
   1,                           /* to_has_stack */
   1,                           /* to_has_registers */
   1,                           /* to_has_execution */
+  tc_none,                     /* to_has_thread_control */
   0,                           /* sections */
   0,                           /* sections_end */
   OPS_MAGIC                    /* to_magic */
index b5b331d01e63bb450b64dfbc74e81eac451846b4..1e9e04091bd797f7504e0921d4f301feb7eb4bba 100644 (file)
@@ -5760,9 +5760,9 @@ struct target_ops procfs_ops = {
   0,                           /* to_close */
   procfs_attach,               /* to_attach */
   NULL,                         /* to_post_attach */
-  procfs_attach,                       /* to_require_attach */
+  procfs_attach,               /* to_require_attach */
   procfs_detach,               /* to_detach */
-  procfs_detach,                       /* to_require_detach */
+  procfs_detach,               /* to_require_detach */
   procfs_resume,               /* to_resume */
   procfs_wait,                 /* to_wait */
   NULL,                         /* to_post_wait */
@@ -5816,6 +5816,7 @@ struct target_ops procfs_ops = {
   1,                           /* to_has_stack */
   1,                           /* to_has_registers */
   1,                           /* to_has_execution */
+  tc_none,                     /* to_has_thread_control */
   0,                           /* sections */
   0,                           /* sections_end */
   OPS_MAGIC                    /* to_magic */
index e6a2252d93b0263b05bbdbc5d4bfc6b4444becac..b4f7ce6460da7c9f52fd5880d6d6d97fb0937d72 100644 (file)
@@ -3185,6 +3185,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_ops.to_has_stack = 1; 
   remote_ops.to_has_registers = 1;     
   remote_ops.to_has_execution = 1;     
+  remote_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */
   remote_ops.to_magic = OPS_MAGIC;     
 }
 
index ccaa6dcc6c90af5868441489e4977197bf701c28..6585d73007f0a011082d9394f8886a0ae3e0a427 100644 (file)
@@ -1569,6 +1569,7 @@ struct target_ops sol_thread_ops = {
   1,                           /* to_has_stack */
   1,                           /* to_has_registers */
   1,                           /* to_has_execution */
+  tc_none,                     /* to_has_thread_control */
   0,                           /* sections */
   0,                           /* sections_end */
   OPS_MAGIC                    /* to_magic */
@@ -1638,6 +1639,7 @@ struct target_ops sol_core_ops = {
   1,                           /* to_has_stack */
   1,                           /* to_has_registers */
   0,                           /* to_has_execution */
+  tc_none,                     /* to_has_thread_control */
   0,                           /* sections */
   0,                           /* sections_end */
   OPS_MAGIC                    /* to_magic */
index 40e458e6bbe66de59bf8648b8193faaccdf2aa9a..1e729faaa9378211fb6a948b448d3cc1b2b5e107 100644 (file)
@@ -248,6 +248,7 @@ struct target_ops dummy_target = {
   0,                           /* to_has_stack */
   0,                           /* to_has_registers */
   0,                           /* to_has_execution */
+  tc_none,                     /* to_has_thread_control */
   0,                           /* to_sections */
   0,                           /* to_sections_end */
   OPS_MAGIC,                   /* to_magic */
@@ -593,6 +594,7 @@ update_current_target ()
       INHERIT (to_has_stack, t);
       INHERIT (to_has_registers, t);
       INHERIT (to_has_execution, t);
+      INHERIT (to_has_thread_control, t);
       INHERIT (to_sections, t);
       INHERIT (to_sections_end, t);
       INHERIT (to_magic, t);
index ccf047f7f9dc8a66df99796534f7f65e7671ef56..c9d6b6e810da28d22f451809054e2de7d46905d7 100644 (file)
@@ -51,6 +51,12 @@ enum strata {
        process_stratum         /* Executing processes */
 };
 
+enum thread_control_capabilities {
+       tc_none = 0,            /* Default: can't control thread execution. */
+       tc_schedlock = 1,       /* Can lock the thread scheduler. */
+       tc_switch = 2,          /* Can switch the running thread on demand. */
+};
+
 /* Stuff for target_wait.  */
 
 /* Generally, what has the program done?  */
@@ -361,6 +367,7 @@ struct target_ops
   int          to_has_stack;
   int          to_has_registers;
   int          to_has_execution;
+  int          to_has_thread_control;  /* control thread execution */
   struct section_table
               *to_sections;
   struct section_table
@@ -934,6 +941,16 @@ print_section_info PARAMS ((struct target_ops *, bfd *));
 #define        target_has_execution    \
        (current_target.to_has_execution)
 
+/* Can the target support the debugger control of thread execution?
+   a) Can it lock the thread scheduler?
+   b) Can it switch the currently running thread?  */
+
+#define target_can_lock_scheduler \
+       (current_target.to_has_thread_control & tc_schedlock)
+
+#define target_can_switch_threads \
+       (current_target.to_has_thread_control & tc_switch)
+
 extern void target_link PARAMS ((char *, CORE_ADDR *));
 
 /* Converts a process id to a string.  Usually, the string just contains