Mon Apr 28 21:25:32 1997 Michael Snyder <msnyder@cleaver.cygnus.com>

* Makefile.in: Add rule for gnu-nat.o and i386gnu-nat.o (Gnu Hurd)
        * config/i386/i386gnu.mh: remove rules for [i386]gnu-nat.o, now
        in Makefile.in (as for other targets); add NATDEPFILE corelow.o to
        satisfy symbol dependancy in solib.c (core_ops).
        * target.[ch] conditionalize Mach-specific signals so that they
        won't show up in non-Mach gdb's!
        * thread.c: add function thread_id_to_pid; change name of static
        function "thread_switch" to "switch_to_thread", to avoid conflict
        with Mach global symbol; move thread_cmd_list to global scope
        so targets can add their own thread commands.
        * infrun.c: sig_print_info: allow for long signal names.
        * gnu-nat.[ch]: tidying up comments.
        * gnu-nat.c: move several functions to static scope, just for tidy;
        remove calls to prune_threads and renumber_threads;
        gnu_wait must not return -1 when inferior exits;
        attach_to_child will modify inferior_pid in a way that allows
        fork_inferior to remain unchanged;
        remove extra arg from startup_inferior;
        move mach-specific thread commands here from thread.c.
This commit is contained in:
Michael Snyder
1997-04-29 04:27:26 +00:00
parent 75dc6b820f
commit c889a1eb87
3 changed files with 181 additions and 96 deletions

View File

