aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/amd64/db_trace.c
diff options
context:
space:
mode:
authorJulian Elischer <julian@FreeBSD.org>2002-12-28 01:23:07 +0000
committerJulian Elischer <julian@FreeBSD.org>2002-12-28 01:23:07 +0000
commit93a7aa79d628bf2b11ed75cba6fc1d904e3a4dd4 (patch)
tree34088f29c02f6a4d56466e7db0deb792a033cebc /sys/amd64/amd64/db_trace.c
parent84cdcd85a03610d9a3113fbbc3a89da4e4298246 (diff)
downloadsrc-93a7aa79d628bf2b11ed75cba6fc1d904e3a4dd4.tar.gz
src-93a7aa79d628bf2b11ed75cba6fc1d904e3a4dd4.zip
Add code to ddb to allow backtracing an arbitrary thread.
(show thread {address}) Remove the IDLE kse state and replace it with a change in the way threads sahre KSEs. Every KSE now has a thread, which is considered its "owner" however a KSE may also be lent to other threads in the same group to allow completion of in-kernel work. n this case the owner remains the same and the KSE will revert to the owner when the other work has been completed. All creations of upcalls etc. is now done from kse_reassign() which in turn is called from mi_switch or thread_exit(). This means that special code can be removed from msleep() and cv_wait(). kse_release() does not leave a KSE with no thread any more but converts the existing thread into teh KSE's owner, and sets it up for doing an upcall. It is just inhibitted from being scheduled until there is some reason to do an upcall. Remove all trace of the kse_idle queue since it is no-longer needed. "Idle" KSEs are now on the loanable queue.
Notes
Notes: svn path=/head/; revision=108338
Diffstat (limited to 'sys/amd64/amd64/db_trace.c')
-rw-r--r--sys/amd64/amd64/db_trace.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index 1134964f9f4e..f0e046481e62 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -107,6 +107,8 @@ static void db_nextframe(struct i386_frame **, db_addr_t *, struct proc *);
static int db_numargs(struct i386_frame *);
static void db_print_stack_entry(const char *, int, char **, int *, db_addr_t);
static void decode_syscall(int, struct proc *);
+static void db_trace_one_stack(int count, boolean_t have_addr,
+ struct proc *p, struct i386_frame *frame, db_addr_t callpc);
static char * watchtype_str(int type);
@@ -284,14 +286,12 @@ db_stack_trace_cmd(addr, have_addr, count, modif)
db_expr_t count;
char *modif;
{
- int *argp;
struct i386_frame *frame;
struct proc *p;
struct pcb *pcb;
struct thread *td;
db_addr_t callpc;
pid_t pid;
- boolean_t first;
if (count == -1)
count = 1024;
@@ -348,6 +348,54 @@ db_stack_trace_cmd(addr, have_addr, count, modif)
callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
frame = frame->f_frame;
}
+ db_trace_one_stack(count, have_addr, p, frame, callpc);
+}
+
+void
+db_stack_thread(db_expr_t addr, boolean_t have_addr,
+ db_expr_t count, char *modif)
+{
+ struct i386_frame *frame;
+ struct thread *td;
+ struct proc *p;
+ struct pcb *pcb;
+ db_addr_t callpc;
+
+ if (!have_addr)
+ return;
+ if (!INKERNEL(addr)) {
+ printf("bad thread address");
+ return;
+ }
+ td = (struct thread *)addr;
+ /* quick sanity check */
+ if ((p = td->td_proc) != td->td_ksegrp->kg_proc)
+ return;
+ if (TD_IS_SWAPPED(td)) {
+ db_printf("thread at %p swapped out\n", td);
+ return;
+ }
+ if (td == curthread) {
+ frame = (struct i386_frame *)ddb_regs.tf_ebp;
+ if (frame == NULL)
+ frame = (struct i386_frame *)(ddb_regs.tf_esp - 4);
+ callpc = (db_addr_t)ddb_regs.tf_eip;
+ } else {
+ pcb = td->td_pcb;
+ frame = (struct i386_frame *)pcb->pcb_ebp;
+ if (frame == NULL)
+ frame = (struct i386_frame *) (pcb->pcb_esp - 4);
+ callpc = (db_addr_t)pcb->pcb_eip;
+ }
+ db_trace_one_stack(count, have_addr, p, frame, callpc);
+}
+
+static void
+db_trace_one_stack(int count, boolean_t have_addr,
+ struct proc *p, struct i386_frame *frame, db_addr_t callpc)
+{
+ int *argp;
+ boolean_t first;
first = TRUE;
while (count--) {