aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/hpux-thread.c1
-rw-r--r--gdb/infrun.c50
-rw-r--r--gdb/m3-nat.c1
-rw-r--r--gdb/procfs.c5
-rw-r--r--gdb/remote.c1
-rw-r--r--gdb/sol-thread.c2
-rw-r--r--gdb/target.c2
-rw-r--r--gdb/target.h17
8 files changed, 73 insertions, 6 deletions
diff --git a/gdb/hpux-thread.c b/gdb/hpux-thread.c
index 82d8ea4..15494ec 100644
--- a/gdb/hpux-thread.c
+++ b/gdb/hpux-thread.c
@@ -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 */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 73efc2d..0633c03 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -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);
}
diff --git a/gdb/m3-nat.c b/gdb/m3-nat.c
index 01594e1..e1f2851 100644
--- a/gdb/m3-nat.c
+++ b/gdb/m3-nat.c
@@ -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 */
diff --git a/gdb/procfs.c b/gdb/procfs.c
index b5b331d..1e9e040 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -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 */
diff --git a/gdb/remote.c b/gdb/remote.c
index e6a2252d..b4f7ce6 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -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;
}
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index ccaa6dc..6585d73 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -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 */
diff --git a/gdb/target.c b/gdb/target.c
index 40e458e..1e729fa 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -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);
diff --git a/gdb/target.h b/gdb/target.h
index ccf047f..c9d6b6e 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -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