From 3ab2abae9ac2dc0ab96fc2d1a678b463485b90a0 Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Wed, 13 Jan 1999 23:53:30 +0000 Subject: [PATCH] Wed Jan 13 14:59:02 1999 Michael Snyder * 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 | 1 + gdb/infrun.c | 50 +++++++++++++++++++++++++++++++++++++++++++---- gdb/m3-nat.c | 1 + gdb/procfs.c | 5 +++-- gdb/remote.c | 1 + gdb/sol-thread.c | 2 ++ gdb/target.c | 2 ++ gdb/target.h | 17 ++++++++++++++++ 8 files changed, 73 insertions(+), 6 deletions(-) diff --git a/gdb/hpux-thread.c b/gdb/hpux-thread.c index 82d8ea43d50..15494ec22bc 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 73efc2d0042..0633c0383e5 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 01594e1e4cf..e1f2851719c 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 b5b331d01e6..1e9e04091bd 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 e6a2252d93b..b4f7ce6460d 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 ccaa6dcc6c9..6585d73007f 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 40e458e6bbe..1e729faaa93 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 ccf047f7f9d..c9d6b6e810d 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 -- 2.30.2