* sol-thread.c: More cleanup, add comments.

* (sol_thread_resume):  Prevent people from trying to step
	inactive threads.
	* (sol_thread_wait sol_thread_fetch_registers
	sol_thread_store_registers):  Remove unnecessary check for
	sol_thread_active.  These routines won't get called unless threads
	are active.
This commit is contained in:
Stu Grossman 1996-05-13 23:22:32 +00:00
parent 05535e79e9
commit a50cedad0e
2 changed files with 145 additions and 33 deletions

View File

@ -1,3 +1,13 @@
Mon May 13 16:17:36 1996 Stu Grossman (grossman@critters.cygnus.com)
* sol-thread.c: More cleanup, add comments.
* (sol_thread_resume): Prevent people from trying to step
inactive threads.
* (sol_thread_wait sol_thread_fetch_registers
sol_thread_store_registers): Remove unnecessary check for
sol_thread_active. These routines won't get called unless threads
are active.
Mon May 13 11:29:37 1996 Stan Shebs <shebs@andros.cygnus.com>
SH3-E support from Allan Tajii <atajii@hmsi.com>:

View File

@ -17,6 +17,34 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This module implements a sort of half target that sits between the
machine-independent parts of GDB and the /proc interface (procfs.c) to
provide access to the Solaris user-mode thread implementation.
Solaris threads are true user-mode threads, which are invoked via the thr_*
and pthread_* (native and Posix respectivly) interfaces. These are mostly
implemented in user-space, with all thread context kept in various
structures that live in the user's heap. These should not be confused with
lightweight processes (LWPs), which are implemented by the kernel, and
scheduled without explicit intervention by the process.
Just to confuse things a little, Solaris threads (both native and Posix) are
actually implemented using LWPs. In general, there are going to be more
threads than LWPs. There is no fixed correspondence between a thread and an
LWP. When a thread wants to run, it gets scheduled onto the first available
LWP and can therefore migrate from one LWP to another as time goes on. A
sleeping thread may not be associated with an LWP at all!
To make it possible to mess with threads, Sun provides a library called
libthread_db.so.1 (not to be confused with libthread_db.so.0, which doesn't
have a published interface). This interface has an upper part, which it
provides, and a lower part which I provide. The upper part consists of the
td_* routines, which allow me to find all the threads, query their state,
etc... The lower part consists of all of the ps_*, which are used by the
td_* routines to read/write memory, manipulate LWPs, lookup symbols, etc...
The ps_* routines actually do most of their work by calling functions in
procfs.c. */
#include "defs.h"
/* Undefine gregset_t and fpregset_t to avoid conflict with defs in xm file. */
@ -44,11 +72,24 @@ 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 */
/* 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
different meaning under Solaris (also, see above). Two, we can't use the
pointer form here as these are actually arrays of ints (for Sparc's at
least), and are automatically coerced into pointers to ints when used as
parameters. That makes it impossible to avoid a compiler warning when
passing pr{g fp}regset_t's from a parameter to an argument of one of
these functions. */
extern void supply_gregset PARAMS ((const prgregset_t));
extern void fill_gregset PARAMS ((prgregset_t, int));
extern void supply_fpregset PARAMS ((const prfpregset_t));
extern void fill_fpregset PARAMS ((prfpregset_t, int));
/* This struct is defined by us, but mainly used for the proc_service interface.
We don't have much use for it, except as a handy place to get a real pid
for memory accesses. */
struct ps_prochandle
{
pid_t pid;
@ -246,8 +287,27 @@ thread_to_lwp (thread_id, default_lwp)
return lwp;
}
/*
/* Convert an LWP id to a thread. */
LOCAL FUNCTION
lwp_to_thread - Convert a LWP id to a Posix or Solaris thread id.
SYNOPSIS
int lwp_to_thread (lwp_id)
DESCRIPTION
This function converts a lightweight process id to a Posix or Solaris
thread id. If thread_id is non-existent, that's an error.
NOTES
This function probably shouldn't call error()...
*/
static int
lwp_to_thread (lwp)
@ -281,6 +341,34 @@ lwp_to_thread (lwp)
return thread_id;
}
/*
LOCAL FUNCTION
save_inferior_pid - Save inferior_pid on the cleanup list
restore_inferior_pid - Restore inferior_pid from the cleanup list
SYNOPSIS
struct cleanup *save_inferior_pid ()
void restore_inferior_pid (int pid)
DESCRIPTION
These two functions act in unison to restore inferior_pid in
case of an error.
NOTES
inferior_pid is a global variable that needs to be changed by many of
these routines before calling functions in procfs.c. In order to
guarantee that inferior_pid gets restored (in case of errors), you
need to call save_inferior_pid before changing it. At the end of the
function, you should invoke do_cleanups to restore it.
*/
static struct cleanup *
save_inferior_pid ()
{
@ -294,6 +382,11 @@ restore_inferior_pid (pid)
inferior_pid = pid;
}
/* Most target vector functions from here on actually just pass through to
procfs.c, as they don't need to do anything specific for threads. */
/* ARGSUSED */
static void
sol_thread_open (arg, from_tty)
@ -334,7 +427,8 @@ sol_thread_detach (args, from_tty)
/* Resume execution of process PID. If STEP is nozero, then
just single step it. If SIGNAL is nonzero, restart it with that
signal activated. */
signal activated. We may have to convert pid from a thread-id to an LWP id
for procfs. */
static void
sol_thread_resume (pid, step, signo)
@ -349,14 +443,19 @@ sol_thread_resume (pid, step, signo)
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
if (pid != -1)
pid = thread_to_lwp (pid, -1);
{
pid = thread_to_lwp (pid, -2);
if (pid == -2) /* Inactive thread */
error ("This version of Solaris can't start inactive threads.");
}
procfs_ops.to_resume (pid, step, signo);
do_cleanups (old_chain);
}
/* Wait for any LWPs to stop */
/* Wait for any threads to stop. We may have to convert PID from a thread id
to a LWP id, and vice versa on the way out. */
static int
sol_thread_wait (pid, ourstatus)
@ -367,9 +466,6 @@ sol_thread_wait (pid, ourstatus)
int save_pid;
struct cleanup *old_chain;
if (!sol_thread_active)
return procfs_ops.to_wait (pid, ourstatus);
save_pid = inferior_pid;
old_chain = save_inferior_pid ();
@ -415,13 +511,6 @@ sol_thread_fetch_registers (regno)
caddr_t xregset;
#endif
if (!sol_thread_active
|| is_lwp (inferior_pid))
{
procfs_ops.to_fetch_registers (regno);
return;
}
/* Convert inferior_pid into a td_thrhandle_t */
thread = GET_THREAD (inferior_pid);
@ -495,13 +584,6 @@ sol_thread_store_registers (regno)
caddr_t xregset;
#endif
if (!sol_thread_active
|| is_lwp (inferior_pid))
{
procfs_ops.to_store_registers (regno);
return;
}
/* Convert inferior_pid into a td_thrhandle_t */
thread = GET_THREAD (inferior_pid);
@ -646,7 +728,10 @@ sol_thread_create_inferior (exec_file, allargs, env)
}
/* This routine is called whenever a new symbol table is read in, or when all
symbol tables are removed. */
symbol tables are removed. libthread_db can only be initialized when it
finds the right variables in libthread.so. Since it's a shared library,
those variables don't show up until the library gets mapped and the symbol
table is read in. */
void
sol_thread_new_objfile (objfile)
@ -687,34 +772,33 @@ sol_thread_mourn_inferior ()
}
/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
static int
sol_thread_can_run ()
{
return procfs_suppress_run;
}
int
static int
sol_thread_alive (pid)
int pid;
{
return 1;
}
void
static void
sol_thread_stop ()
{
procfs_ops.to_stop ();
}
/* These routines implement the lower half of the thread_db interface. Ie: the
ps_* routines. */
/* Service routines we must supply to libthread_db */
struct lwp_map
{
struct lwp_map *next;
pid_t pid;
lwpid_t lwp;
int lwpfd;
};
/* The next four routines are called by thread_db to tell us to stop and stop
a particular process or lwp. Since GDB ensures that these are all stopped
by the time we call anything in thread_db, these routines need to do
nothing. */
ps_err_e
ps_pstop (const struct ps_prochandle *ph)
@ -756,6 +840,8 @@ ps_pglobal_lookup (const struct ps_prochandle *ph, const char *ld_object_name,
return PS_OK;
}
/* Common routine for reading and writing memory. */
static ps_err_e
rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
char *buf, int size)
@ -817,6 +903,8 @@ ps_ptwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
return rw_common (1, ph, addr, buf, size);
}
/* Get integer regs */
ps_err_e
ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
prgregset_t gregset)
@ -835,6 +923,8 @@ ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
return PS_OK;
}
/* Set integer regs */
ps_err_e
ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
const prgregset_t gregset)
@ -863,6 +953,8 @@ ps_plog (const char *fmt, ...)
vfprintf_filtered (gdb_stderr, fmt, args);
}
/* Get size of extra register set. Currently a noop. */
ps_err_e
ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
{
@ -889,6 +981,8 @@ ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
return PS_OK;
}
/* Get extra register set. Currently a noop. */
ps_err_e
ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
{
@ -910,6 +1004,8 @@ ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
return PS_OK;
}
/* Set extra register set. Currently a noop. */
ps_err_e
ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
{
@ -931,6 +1027,8 @@ ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
return PS_OK;
}
/* Get floating-point regs. */
ps_err_e
ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
prfpregset_t *fpregset)
@ -949,6 +1047,8 @@ ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
return PS_OK;
}
/* Set floating-point regs. */
ps_err_e
ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
const prfpregset_t *fpregset)
@ -967,6 +1067,8 @@ ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
return PS_OK;
}
/* Convert a pid to printable form. */
char *
solaris_pid_to_str (pid)
int pid;