Wed May 21 16:03:25 1997 Michael Snyder <msnyder@cleaver.cygnus.com>

* procfs.c (init_procinfo): new function, abstracts some code
        shared by create_procinfo and do_attach;
        (procfs_set_inferior_syscall_traps): new function, abstracts
        some code needed by procfs_init_inferior, do_attach, and
        procfs_lwp_creation_handler; (procfs_first_available): new
        function, find any LWP that's runnable; (procfs_thread_alive):
        replace stub function with real implementation;
        (procfs_lwp_creation_handler): fix bug starting new child
        threads; (info_proc): bug fixes and enhancements for the
        "INFO PROCESSES" command; (close_procinfo_file): call new
        function "delete_thread" to cleanup GDB's thread database;
        (proc_init_failed): add new argument "kill", to control whether
        process is killed (so this function can be shared by
        create_procinfo and do_attach); (procfs_exit_handler): handle
        exit from an attached process, and cleanup procinfo handles
        when the process exits; (procfs_resume, procfs_wait): cleanup
        after a thread when it exits; (do_attach, do_detach): handle
        attached processes with multiple threads; plus some general
        improvements in the diagnostic output.
        * sol-thread.c (sol_thread_alive): replace stub with real
        implementation; (thread_to_lwp, lwp_to_thread): enhance to
        handle threads that may have exited; (sol_thread_attach): add
        startup setup stuff; (sol_thread_detach): add unpush_target
        call; (sol_thread_mourn_inferior): add unpush_target call;
        (sol_thread_wait, sol_thread_resume): enhance to deal with
        thread exit cleanly; (sol_thread_new_objfile,
        sol_thread_pid_to_str): detect unsuccessful startup and
        don't crash; plus some general cleanup.
        * thread.c (delete_thread): new function, allows targets to
        notify gdb when a thread is no longer valid.
        * infrun.c (wait_for_inferior): don't try to detect a new
        thread on receiving a TARGET_EXITED event.
This commit is contained in:
Michael Snyder 1997-05-21 23:33:33 +00:00
parent b4a4a6dc0f
commit 3780c33708
4 changed files with 745 additions and 410 deletions

View file

@ -1,3 +1,43 @@
Wed May 21 16:03:25 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
* procfs.c (init_procinfo): new function, abstracts some code
shared by create_procinfo and do_attach;
(procfs_set_inferior_syscall_traps): new function, abstracts
some code needed by procfs_init_inferior, do_attach, and
procfs_lwp_creation_handler; (procfs_first_available): new
function, find any LWP that's runnable; (procfs_thread_alive):
replace stub function with real implementation;
(procfs_lwp_creation_handler): fix bug starting new child
threads; (info_proc): bug fixes and enhancements for the
"INFO PROCESSES" command; (close_procinfo_file): call new
function "delete_thread" to cleanup GDB's thread database;
(proc_init_failed): add new argument "kill", to control whether
process is killed (so this function can be shared by
create_procinfo and do_attach); (procfs_exit_handler): handle
exit from an attached process, and cleanup procinfo handles
when the process exits; (procfs_resume, procfs_wait): cleanup
after a thread when it exits; (do_attach, do_detach): handle
attached processes with multiple threads; plus some general
improvements in the diagnostic output.
* sol-thread.c (sol_thread_alive): replace stub with real
implementation; (thread_to_lwp, lwp_to_thread): enhance to
handle threads that may have exited; (sol_thread_attach): add
startup setup stuff; (sol_thread_detach): add unpush_target
call; (sol_thread_mourn_inferior): add unpush_target call;
(sol_thread_wait, sol_thread_resume): enhance to deal with
thread exit cleanly; (sol_thread_new_objfile,
sol_thread_pid_to_str): detect unsuccessful startup and
don't crash; plus some general cleanup.
* thread.c (delete_thread): new function, allows targets to
notify gdb when a thread is no longer valid.
* infrun.c (wait_for_inferior): don't try to detect a new
thread on receiving a TARGET_EXITED event.
Tue May 20 09:32:02 1997 Andrew Cagney <cagney@b1.cygnus.com>
* remote-sim.c (gdbsim_open): Pass callback struct.
(init_callbacks): Remove call to sim_set_callbacks.
Thu May 15 07:56:50 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
* config/rs6000/tm-rs6000.h (SIG_FRAME_LR_OFFSET): Define.

File diff suppressed because it is too large Load diff

View file

