Thu May 1 11:44:46 1997 Michael Snyder <msnyder@cleaver.cygnus.com>

* Finalize merge from Hurd folk.
	    Mon Oct 30 16:41:04 1995  Miles Bader  <miles@gnu.ai.mit.edu>
	    * thread.c (thread_apply_command, thread_apply_all_command,
	    thread_command): Make sure TP is alive.
	    (thread_alive): New function.
	    Tue Nov 14 14:31:03 1995  Miles Bader  <miles@gnu.ai.mit.edu>
	    * infrun.c (sig_print_info): Deal better with long signal names.
	    Wed Nov 22 15:23:35 1995  Miles Bader  <miles@gnu.ai.mit.edu>
	    * thread.c (thread_id_to_pid): New function.
	    Fri Dec  1 13:25:25 1995  Miles Bader  <miles@gnu.ai.mit.edu>
	    * gnu-nat.c: (set_thread_cmd_list, show_thread_cmd_list,
	    set_thread_default_cmd_list, show_thread_default_cmd_list):
	    New variables.  (set_thread_cmd, show_thread_cmd,
	    set_thread_default_cmd, show_thread_default_cmd): New functions.
	    Fri Apr 18 15:20:16 1997  Miles Bader  <miles@gnu.ai.mit.edu>
	    * gnu-nat.c (inf_startup): remove TASK parameter.
	    (inf_set_task): replace with new function (inf_set_pid).
	  * gdbthread.h: Add extern decl for thread_cmd_list.
This commit is contained in:
Michael Snyder 1997-05-01 20:39:06 +00:00
parent 6475b23404
commit 2847920ae9
3 changed files with 164 additions and 148 deletions

View File

@ -43,4 +43,7 @@ extern void save_infrun_state PARAMS ((int, CORE_ADDR, CORE_ADDR, char *,
struct breakpoint *, CORE_ADDR,
CORE_ADDR, CORE_ADDR, int, int));
/* Commands with a prefix of `thread'. */
extern struct cmd_list_element *thread_cmd_list;
#endif /* GDBTHREAD_H */

View File

