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 */
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
}
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);
}
{
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\
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);
}
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 */
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 */
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 */
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;
}
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 */
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 */
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 */
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);
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? */
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
#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