@ -72,6 +72,7 @@ extern struct target_ops sol_thread_ops; /* Forward declaration */
extern int procfs_suppress_run;
extern struct target_ops procfs_ops; /* target vector for procfs.c */
extern char *procfs_pid_to_str PARAMS ((int pid));
/* Note that these prototypes differ slightly from those used in procfs.c
for of two reasons. One, we can't use gregset_t, as that's got a whole
@ -110,10 +111,11 @@ static struct cleanup * save_inferior_pid PARAMS ((void));
static void restore_inferior_pid PARAMS ((int pid));
static char *td_err_string PARAMS ((td_err_e errcode));
static char *td_state_string PARAMS ((td_thr_state_e statecode));
static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
static void sol_thread_resume PARAMS ((int pid, int step,
enum target_signal signo));
static int lwp_to_thread PARAMS ((int lwp));
static int sol_thread_alive PARAMS ((int pid));
#define THREAD_FLAG 0x80000000
#define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
@ -306,24 +308,22 @@ thread_to_lwp (thread_id, default_lwp)
td_thrinfo_t ti;
td_thrhandle_t th;
td_err_e val;
int pid;
int lwp;
if (is_lwp (thread_id))
return thread_id; /* It's already an LWP id */
/* It's a thread. Convert to lwp */
pid = PIDGET (thread_id);
thread_id = GET_THREAD(thread_id);
val = p_td_ta_map_id2thr (main_ta, thread_id, &th);
if (val != TD_OK)
val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
if (val == TD_NOTHR)
return -1; /* thread must have terminated */
else if (val != TD_OK)
error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
val = p_td_thr_get_info (&th, &ti);
if (val != TD_OK)
if (val == TD_NOTHR)
return -1; /* thread must have terminated */
else if (val != TD_OK)
error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
if (ti.ti_state != TD_THR_ACTIVE)
@ -333,10 +333,8 @@ thread_to_lwp (thread_id, default_lwp)
error ("thread_to_lwp: thread state not active: %s",
td_state_string (ti.ti_state));
}
lwp = BUILD_LWP (ti.ti_lid, pid);
return lwp;
return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
}
/*
@ -367,29 +365,34 @@ lwp_to_thread (lwp)
td_thrinfo_t ti;
td_thrhandle_t th;
td_err_e val;
int pid;
int thread_id;
if (is_thread (lwp))
return lwp; /* It's already a thread id */
/* It's an lwp. Convert it to a thread id. */
pid = PIDGET (lwp);
lwp = GET_LWP (lwp);
if (!sol_thread_alive (lwp))
return -1; /* defunct lwp */
val = p_td_ta_map_lwp2thr (main_ta, lwp, &th);
if (val != TD_OK)
val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
if (val == TD_NOTHR)
return -1; /* thread must have terminated */
else if (val != TD_OK)
error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
val = p_td_thr_validate (&th);
if (val == TD_NOTHR)
return lwp; /* libthread doesn't know about it, just return lwp */
else if (val != TD_OK)
error ("lwp_to_thread: td_thr_validate: %s.", td_err_string (val));
val = p_td_thr_get_info (&th, &ti);
if (val != TD_OK)
if (val == TD_NOTHR)
return -1; /* thread must have terminated */
else if (val != TD_OK)
error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
thread_id = BUILD_THREAD (ti.ti_tid, pid);
return thread_id;
return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
}
/*
@ -456,7 +459,19 @@ sol_thread_attach (args, from_tty)
int from_tty;
{
procfs_ops.to_attach (args, from_tty);
/* Must get symbols from solibs before libthread_db can run! */
SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
if (sol_thread_active)
{
printf_filtered ("sol-thread active.\n");
main_ph.pid = inferior_pid; /* Save for xfer_memory */
push_target (&sol_thread_ops);
inferior_pid = lwp_to_thread (inferior_pid);
if (inferior_pid == -1)
inferior_pid = main_ph.pid;
else
add_thread (inferior_pid);
}
/* XXX - might want to iterate over all the threads and register them. */
}
@ -473,6 +488,7 @@ sol_thread_detach (args, from_tty)
char *args;
int from_tty;
{
unpush_target (&sol_thread_ops);
procfs_ops.to_detach (args, from_tty);
}
@ -492,12 +508,19 @@ sol_thread_resume (pid, step, signo)
old_chain = save_inferior_pid ();
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
if (inferior_pid == -1)
inferior_pid = procfs_first_available ();
if (pid != -1)
{
int save_pid = pid;
pid = thread_to_lwp (pid, -2);
if (pid == -2) /* Inactive thread */
error ("This version of Solaris can't start inactive threads.");
if (info_verbose && pid == -1)
warning ("Specified thread %d seems to have terminated",
GET_THREAD (save_pid));
}
procfs_ops.to_resume (pid, step, signo);
@ -521,28 +544,44 @@ sol_thread_wait (pid, ourstatus)
old_chain = save_inferior_pid ();
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
if (inferior_pid == -1)
inferior_pid = procfs_first_available ();
if (pid != -1)
pid = thread_to_lwp (pid, -1);
{
int save_pid = pid;
pid = thread_to_lwp (pid, -2);
if (pid == -2) /* Inactive thread */
error ("This version of Solaris can't start inactive threads.");
if (info_verbose && pid == -1)
warning ("Specified thread %d seems to have terminated",
GET_THREAD (save_pid));
}
rtnval = procfs_ops.to_wait (pid, ourstatus);
if (rtnval != save_pid
&& !in_thread_list (rtnval))
if (ourstatus->kind != TARGET_WAITKIND_EXITED)
{
fprintf_unfiltered (gdb_stderr, "[New %s]\n",
target_pid_to_str (rtnval));
add_thread (rtnval);
/* Map the LWP of interest back to the appropriate thread ID */
rtnval = lwp_to_thread (rtnval);
if (rtnval == -1)
rtnval = save_pid;
/* See if we have a new thread */
if (is_thread (rtnval)
&& rtnval != save_pid
&& !in_thread_list (rtnval))
{
printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
add_thread (rtnval);
}
}
/* During process initialization, we may get here without the thread package
being initialized, since that can only happen after we've found the shared
libs. */
/* Map the LWP of interest back to the appropriate thread ID */
rtnval = lwp_to_thread (rtnval);
do_cleanups (old_chain);
return rtnval;
@ -751,8 +790,6 @@ sol_thread_notice_signals (pid)
procfs_ops.to_notice_signals (pid);
}
void target_new_objfile PARAMS ((struct objfile *objfile));
/* Fork an inferior process, and start debugging it with /proc. */
static void
@ -763,13 +800,15 @@ sol_thread_create_inferior (exec_file, allargs, env)
{
procfs_ops.to_create_inferior (exec_file, allargs, env);
if (sol_thread_active)
if (sol_thread_active && inferior_pid != 0)
{
main_ph.pid = inferior_pid; /* Save for xfer_memory */
push_target (&sol_thread_ops);
inferior_pid = lwp_to_thread (inferior_pid);
if (inferior_pid == -1)
inferior_pid = main_ph.pid;
add_thread (inferior_pid);
}
@ -794,6 +833,10 @@ sol_thread_new_objfile (objfile)
return;
}
/* don't do anything if init failed to resolve the libthread_db library */
if (!procfs_suppress_run)
return;
/* Now, initialize the thread debugging library. This needs to be done after
the shared libraries are located because it needs information from the
user's thread library. */
@ -816,6 +859,7 @@ sol_thread_new_objfile (objfile)
static void
sol_thread_mourn_inferior ()
{
unpush_target (&sol_thread_ops);
procfs_ops.to_mourn_inferior ();
}
@ -827,11 +871,40 @@ sol_thread_can_run ()
return procfs_suppress_run;
}
/*
LOCAL FUNCTION
sol_thread_alive - test thread for "aliveness"
SYNOPSIS
static bool sol_thread_alive (int pid);
DESCRIPTION
returns true if thread still active in inferior.
*/
static int
sol_thread_alive (pid)
int pid;
{
return 1;
if (is_thread (pid)) /* non-kernel thread */
{
td_err_e val;
td_thrhandle_t th;
pid = GET_THREAD (pid);
if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
return 0; /* thread not found */
if ((val = p_td_thr_validate (&th)) != TD_OK)
return 0; /* thread not valid */
return 1; /* known thread: return true */
}
else /* kernel thread (LWP): let procfs test it */
return procfs_ops.to_thread_alive (pid);
}
static void
@ -910,9 +983,9 @@ rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
if (cc < 0)
{
if (dowrite == 0)
print_sys_errmsg ("ps_pdread (): read", errno);
print_sys_errmsg ("rw_common (): read", errno);
else
print_sys_errmsg ("ps_pdread (): write", errno);
print_sys_errmsg ("rw_common (): write", errno);
do_cleanups (old_chain);
@ -1123,19 +1196,27 @@ solaris_pid_to_str (pid)
{
static char buf[100];
/* in case init failed to resolve the libthread_db library */
if (!procfs_suppress_run)
return procfs_pid_to_str (pid);
if (is_thread (pid))
{
int lwp;
lwp = thread_to_lwp (pid, -2);
if (lwp != -2)
if (lwp == -1)
sprintf (buf, "Thread %d (defunct)", GET_THREAD (pid));
else if (lwp != -2)
sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
else
sprintf (buf, "Thread %d ", GET_THREAD (pid));
}
else
else if (GET_LWP (pid) != 0)
sprintf (buf, "LWP %d ", GET_LWP (pid));
else
sprintf (buf, "process %d ", PIDGET (pid));
return buf;
}

View file

@ -125,6 +125,31 @@ add_thread (pid)
thread_list = tp;
}
void
delete_thread (pid)
int pid;
{
struct thread_info *tp, *tpprev;
tpprev = NULL;
for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
if (tp->pid == pid)
break;
if (!tp)
return;
if (tpprev)
tpprev->next = tp->next;
else
thread_list = tp->next;
free (tp);
return;
}
static struct thread_info *
find_thread_id (num)
int num;
@ -332,7 +357,10 @@ info_threads_command (arg, from_tty)
printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
switch_to_thread (tp->pid);
print_stack_frame (selected_frame, -1, 0);
if (selected_frame)
print_stack_frame (selected_frame, -1, 0);
else
printf_filtered ("[No stack.]\n");
}
switch_to_thread (current_pid);