Wed Jan 13 14:59:02 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
* 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.
This commit is contained in:
parent
ea377ea4c0
commit
3ab2abae9a
8 changed files with 73 additions and 6 deletions
|
@ -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 */
|
||||
|
|
50
gdb/infrun.c
50
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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
17
gdb/target.h
17
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
|
||||
|
|
Loading…
Add table
Reference in a new issue