@ -1,5 +1,5 @@
/* Interface GDB to the GNU Hurd
Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
Copyright (C) 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GDB.
@ -88,26 +88,26 @@ extern struct target_ops gnu_ops;
extern char *strerror();
int inf_update_procs (struct inf *inf);
static struct inf *make_inf ();
static void inf_clear_wait (struct inf *inf);
static void inf_cleanup (struct inf *inf);
static void inf_startup (struct inf *inf, int pid, task_t task);
static int inf_update_suspends (struct inf *inf);
static void inf_set_task (struct inf *inf, task_t port);
static void inf_validate_procs (struct inf *inf);
static void inf_steal_exc_ports (struct inf *inf);
static void inf_restore_exc_ports (struct inf *inf);
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);
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);
int inf_update_suspends (struct inf *inf);
void inf_set_pid (struct inf *inf, pid_t pid);
void inf_validate_procs (struct inf *inf);
void inf_steal_exc_ports (struct inf *inf);
void inf_restore_exc_ports (struct inf *inf);
struct proc *inf_tid_to_proc (struct inf *inf, int tid);
inline void inf_set_threads_resume_sc (struct inf *inf,
struct proc *run_thread,
int run_others);
inline int inf_set_threads_resume_sc_for_signal_thread (struct inf *inf);
inline void inf_suspend (struct inf *inf);
inline void inf_resume (struct inf *inf);
void inf_set_step_thread (struct inf *inf, struct proc *proc);
void inf_detach (struct inf *inf);
void inf_attach (struct inf *inf, int pid);
void inf_signal (struct inf *inf, enum target_signal sig);
#define inf_debug(_inf, msg, args...) \
do { struct inf *__inf = (_inf); \
@ -115,15 +115,15 @@ static void inf_signal (struct inf *inf, enum target_signal sig);
void proc_abort (struct proc *proc, int force);
thread_state_t proc_get_state (struct proc *proc, int force);
static struct proc *make_proc (struct inf *inf, mach_port_t port, int tid);
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);
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);
error_t proc_get_exception_port (struct proc *proc, mach_port_t *port);
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 void proc_steal_exc_port (struct proc *proc, mach_port_t exc_port);
static void proc_restore_exc_port (struct proc *proc);
static int proc_trace (struct proc *proc, int set);
void proc_steal_exc_port (struct proc *proc, mach_port_t exc_port);
void proc_restore_exc_port (struct proc *proc);
int proc_trace (struct proc *proc, int set);
char *proc_string (struct proc *proc);
/* Evaluate RPC_EXPR in a scope with the variables MSGPORT and REFPORT bound
@ -248,7 +248,7 @@ int __proc_pid (struct proc *proc)
/* Update PROC's real suspend count to match it's desired one. Returns true
if we think PROC is now in a runnable state. */
static int
int
proc_update_sc (struct proc *proc)
{
int running;
@ -378,7 +378,7 @@ proc_get_state (struct proc *proc, int will_modify)
}
/* Set PORT to PROC's exception port. */
static error_t
error_t
proc_get_exception_port (struct proc *proc, mach_port_t *port)
{
if (proc_is_task (proc))
@ -388,7 +388,7 @@ proc_get_exception_port (struct proc *proc, mach_port_t *port)
}
/* Set PROC's exception port to PORT. */
static error_t
error_t
proc_set_exception_port (struct proc *proc, mach_port_t port)
{
proc_debug (proc, "setting exception port: %d", port);
@ -421,7 +421,7 @@ _proc_get_exc_port (struct proc *proc)
/* 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. */
static void
void
proc_steal_exc_port (struct proc *proc, mach_port_t exc_port)
{
mach_port_t cur_exc_port = _proc_get_exc_port (proc);
@ -464,7 +464,7 @@ 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 there at the time, unless *our* exception port has since been
overwritten, in which case who knows what's going on. */
static void
void
proc_restore_exc_port (struct proc *proc)
{
mach_port_t cur_exc_port = _proc_get_exc_port (proc);
@ -493,7 +493,7 @@ proc_restore_exc_port (struct proc *proc)
/* Turns hardware tracing in PROC on or off when SET is true or false,
respectively. Returns true on success. */
static int
int
proc_trace (struct proc *proc, int set)
{
thread_state_t state = proc_get_state (proc, 1);
@ -583,7 +583,7 @@ make_proc (struct inf *inf, mach_port_t port, int tid)
/* Frees PROC and any resources it uses, and returns the value of PROC's
next field. */
static struct proc *
struct proc *
_proc_free (struct proc *proc)
{
struct inf *inf = proc->inf;
@ -652,7 +652,7 @@ struct inf *make_inf ()
}
/* clear INF's target wait status. */
static void
void
inf_clear_wait (struct inf *inf)
{
inf_debug (inf, "clearing wait");
@ -671,14 +671,14 @@ inf_clear_wait (struct inf *inf)
}
}
static void
void
inf_cleanup (struct inf *inf)
{
inf_debug (inf, "cleanup");
inf_clear_wait (inf);
inf_set_task (inf, MACH_PORT_NULL);
inf_set_pid (inf, -1);
inf->pid = 0;
inf->traced = 0;
inf->no_wait = 0;
@ -693,12 +693,12 @@ inf_cleanup (struct inf *inf)
}
}
static void
inf_startup (struct inf *inf, int pid, task_t task)
void
inf_startup (struct inf *inf, int pid)
{
error_t err;
inf_debug (inf, "startup: pid = %d, task = %d", pid, task);
inf_debug (inf, "startup: pid = %d", pid);
inf_cleanup (inf);
@ -711,11 +711,44 @@ inf_startup (struct inf *inf, int pid, task_t task)
/* Make a send right for it, so we can easily copy it for other people. */
mach_port_insert_right (mach_task_self (), inf->event_port,
inf->event_port, MACH_MSG_TYPE_MAKE_SEND);
inf_set_pid (inf, pid);
}
/* close current process, if any, and attach INF to process PORT */
void
inf_set_pid (struct inf *inf, pid_t pid)
{
task_t task_port;
struct proc *task = inf->task;
inf_debug (inf, "setting pid: %d", pid);
if (pid < 0)
task_port = MACH_PORT_NULL;
else
{
error_t err = proc_pid2task (proc_server, pid, &task_port);
if (err)
error ("Error getting task for pid %d: %s", pid, strerror (err));
}
inf_debug (inf, "setting task: %d", task_port);
if (inf->pause_sc)
task_suspend (task);
task_suspend (task_port);
inf_set_task (inf, task);
if (task && task->port != task_port)
{
inf->task = 0;
inf_validate_procs (inf); /* Trash all the threads. */
_proc_free (task); /* And the task. */
}
if (task_port != MACH_PORT_NULL)
{
inf->task = make_proc (inf, task_port, PROC_TID_TASK);
inf->threads_up_to_date = 0;
}
if (inf->task)
{
@ -723,28 +756,8 @@ inf_startup (struct inf *inf, int pid, task_t task)
if (inf->pause_sc)
inf->task->sc = inf->task->cur_sc = 1; /* Reflect task_suspend above */
}
}
/* close current process, if any, and attach INF to process PORT */
static void
inf_set_task (struct inf *inf, mach_port_t port)
{
struct proc *task = inf->task;
inf_debug (inf, "setting task: %d", port);
if (task && task->port != port)
{
inf->task = 0;
inf_validate_procs (inf); /* Trash all the threads. */
_proc_free (task); /* And the task. */
}
if (port != MACH_PORT_NULL)
{
inf->task = make_proc (inf, port, PROC_TID_TASK);
inf->threads_up_to_date = 0;
}
else
inf->pid = -1;
}
/* Validates INF's stopped field from the actual proc server state. */
@ -801,7 +814,7 @@ inf_validate_task_sc (struct inf *inf)
/* 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,
and the signal thread will briefly be run to change the trace state. */
static void
void
inf_set_traced (struct inf *inf, int on)
{
if (on != inf->traced)
@ -832,7 +845,7 @@ inf_set_traced (struct inf *inf, int on)
/* 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
safe order. Returns true if at least one thread is thought to be running.*/
static int
int
inf_update_suspends (struct inf *inf)
{
struct proc *task = inf->task;
@ -886,8 +899,7 @@ struct proc *
inf_tid_to_thread (struct inf *inf, int tid)
{
struct proc *thread = inf->threads;
if (tid == inf->pid) /* main thread */
return thread;
while (thread)
if (thread->tid == tid)
return thread;
@ -897,7 +909,7 @@ inf_tid_to_thread (struct inf *inf, int tid)
}
/* Converts a thread port to a struct proc. */
static struct proc *
struct proc *
inf_port_to_thread (struct inf *inf, mach_port_t port)
{
struct proc *thread = inf->threads;
@ -910,7 +922,7 @@ inf_port_to_thread (struct inf *inf, mach_port_t port)
}
/* Make INF's list of threads be consistent with reality of TASK. */
static void
void
inf_validate_procs (struct inf *inf)
{
int i;
@ -988,23 +1000,11 @@ inf_validate_procs (struct inf *inf)
else
/* THREADS[I] is a thread we don't know about yet! */
{
#if 0
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 = thread;
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. */
#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(),
@ -1026,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,
and others are set to their run_sc if RUN_OTHERS is true, and otherwise
their pause_sc. */
static inline void
inline void
inf_set_threads_resume_sc (struct inf *inf,
struct proc *run_thread, int run_others)
{
@ -1043,7 +1043,7 @@ inf_set_threads_resume_sc (struct inf *inf,
/* Cause INF to continue execution immediately; individual threads may still
be suspended (but their suspend counts will be updated). */
static inline void
inline void
inf_resume (struct inf *inf)
{
struct proc *thread;
@ -1068,7 +1068,7 @@ inf_resume (struct inf *inf)
/* Cause INF to stop execution immediately; individual threads may still
be running. */
static inline void
inline void
inf_suspend (struct inf *inf)
{
struct proc *thread;
@ -1087,7 +1087,7 @@ inf_suspend (struct inf *inf)
/* 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
PROC of 0 clears any existing value. */
static void
void
inf_set_step_thread (struct inf *inf, struct proc *thread)
{
assert (!thread || proc_is_thread (thread));
@ -1112,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
(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. */
static inline int
inline int
inf_set_threads_resume_sc_for_signal_thread (struct inf *inf)
{
if (inf->signal_thread)
@ -1133,7 +1133,7 @@ inf_update_signal_thread (struct inf *inf)
}
/* Detachs from INF's inferior task, letting it run once again... */
static void
void
inf_detach (struct inf *inf)
{
struct proc *task = inf->task;
@ -1168,22 +1168,15 @@ inf_detach (struct inf *inf)
/* Attaches INF to the process with process id PID, returning it in a suspended
state suitable for debugging. */
static void
void
inf_attach (struct inf *inf, int pid)
{
error_t err;
task_t task;
inf_debug (inf, "attaching: %d", pid);
err = proc_pid2task (proc_server, pid, &task);
if (err)
error ("Error getting task for pid %d: %s", pid, strerror (err));
if (inf->pid)
inf_detach (inf);
inf_startup (inf, pid, task);
inf_startup (inf, pid);
}
/* Makes sure that we've got our exception ports entrenched in the process. */
@ -1217,7 +1210,7 @@ void inf_restore_exc_ports (struct inf *inf)
/* 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
the resume_sc's of INF's threads may be affected. */
static void
void
inf_signal (struct inf *inf, enum target_signal sig)
{
error_t err = 0;
@ -1377,6 +1370,12 @@ gnu_wait (int tid, struct target_waitstatus *status)
/* Re-suspend the task. */
inf_suspend (inf);
if (!inf->task && inf->pending_execs)
/* When doing an exec, it's possible that the old task wasn't reused
(e.g., setuid execs). So if the task seems to have disappeared,
attempt to refetch it, as the pid should still be the same. */
inf_set_pid (inf, inf->pid);
if (err == EMACH_RCV_INTERRUPTED)
inf_debug (inf, "interrupted");
else if (err)
@ -1425,17 +1424,24 @@ gnu_wait (int tid, struct target_waitstatus *status)
/* Ah hah! A SIGTRAP from the inferior while starting up probably
means we've succesfully completed an exec! */
{
#if 0 /* do we need this? */
if (--inf->pending_execs == 0)
/* We're done! */
{
#if 0 /* do we need this? */
prune_threads (1); /* Get rid of the old shell threads */
renumber_threads (0); /* Give our threads reasonable names. */
}
#endif
}
inf_debug (inf, "pending exec completed, pending_execs => %d",
inf->pending_execs);
}
else if (kind == TARGET_WAITKIND_STOPPED)
/* It's possible that this signal is because of a crashed process
being handled by the hurd crash server; in this case, the process
will have an extra task suspend, which we need to know about.
Since the code in inf_resume that normally checks for this is
disabled while INF->pending_execs, we do the check here instead. */
inf_validate_task_sc (inf);
}
if (inf->wait.suppress)
@ -1569,7 +1575,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
detailed information. */
static void
void
inf_task_died_status (struct inf *inf)
{
warning ("Pid %d died with unknown exit status, using SIGKILL.", inf->pid);
@ -1853,7 +1859,7 @@ gnu_kill_inferior ()
{
proc_debug (task, "terminating...");
task_terminate (task->port);
inf_set_task (current_inferior, MACH_PORT_NULL);
inf_set_pid (current_inferior, -1);
}
target_mourn_inferior ();
}
@ -2006,9 +2012,7 @@ gnu_attach (args, from_tty)
time the user does a continue. */
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. */
#if 0 /* Do we need this? */
renumber_threads (0); /* Give our threads reasonable names. */
#endif
}
@ -2389,13 +2393,7 @@ char *proc_string (struct proc *proc)
sprintf (tid_str, "process %d", proc->inf->pid);
else
sprintf (tid_str, "thread %d.%d",
proc->inf->pid,
#if 0
pid_to_thread_id (proc->tid)
#else
proc->tid
#endif
);
proc->inf->pid, pid_to_thread_id (proc->tid));
return tid_str;
}

View File

@ -270,25 +270,41 @@ void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
tp->another_trap = another_trap;
}
/* Return true if TP is an active thread. */
static int
thread_alive (tp)
struct thread_info *tp;
{
if (tp->pid == -1)
return 0;
if (! target_thread_alive (tp->pid))
{
tp->pid = -1; /* Mark it as dead */
return 0;
}
return 1;
}
static void
prune_threads ()
{
struct thread_info *tp, *tpprev;
struct thread_info *tp, *tpprev, *next;
tpprev = 0;
for (tp = thread_list; tp; tp = tp->next)
if (tp->pid == -1)
{
if (tpprev)
tpprev->next = tp->next;
else
thread_list = NULL;
free (tp);
}
else
tpprev = tp;
for (tp = thread_list; tp; tp = next)
{
next = tp->next;
if (!thread_alive (tp))
{
if (tpprev)
tpprev->next = next;
else
thread_list = next;
free (tp);
}
else
tpprev = tp;
}
}
/* Print information about currently known threads */
@ -305,14 +321,9 @@ info_threads_command (arg, from_tty)
selected_frame. */
if (!target_has_stack) error ("No stack.");
prune_threads ();
for (tp = thread_list; tp; tp = tp->next)
{
if (! target_thread_alive (tp->pid))
{
tp->pid = -1; /* Mark it as dead */
continue;
}
if (tp->pid == current_pid)
printf_filtered ("* ");
else
@ -325,7 +336,6 @@ info_threads_command (arg, from_tty)
}
switch_to_thread (current_pid);
prune_threads ();
}
/* Switch from one thread to another. */
@ -375,12 +385,13 @@ thread_apply_all_command (cmd, from_tty)
old_chain = make_cleanup (restore_current_thread, inferior_pid);
for (tp = thread_list; tp; tp = tp->next)
{
switch_to_thread (tp->pid);
printf_filtered ("\nThread %d (%s):\n", tp->num,
target_pid_to_str (inferior_pid));
execute_command (cmd, from_tty);
}
if (thread_alive (tp))
{
switch_to_thread (tp->pid);
printf_filtered ("\nThread %d (%s):\n", tp->num,
target_pid_to_str (inferior_pid));
execute_command (cmd, from_tty);
}
}
static void
@ -434,15 +445,16 @@ thread_apply_command (tidlist, from_tty)
tp = find_thread_id (start);
if (!tp)
warning ("Unknown thread %d.", start);
else if (!thread_alive (tp))
warning ("Thread %d has terminated.", start);
else
{
warning ("Unknown thread %d.", start);
continue;
switch_to_thread (tp->pid);
printf_filtered ("\nThread %d (%s):\n", tp->num,
target_pid_to_str (inferior_pid));
execute_command (cmd, from_tty);
}
switch_to_thread (tp->pid);
printf_filtered ("\nThread %d (%s):\n", tp->num,
target_pid_to_str (inferior_pid));
execute_command (cmd, from_tty);
}
}
}
@ -470,6 +482,9 @@ see the IDs of currently known threads.");
error ("Thread ID %d not known. Use the \"info threads\" command to\n\
see the IDs of currently known threads.", num);
if (!thread_alive (tp))
error ("Thread ID %d has terminated.\n", num);
switch_to_thread (tp->pid);
printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));