@ -85,43 +85,45 @@ int gnu_debug_flag = 0;
/* Forward decls */ /* Forward decls */
extern struct target_ops gnu_ops; extern struct target_ops gnu_ops;
extern char *strerror();
struct inf *make_inf ();
void inf_clear_wait (struct inf *inf);
void inf_cleanup (struct inf *inf);
void inf_startup (struct inf *inf, int pid, task_t task);
int inf_update_suspends (struct inf *inf);
void inf_set_task (struct inf *inf, task_t port);
void inf_validate_procs (struct inf *inf);
void inf_steal_exc_ports (struct inf *inf);
void inf_restore_exc_ports (struct inf *inf);
int inf_update_procs (struct inf *inf); int inf_update_procs (struct inf *inf);
struct proc *inf_tid_to_proc (struct inf *inf, int tid); static struct inf *make_inf ();
inline void inf_set_threads_resume_sc (struct inf *inf, struct proc static void inf_clear_wait (struct inf *inf);
*run_thread, int run_others); static void inf_cleanup (struct inf *inf);
inline int inf_set_threads_resume_sc_for_signal_thread (struct inf *inf); static void inf_startup (struct inf *inf, int pid, task_t task);
inline void inf_suspend (struct inf *inf); static int inf_update_suspends (struct inf *inf);
inline void inf_resume (struct inf *inf); static void inf_set_task (struct inf *inf, task_t port);
void inf_set_step_thread (struct inf *inf, struct proc *proc); static void inf_validate_procs (struct inf *inf);
void inf_detach (struct inf *inf); static void inf_steal_exc_ports (struct inf *inf);
void inf_attach (struct inf *inf, int pid); static void inf_restore_exc_ports (struct inf *inf);
void inf_signal (struct inf *inf, enum target_signal sig); static struct proc *inf_tid_to_proc (struct inf *inf, int tid);
static inline void inf_set_threads_resume_sc (struct inf *inf,
struct proc *run_thread,
int run_others);
static inline int inf_set_threads_resume_sc_for_signal_thread (struct inf *inf);
static inline void inf_suspend (struct inf *inf);
static inline void inf_resume (struct inf *inf);
static void inf_set_step_thread (struct inf *inf, struct proc *proc);
static void inf_detach (struct inf *inf);
static void inf_attach (struct inf *inf, int pid);
static void inf_signal (struct inf *inf, enum target_signal sig);
#define inf_debug(_inf, msg, args...) \ #define inf_debug(_inf, msg, args...) \
do { struct inf *__inf = (_inf); \ do { struct inf *__inf = (_inf); \
debug ("{inf %d %p}: " msg, __inf->pid, __inf , ##args); } while (0) debug ("{inf %d %p}: " msg, __inf->pid, __inf , ##args); } while (0)
struct proc *make_proc (struct inf *inf, mach_port_t port, int tid);
struct proc *_proc_free (struct proc *proc);
int proc_update_sc (struct proc *proc);
void proc_abort (struct proc *proc, int force); void proc_abort (struct proc *proc, int force);
thread_state_t proc_get_state (struct proc *proc, int force); thread_state_t proc_get_state (struct proc *proc, int force);
error_t proc_get_exception_port (struct proc *proc, mach_port_t *port); static struct proc *make_proc (struct inf *inf, mach_port_t port, int tid);
error_t proc_set_exception_port (struct proc *proc, mach_port_t port); static struct proc *_proc_free (struct proc *proc);
static int proc_update_sc (struct proc *proc);
static error_t proc_get_exception_port (struct proc *proc, mach_port_t *port);
static error_t proc_set_exception_port (struct proc *proc, mach_port_t port);
static mach_port_t _proc_get_exc_port (struct proc *proc); static mach_port_t _proc_get_exc_port (struct proc *proc);
void proc_steal_exc_port (struct proc *proc, mach_port_t exc_port); static void proc_steal_exc_port (struct proc *proc, mach_port_t exc_port);
void proc_restore_exc_port (struct proc *proc); static void proc_restore_exc_port (struct proc *proc);
int proc_trace (struct proc *proc, int set); static int proc_trace (struct proc *proc, int set);
char *proc_string (struct proc *proc); char *proc_string (struct proc *proc);
/* Evaluate RPC_EXPR in a scope with the variables MSGPORT and REFPORT bound /* Evaluate RPC_EXPR in a scope with the variables MSGPORT and REFPORT bound
@ -238,6 +240,7 @@ struct inf
int want_exceptions; int want_exceptions;
}; };
int __proc_pid (struct proc *proc) int __proc_pid (struct proc *proc)
{ {
return proc->inf->pid; return proc->inf->pid;
@ -245,7 +248,7 @@ int __proc_pid (struct proc *proc)
/* Update PROC's real suspend count to match it's desired one. Returns true /* Update PROC's real suspend count to match it's desired one. Returns true
if we think PROC is now in a runnable state. */ if we think PROC is now in a runnable state. */
int static int
proc_update_sc (struct proc *proc) proc_update_sc (struct proc *proc)
{ {
int running; int running;
@ -374,7 +377,8 @@ proc_get_state (struct proc *proc, int will_modify)
return 0; return 0;
} }
error_t /* Set PORT to PROC's exception port. */
static error_t
proc_get_exception_port (struct proc *proc, mach_port_t *port) proc_get_exception_port (struct proc *proc, mach_port_t *port)
{ {
if (proc_is_task (proc)) if (proc_is_task (proc))
@ -383,7 +387,8 @@ proc_get_exception_port (struct proc *proc, mach_port_t *port)
return thread_get_exception_port (proc->port, port); return thread_get_exception_port (proc->port, port);
} }
error_t /* Set PROC's exception port to PORT. */
static error_t
proc_set_exception_port (struct proc *proc, mach_port_t port) proc_set_exception_port (struct proc *proc, mach_port_t port)
{ {
proc_debug (proc, "setting exception port: %d", port); proc_debug (proc, "setting exception port: %d", port);
@ -416,7 +421,7 @@ _proc_get_exc_port (struct proc *proc)
/* Replace PROC's exception port with EXC_PORT, unless it's already been /* Replace PROC's exception port with EXC_PORT, unless it's already been
done. Stash away any existing exception port so we can restore it later. */ done. Stash away any existing exception port so we can restore it later. */
void static void
proc_steal_exc_port (struct proc *proc, mach_port_t exc_port) proc_steal_exc_port (struct proc *proc, mach_port_t exc_port)
{ {
mach_port_t cur_exc_port = _proc_get_exc_port (proc); mach_port_t cur_exc_port = _proc_get_exc_port (proc);
@ -456,10 +461,10 @@ proc_steal_exc_port (struct proc *proc, mach_port_t exc_port)
} }
} }
/* If we previously replaced PROC's exception port, put back what we found /* If we previously replaced PROC's exception port, put back what we
there at the time, unless *our* exception port has since be overwritten, found there at the time, unless *our* exception port has since been
in which case who knows what's going on. */ overwritten, in which case who knows what's going on. */
void static void
proc_restore_exc_port (struct proc *proc) proc_restore_exc_port (struct proc *proc)
{ {
mach_port_t cur_exc_port = _proc_get_exc_port (proc); mach_port_t cur_exc_port = _proc_get_exc_port (proc);
@ -486,9 +491,9 @@ proc_restore_exc_port (struct proc *proc)
} }
} }
/* Turns hardware tracing in PROC on or off when SET is true or fals, /* Turns hardware tracing in PROC on or off when SET is true or false,
respectively. Returns true on success. */ respectively. Returns true on success. */
int static int
proc_trace (struct proc *proc, int set) proc_trace (struct proc *proc, int set)
{ {
thread_state_t state = proc_get_state (proc, 1); thread_state_t state = proc_get_state (proc, 1);
@ -576,9 +581,9 @@ make_proc (struct inf *inf, mach_port_t port, int tid)
return proc; return proc;
} }
/* Frees PROC and any resources it uses, and returns the value of PROC's next /* Frees PROC and any resources it uses, and returns the value of PROC's
field. */ next field. */
struct proc * static struct proc *
_proc_free (struct proc *proc) _proc_free (struct proc *proc)
{ {
struct inf *inf = proc->inf; struct inf *inf = proc->inf;
@ -646,7 +651,8 @@ struct inf *make_inf ()
return inf; return inf;
} }
void /* clear INF's target wait status. */
static void
inf_clear_wait (struct inf *inf) inf_clear_wait (struct inf *inf)
{ {
inf_debug (inf, "clearing wait"); inf_debug (inf, "clearing wait");
@ -665,7 +671,7 @@ inf_clear_wait (struct inf *inf)
} }
} }
void static void
inf_cleanup (struct inf *inf) inf_cleanup (struct inf *inf)
{ {
inf_debug (inf, "cleanup"); inf_debug (inf, "cleanup");
@ -687,7 +693,7 @@ inf_cleanup (struct inf *inf)
} }
} }
void static void
inf_startup (struct inf *inf, int pid, task_t task) inf_startup (struct inf *inf, int pid, task_t task)
{ {
error_t err; error_t err;
@ -719,7 +725,8 @@ inf_startup (struct inf *inf, int pid, task_t task)
} }
} }
void /* close current process, if any, and attach INF to process PORT */
static void
inf_set_task (struct inf *inf, mach_port_t port) inf_set_task (struct inf *inf, mach_port_t port)
{ {
struct proc *task = inf->task; struct proc *task = inf->task;
@ -794,7 +801,7 @@ inf_validate_task_sc (struct inf *inf)
/* Turns tracing for INF on or off, depending on ON, unless it already is. /* Turns tracing for INF on or off, depending on ON, unless it already is.
If INF is running, the resume_sc count of INF's threads will be modified, If INF is running, the resume_sc count of INF's threads will be modified,
and the signal thread will briefly be run to change the trace state. */ and the signal thread will briefly be run to change the trace state. */
void static void
inf_set_traced (struct inf *inf, int on) inf_set_traced (struct inf *inf, int on)
{ {
if (on != inf->traced) if (on != inf->traced)
@ -825,7 +832,7 @@ inf_set_traced (struct inf *inf, int on)
/* Makes all the real suspend count deltas of all the procs in INF match the /* Makes all the real suspend count deltas of all the procs in INF match the
desired values. Careful to always do thread/task suspend counts in the desired values. Careful to always do thread/task suspend counts in the
safe order. Returns true if at least one thread is thought to be running.*/ safe order. Returns true if at least one thread is thought to be running.*/
int static int
inf_update_suspends (struct inf *inf) inf_update_suspends (struct inf *inf)
{ {
struct proc *task = inf->task; struct proc *task = inf->task;
@ -879,6 +886,8 @@ struct proc *
inf_tid_to_thread (struct inf *inf, int tid) inf_tid_to_thread (struct inf *inf, int tid)
{ {
struct proc *thread = inf->threads; struct proc *thread = inf->threads;
if (tid == inf->pid) /* main thread */
return thread;
while (thread) while (thread)
if (thread->tid == tid) if (thread->tid == tid)
return thread; return thread;
@ -888,7 +897,7 @@ inf_tid_to_thread (struct inf *inf, int tid)
} }
/* Converts a thread port to a struct proc. */ /* Converts a thread port to a struct proc. */
struct proc * static struct proc *
inf_port_to_thread (struct inf *inf, mach_port_t port) inf_port_to_thread (struct inf *inf, mach_port_t port)
{ {
struct proc *thread = inf->threads; struct proc *thread = inf->threads;
@ -901,7 +910,7 @@ inf_port_to_thread (struct inf *inf, mach_port_t port)
} }
/* Make INF's list of threads be consistent with reality of TASK. */ /* Make INF's list of threads be consistent with reality of TASK. */
void static void
inf_validate_procs (struct inf *inf) inf_validate_procs (struct inf *inf)
{ {
int i; int i;
@ -979,11 +988,23 @@ inf_validate_procs (struct inf *inf)
else else
/* THREADS[I] is a thread we don't know about yet! */ /* THREADS[I] is a thread we don't know about yet! */
{ {
#if 0
thread = make_proc (inf, threads[i], next_thread_id++); thread = make_proc (inf, threads[i], next_thread_id++);
#else
thread = make_proc (inf, threads[i], threads[i]);
#endif
(last ? last->next : inf->threads) = thread; (last ? last->next : inf->threads) = thread;
last = thread; last = thread;
proc_debug (thread, "new thread: %d", threads[i]); proc_debug (thread, "new thread: %d", threads[i]);
#if 1 /* try leaving this out, see what happens */
add_thread (thread->tid); /* Tell GDB's generic thread code. */ add_thread (thread->tid); /* Tell GDB's generic thread code. */
#if 0 /* seems to cause kernel exceptions??? */
target_terminal_ours_for_output (); /* allow debugger I/O */
printf_filtered ("[gnu-nat: New %s]\n",
target_pid_to_str (thread->tid));
target_terminal_inferior (); /* give it back */
#endif
#endif
} }
vm_deallocate(mach_task_self(), vm_deallocate(mach_task_self(),
@ -1005,7 +1026,7 @@ inf_update_procs (struct inf *inf)
/* Sets the resume_sc of each thread in inf. That of RUN_THREAD is set to 0, /* Sets the resume_sc of each thread in inf. That of RUN_THREAD is set to 0,
and others are set to their run_sc if RUN_OTHERS is true, and otherwise and others are set to their run_sc if RUN_OTHERS is true, and otherwise
their pause_sc. */ their pause_sc. */
inline void static inline void
inf_set_threads_resume_sc (struct inf *inf, inf_set_threads_resume_sc (struct inf *inf,
struct proc *run_thread, int run_others) struct proc *run_thread, int run_others)
{ {
@ -1022,7 +1043,7 @@ inf_set_threads_resume_sc (struct inf *inf,
/* Cause INF to continue execution immediately; individual threads may still /* Cause INF to continue execution immediately; individual threads may still
be suspended (but their suspend counts will be updated). */ be suspended (but their suspend counts will be updated). */
inline void static inline void
inf_resume (struct inf *inf) inf_resume (struct inf *inf)
{ {
struct proc *thread; struct proc *thread;
@ -1047,7 +1068,7 @@ inf_resume (struct inf *inf)
/* Cause INF to stop execution immediately; individual threads may still /* Cause INF to stop execution immediately; individual threads may still
be running. */ be running. */
inline void static inline void
inf_suspend (struct inf *inf) inf_suspend (struct inf *inf)
{ {
struct proc *thread; struct proc *thread;
@ -1063,10 +1084,10 @@ inf_suspend (struct inf *inf)
inf_update_suspends (inf); inf_update_suspends (inf);
} }
/* INF has one thread PROC that is in single-stepping mode. This functions /* INF has one thread PROC that is in single-stepping mode. This function
changes it to be PROC, changing any old step_thread to be a normal one. A changes it to be PROC, changing any old step_thread to be a normal one. A
PROC of 0 clears an any existing value. */ PROC of 0 clears any existing value. */
void static void
inf_set_step_thread (struct inf *inf, struct proc *thread) inf_set_step_thread (struct inf *inf, struct proc *thread)
{ {
assert (!thread || proc_is_thread (thread)); assert (!thread || proc_is_thread (thread));
@ -1091,7 +1112,7 @@ inf_set_step_thread (struct inf *inf, struct proc *thread)
/* Set up the thread resume_sc's so that only the signal thread is running /* Set up the thread resume_sc's so that only the signal thread is running
(plus whatever other thread are set to always run). Returns true if we (plus whatever other thread are set to always run). Returns true if we
did so, or false if we can't find a signal thread. */ did so, or false if we can't find a signal thread. */
inline int static inline int
inf_set_threads_resume_sc_for_signal_thread (struct inf *inf) inf_set_threads_resume_sc_for_signal_thread (struct inf *inf)
{ {
if (inf->signal_thread) if (inf->signal_thread)
@ -1112,7 +1133,7 @@ inf_update_signal_thread (struct inf *inf)
} }
/* Detachs from INF's inferior task, letting it run once again... */ /* Detachs from INF's inferior task, letting it run once again... */
void static void
inf_detach (struct inf *inf) inf_detach (struct inf *inf)
{ {
struct proc *task = inf->task; struct proc *task = inf->task;
@ -1147,7 +1168,7 @@ inf_detach (struct inf *inf)
/* Attaches INF to the process with process id PID, returning it in a suspended /* Attaches INF to the process with process id PID, returning it in a suspended
state suitable for debugging. */ state suitable for debugging. */
void static void
inf_attach (struct inf *inf, int pid) inf_attach (struct inf *inf, int pid)
{ {
error_t err; error_t err;
@ -1196,7 +1217,7 @@ void inf_restore_exc_ports (struct inf *inf)
/* Deliver signal SIG to INF. If INF is stopped, delivering a signal, even /* Deliver signal SIG to INF. If INF is stopped, delivering a signal, even
signal 0, will continue it. INF is assumed to be in a paused state, and signal 0, will continue it. INF is assumed to be in a paused state, and
the resume_sc's of INF's threads may be affected. */ the resume_sc's of INF's threads may be affected. */
void static void
inf_signal (struct inf *inf, enum target_signal sig) inf_signal (struct inf *inf, enum target_signal sig)
{ {
error_t err = 0; error_t err = 0;
@ -1237,7 +1258,7 @@ inf_signal (struct inf *inf, enum target_signal sig)
else else
/* A Unix signal. */ /* A Unix signal. */
if (inf->stopped) if (inf->stopped)
/* The process is stopped an expecting a signal. Just send off a /* The process is stopped and expecting a signal. Just send off a
request and let it get handled when we resume everything. */ request and let it get handled when we resume everything. */
{ {
inf_debug (inf, "sending %s to stopped process", NAME); inf_debug (inf, "sending %s to stopped process", NAME);
@ -1404,12 +1425,14 @@ gnu_wait (int tid, struct target_waitstatus *status)
/* Ah hah! A SIGTRAP from the inferior while starting up probably /* Ah hah! A SIGTRAP from the inferior while starting up probably
means we've succesfully completed an exec! */ means we've succesfully completed an exec! */
{ {
#if 0 /* do we need this? */
if (--inf->pending_execs == 0) if (--inf->pending_execs == 0)
/* We're done! */ /* We're done! */
{ {
prune_threads (1); /* Get rid of the old shell threads */ prune_threads (1); /* Get rid of the old shell threads */
renumber_threads (0); /* Give our threads reasonable names. */ renumber_threads (0); /* Give our threads reasonable names. */
} }
#endif
inf_debug (inf, "pending exec completed, pending_execs => %d", inf_debug (inf, "pending exec completed, pending_execs => %d",
inf->pending_execs); inf->pending_execs);
} }
@ -1438,7 +1461,7 @@ gnu_wait (int tid, struct target_waitstatus *status)
if (inf_update_procs (inf) && inf->threads) if (inf_update_procs (inf) && inf->threads)
tid = inf->threads->tid; /* The first available thread. */ tid = inf->threads->tid; /* The first available thread. */
else else
tid = -1; tid = inferior_pid; /* let wait_for_inferior handle exit case */
if (thread && tid >= 0 && status->kind != TARGET_WAITKIND_SPURIOUS if (thread && tid >= 0 && status->kind != TARGET_WAITKIND_SPURIOUS
&& inf->pause_sc == 0 && thread->pause_sc == 0) && inf->pause_sc == 0 && thread->pause_sc == 0)
@ -1546,7 +1569,7 @@ S_exception_raise_request (mach_port_t port, mach_port_t reply_port,
/* Fill in INF's wait field after a task has died without giving us more /* Fill in INF's wait field after a task has died without giving us more
detailed information. */ detailed information. */
void static void
inf_task_died_status (struct inf *inf) inf_task_died_status (struct inf *inf)
{ {
warning ("Pid %d died with unknown exit status, using SIGKILL.", inf->pid); warning ("Pid %d died with unknown exit status, using SIGKILL.", inf->pid);
@ -1849,15 +1872,15 @@ gnu_mourn_inferior ()
/* Fork an inferior process, and start debugging it. */ /* Fork an inferior process, and start debugging it. */
/* Set INFERIOR_PID to the first thread available in the child, if any. */ /* Set INFERIOR_PID to the first thread available in the child, if any. */
static void static int
pick_first_thread () inf_pick_first_thread ()
{ {
if (current_inferior->task && current_inferior->threads) if (current_inferior->task && current_inferior->threads)
/* The first thread. */ /* The first thread. */
inferior_pid = current_inferior->threads->tid; return current_inferior->threads->tid;
else else
/* What may be the next thread. */ /* What may be the next thread. */
inferior_pid = next_thread_id; return next_thread_id;
} }
static struct inf * static struct inf *
@ -1889,7 +1912,6 @@ gnu_create_inferior (exec_file, allargs, env)
inf_debug (inf, "attaching to child: %d", pid); inf_debug (inf, "attaching to child: %d", pid);
inf_attach (inf, pid); inf_attach (inf, pid);
pick_first_thread ();
attach_flag = 0; attach_flag = 0;
push_target (&gnu_ops); push_target (&gnu_ops);
@ -1900,10 +1922,11 @@ gnu_create_inferior (exec_file, allargs, env)
/* Now let the child run again, knowing that it will stop immediately /* Now let the child run again, knowing that it will stop immediately
because of the ptrace. */ because of the ptrace. */
inf_resume (inf); inf_resume (inf);
inferior_pid = inf_pick_first_thread ();
startup_inferior (pid, inf->pending_execs); startup_inferior (inf->pending_execs);
return pid; return inferior_pid;
} }
inf_debug (inf, "creating inferior"); inf_debug (inf, "creating inferior");
@ -1971,7 +1994,7 @@ gnu_attach (args, from_tty)
inf_attach (inf, pid); inf_attach (inf, pid);
inf_update_procs (inf); inf_update_procs (inf);
pick_first_thread (); inferior_pid = inf_pick_first_thread ();
attach_flag = 1; attach_flag = 1;
push_target (&gnu_ops); push_target (&gnu_ops);
@ -1983,7 +2006,11 @@ gnu_attach (args, from_tty)
time the user does a continue. */ time the user does a continue. */
inf_validate_stopped (inf); inf_validate_stopped (inf);
#if 0 /* Do we need this? Actually I can see where it
might be helpful here, but it's just cosmetic.
Let's come back to it later. XXX Fix me. */
renumber_threads (0); /* Give our threads reasonable names. */ renumber_threads (0); /* Give our threads reasonable names. */
#endif
} }
/* Take a program previously attached to and detaches it. /* Take a program previously attached to and detaches it.
@ -2111,8 +2138,8 @@ struct vm_region_list {
struct obstack region_obstack; struct obstack region_obstack;
/* /*
* Write inferior task's LEN bytes from ADDR and copy it to MYADDR * Write gdb's LEN bytes from MYADDR and copy it to ADDR
* in gdb's address space. * in inferior task's address space.
*/ */
int int
gnu_write_inferior (task, addr, myaddr, length) gnu_write_inferior (task, addr, myaddr, length)
@ -2354,6 +2381,7 @@ struct target_ops gnu_ops = {
OPS_MAGIC /* to_magic */ OPS_MAGIC /* to_magic */
}; };
/* Return printable description of proc. */
char *proc_string (struct proc *proc) char *proc_string (struct proc *proc)
{ {
static char tid_str[80]; static char tid_str[80];
@ -2362,7 +2390,12 @@ char *proc_string (struct proc *proc)
else else
sprintf (tid_str, "thread %d.%d", sprintf (tid_str, "thread %d.%d",
proc->inf->pid, proc->inf->pid,
pid_to_thread_id (proc->tid)); #if 0
pid_to_thread_id (proc->tid)
#else
proc->tid
#endif
);
return tid_str; return tid_str;
} }
@ -2386,9 +2419,41 @@ gnu_target_pid_to_str (int tid)
struct cmd_list_element *set_task_cmd_list = 0; struct cmd_list_element *set_task_cmd_list = 0;
struct cmd_list_element *show_task_cmd_list = 0; struct cmd_list_element *show_task_cmd_list = 0;
/* User thread commands. */
extern struct cmd_list_element *set_thread_default_cmd_list; /* Commands with a prefix of `set/show thread'. */
extern struct cmd_list_element *show_thread_default_cmd_list; extern struct cmd_list_element *thread_cmd_list;
struct cmd_list_element *set_thread_cmd_list = NULL;
struct cmd_list_element *show_thread_cmd_list = NULL;
/* Commands with a prefix of `set/show thread default'. */
struct cmd_list_element *set_thread_default_cmd_list = NULL;
struct cmd_list_element *show_thread_default_cmd_list = NULL;
static void
set_thread_cmd (char *args, int from_tty)
{
printf_unfiltered ("\"set thread\" must be followed by the name of a thread
property, or \"default\".\n");
}
static void
show_thread_cmd (char *args, int from_tty)
{
printf_unfiltered ("\"show thread\" must be followed by the name of a thread property, or \"default\".\n");
}
static void
set_thread_default_cmd (char *args, int from_tty)
{
printf_unfiltered ("\"set thread default\" must be followed by the name of a thread property.\n");
}
static void
show_thread_default_cmd (char *args, int from_tty)
{
printf_unfiltered ("\"show thread default\" must be followed by the name of a thread property.\n");
}
static int static int
parse_int_arg (char *args, char *cmd_prefix) parse_int_arg (char *args, char *cmd_prefix)
@ -2905,11 +2970,6 @@ them).",
add_info_alias ("psets", "port-sets", 1); add_info_alias ("psets", "port-sets", 1);
} }
/* User thread commands. */
extern struct cmd_list_element *set_thread_cmd_list;
extern struct cmd_list_element *show_thread_cmd_list;
extern struct cmd_list_element *thread_cmd_list;
static void static void
set_thread_pause_cmd (char *args, int from_tty) set_thread_pause_cmd (char *args, int from_tty)
@ -2977,12 +3037,7 @@ set_thread_exc_port_cmd (char *args, int from_tty)
steal_exc_port (thread, parse_and_eval_address (args)); steal_exc_port (thread, parse_and_eval_address (args));
} }
static void #if 0
set_thread_cmd (char *args, int from_tty)
{
printf_unfiltered ("\"set thread\" must be followed by the name of a thread property.\n");
}
static void static void
show_thread_cmd (char *args, int from_tty) show_thread_cmd (char *args, int from_tty)
{ {
@ -2993,6 +3048,7 @@ show_thread_cmd (char *args, int from_tty)
if (thread->detach_sc != 0) if (thread->detach_sc != 0)
show_thread_detach_sc_cmd (0, from_tty); show_thread_detach_sc_cmd (0, from_tty);
} }
#endif
static void static void
thread_takeover_sc_cmd (char *args, int from_tty) thread_takeover_sc_cmd (char *args, int from_tty)
@ -3014,6 +3070,21 @@ thread_takeover_sc_cmd (char *args, int from_tty)
add_thread_commands () add_thread_commands ()
{ {
add_prefix_cmd ("thread", no_class, set_thread_cmd,
"Command prefix for setting thread properties.",
&set_thread_cmd_list, "set thread ", 0, &setlist);
add_prefix_cmd ("default", no_class, show_thread_cmd,
"Command prefix for setting default thread properties.",
&set_thread_default_cmd_list, "set thread default ", 0,
&set_thread_cmd_list);
add_prefix_cmd ("thread", no_class, set_thread_default_cmd,
"Command prefix for showing thread properties.",
&show_thread_cmd_list, "show thread ", 0, &showlist);
add_prefix_cmd ("default", no_class, show_thread_default_cmd,
"Command prefix for showing default thread properties.",
&show_thread_default_cmd_list, "show thread default ", 0,
&show_thread_cmd_list);
add_cmd ("pause", class_run, set_thread_pause_cmd, add_cmd ("pause", class_run, set_thread_pause_cmd,
"Set whether the current thread is suspended while gdb has control.\n" "Set whether the current thread is suspended while gdb has control.\n"
"A value of \"on\" takes effect immediately, otherwise nothing\n" "A value of \"on\" takes effect immediately, otherwise nothing\n"

View File

@ -46,8 +46,9 @@ struct proc
int cur_sc; /* Implemented suspend count. */ int cur_sc; /* Implemented suspend count. */
int run_sc; /* Default sc when the program is running. */ int run_sc; /* Default sc when the program is running. */
int pause_sc; /* Default sc when gdb has control. */ int pause_sc; /* Default sc when gdb has control. */
int resume_sc; /* Sc resulting form the last resume. */ int resume_sc; /* Sc resulting from the last resume. */
int detach_sc; /* SC to leave around when detaching from program. */ int detach_sc; /* SC to leave around when detaching
from program. */
thread_state_data_t state; /* Registers, &c. */ thread_state_data_t state; /* Registers, &c. */
int state_valid : 1; /* True if STATE is up to date. */ int state_valid : 1; /* True if STATE is up to date. */

View File

@ -65,7 +65,7 @@ static void
prune_threads PARAMS ((void)); prune_threads PARAMS ((void));
static void static void
thread_switch PARAMS ((int pid)); switch_to_thread PARAMS ((int pid));
static struct thread_info * static struct thread_info *
find_thread_id PARAMS ((int num)); find_thread_id PARAMS ((int num));
@ -164,6 +164,17 @@ pid_to_thread_id (pid)
return 0; return 0;
} }
int
thread_id_to_pid (num)
int num;
{
struct thread_info *thread = find_thread_id (num);
if (thread)
return thread->pid;
else
return -1;
}
int int
in_thread_list (pid) in_thread_list (pid)
int pid; int pid;
@ -309,18 +320,18 @@ info_threads_command (arg, from_tty)
printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid)); printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
thread_switch (tp->pid); switch_to_thread (tp->pid);
print_stack_frame (selected_frame, -1, 0); print_stack_frame (selected_frame, -1, 0);
} }
thread_switch (current_pid); switch_to_thread (current_pid);
prune_threads (); prune_threads ();
} }
/* Switch from one thread to another. */ /* Switch from one thread to another. */
static void static void
thread_switch (pid) switch_to_thread (pid)
int pid; int pid;
{ {
if (pid == inferior_pid) if (pid == inferior_pid)
@ -338,7 +349,7 @@ restore_current_thread (pid)
int pid; int pid;
{ {
if (pid != inferior_pid) if (pid != inferior_pid)
thread_switch (pid); switch_to_thread (pid);
} }
/* Apply a GDB command to a list of threads. List syntax is a whitespace /* Apply a GDB command to a list of threads. List syntax is a whitespace
@ -365,7 +376,7 @@ thread_apply_all_command (cmd, from_tty)
for (tp = thread_list; tp; tp = tp->next) for (tp = thread_list; tp; tp = tp->next)
{ {
thread_switch (tp->pid); switch_to_thread (tp->pid);
printf_filtered ("\nThread %d (%s):\n", tp->num, printf_filtered ("\nThread %d (%s):\n", tp->num,
target_pid_to_str (inferior_pid)); target_pid_to_str (inferior_pid));
execute_command (cmd, from_tty); execute_command (cmd, from_tty);
@ -428,7 +439,7 @@ thread_apply_command (tidlist, from_tty)
continue; continue;
} }
thread_switch (tp->pid); switch_to_thread (tp->pid);
printf_filtered ("\nThread %d (%s):\n", tp->num, printf_filtered ("\nThread %d (%s):\n", tp->num,
target_pid_to_str (inferior_pid)); target_pid_to_str (inferior_pid));
execute_command (cmd, from_tty); execute_command (cmd, from_tty);
@ -459,16 +470,18 @@ see the IDs of currently known threads.");
error ("Thread ID %d not known. Use the \"info threads\" command to\n\ error ("Thread ID %d not known. Use the \"info threads\" command to\n\
see the IDs of currently known threads.", num); see the IDs of currently known threads.", num);
thread_switch (tp->pid); switch_to_thread (tp->pid);
printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid)); printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));
print_stack_frame (selected_frame, selected_frame_level, 1); print_stack_frame (selected_frame, selected_frame_level, 1);
} }
/* Commands with a prefix of `thread'. */
struct cmd_list_element *thread_cmd_list = NULL;
void void
_initialize_thread () _initialize_thread ()
{ {
static struct cmd_list_element *thread_cmd_list = NULL;
static struct cmd_list_element *thread_apply_list = NULL; static struct cmd_list_element *thread_apply_list = NULL;
extern struct cmd_list_element *cmdlist; extern struct cmd_list_element *cmdlist;