path: root/sys/sys
diff options
authorDavid Xu <davidxu@FreeBSD.org>2004-07-13 07:20:10 +0000
committerDavid Xu <davidxu@FreeBSD.org>2004-07-13 07:20:10 +0000
commitcbf4e354ec2e443527cf031282f960cd0fd1a7ad (patch)
tree7b594e9c78fb4c5b7c6d232be655c25bb67cc072 /sys/sys
parentd83ed0fac0cc10daabc3198fde20003ff486daf9 (diff)
Add code to support debugging threaded process.
1. Add tm_lwpid into kse_thr_mailbox to indicate which kernel thread current user thread is running on. Add tm_dflags into kse_thr_mailbox, the flags is written by debugger, it tells UTS and kernel what should be done when the process is being debugged, current, there two flags TMDF_SSTEP and TMDF_DONOTRUNUSER. TMDF_SSTEP is used to tell kernel to turn on single stepping, or turn off if it is not set. TMDF_DONOTRUNUSER is used to tell kernel to schedule upcall whenever possible, to UTS, it means do not run the user thread until debugger clears it, this behaviour is necessary because gdb wants to resume only one thread when the thread's pc is at a breakpoint, and thread needs to go forward, in order to avoid other threads sneak pass the breakpoints, it needs to remove breakpoint, only wants one thread to go. Also, add km_lwp to kse_mailbox, the lwp id is copied to kse_thr_mailbox at context switch time when process is not being debugged, so when process is attached, debugger can map kernel thread to user thread. 2. Add p_xthread to proc strcuture and td_xsig to thread structure. p_xthread is used by a thread when it wants to report event to debugger, every thread can set the pointer, especially, when it is used in ptracestop, it is the last thread reporting event will win the race. Every thread has a td_xsig to exchange signal with debugger, thread uses TDF_XSIG flag to indicate it is reporting signal to debugger, if the flag is not cleared, thread will keep retrying until it is cleared by debugger, p_xthread may be used by debugger to indicate CURRENT thread. The p_xstat is still in proc structure to keep wait() to work, in future, we may just use td_xsig. 3. Add TDF_DBSUSPEND flag, the flag is used by debugger to suspend a thread. When process stops, debugger can set the flag for thread, thread will check the flag in thread_suspend_check, enters a loop, unless it is cleared by debugger, process is detached or process is existing. The flag is also checked in ptracestop, so debugger can temporarily suspend a thread even if the thread wants to exchange signal. 4. Current, in ptrace, we always resume all threads, but if a thread has already a TDF_DBSUSPEND flag set by debugger, it won't run. Encouraged by: marcel, julian, deischen
Notes: svn path=/head/; revision=132087
Diffstat (limited to 'sys/sys')
3 files changed, 37 insertions, 24 deletions
diff --git a/sys/sys/kse.h b/sys/sys/kse.h
index 2d02eb788395..a0a2752a2503 100644
--- a/sys/sys/kse.h
+++ b/sys/sys/kse.h
@@ -54,13 +54,15 @@ typedef void kse_func_t(struct kse_mailbox *);
struct kse_thr_mailbox {
ucontext_t tm_context; /* User and machine context */
- unsigned int tm_flags; /* Thread flags */
+ uint32_t tm_flags; /* Thread flags */
struct kse_thr_mailbox *tm_next; /* Next thread in list */
void *tm_udata; /* For use by the UTS */
- uint32_t tm_uticks;
- uint32_t tm_sticks;
+ uint32_t tm_uticks; /* Time in userland */
+ uint32_t tm_sticks; /* Time in kernel */
siginfo_t tm_syncsig;
- int tm_spare[8];
+ uint32_t tm_dflags; /* Debug flags */
+ lwpid_t tm_lwp; /* kernel thread UTS runs on */
+ uint32_t __spare__[6];
@@ -70,40 +72,48 @@ struct kse_thr_mailbox {
* a single KSE.
struct kse_mailbox {
- int km_version; /* Mailbox version */
+ uint32_t km_version; /* Mailbox version */
struct kse_thr_mailbox *km_curthread; /* Currently running thread */
struct kse_thr_mailbox *km_completed; /* Threads back from kernel */
sigset_t km_sigscaught; /* Caught signals */
- uint32_t km_flags; /* KSE flags */
+ uint32_t km_flags; /* Mailbox flags */
kse_func_t *km_func; /* UTS function */
- stack_t km_stack; /* UTS context */
+ stack_t km_stack; /* UTS stack */
void *km_udata; /* For use by the UTS */
struct timespec km_timeofday; /* Time of day */
- int km_quantum; /* Upcall quantum in msecs */
- int km_spare[8];
+ uint32_t km_quantum; /* Upcall quantum in msecs */
+ lwpid_t km_lwp; /* kernel thread UTS runs on */
+ uint32_t __spare2__[7];
-#define KSE_VER_0 0
+#define KSE_VER_0 0
/* These flags are kept in km_flags */
-#define KMF_NOUPCALL 0x01
-#define KMF_NOCOMPLETED 0x02
-#define KMF_DONE 0x04
-#define KMF_BOUND 0x08
-#define KMF_WAITSIGEVENT 0x10
+#define KMF_NOUPCALL 0x01
+#define KMF_NOCOMPLETED 0x02
+#define KMF_DONE 0x04
+#define KMF_BOUND 0x08
+#define KMF_WAITSIGEVENT 0x10
/* These flags are kept in tm_flags */
-#define TMF_NOUPCALL 0x01
+#define TMF_NOUPCALL 0x01
+/* These flags are kept in tm_dlfags */
+#define TMDF_SSTEP 0x01
+/* Flags for kse_switchin */
/* Flags for kse_switchin */
/* Commands for kse_thr_interrupt */
-#define KSE_INTR_INTERRUPT 0x01
-#define KSE_INTR_RESTART 0x02
-#define KSE_INTR_SENDSIG 0x03
-#define KSE_INTR_SIGEXIT 0x04
+#define KSE_INTR_INTERRUPT 0x01
+#define KSE_INTR_RESTART 0x02
+#define KSE_INTR_SENDSIG 0x03
+#define KSE_INTR_SIGEXIT 0x04
#ifndef _KERNEL
int kse_create(struct kse_mailbox *, int);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index bf3c78846a76..0a15daf6605d 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -303,7 +303,7 @@ struct thread {
volatile u_int td_generation; /* (k) Enable detection of preemption */
stack_t td_sigstk; /* (k) Stack ptr and on-stack flag. */
int td_kflags; /* (c) Flags for KSE threading. */
+ int td_xsig; /* (c) Signal for ptrace */
#define td_endzero td_base_pri
/* Copied during fork1() or thread_sched_upcall(). */
@@ -354,8 +354,10 @@ struct thread {
#define TDF_OWEUPC 0x008000 /* Owe thread an addupc() call at next AST. */
#define TDF_NEEDRESCHED 0x010000 /* Thread needs to yield. */
#define TDF_NEEDSIGCHK 0x020000 /* Thread may need signal delivery. */
+#define TDF_XSIG 0x040000 /* Thread is exchanging signal under traced */
#define TDF_UMTXWAKEUP 0x080000 /* Libthr thread must not sleep on a umtx. */
#define TDF_THRWAKEUP 0x100000 /* Libthr thread must not suspend itself. */
+#define TDF_DBSUSPEND 0x200000 /* Thread is suspended by debugger */
/* "Private" flags kept in td_pflags: */
#define TDP_OLDMASK 0x0001 /* Need to restore mask after suspend. */
@@ -586,6 +588,7 @@ struct proc {
void *p_aioinfo; /* (?) ASYNC I/O info. */
struct thread *p_singlethread;/* (c + j) If single threading this is it */
int p_suspcount; /* (c) # threads in suspended mode */
+ struct thread *p_xthread; /* (c) Trap thread */
/* End area that is zeroed on creation. */
#define p_endzero p_magic
@@ -602,7 +605,6 @@ struct proc {
#define p_endcopy p_xstat
u_short p_xstat; /* (c) Exit status; also stop sig. */
- lwpid_t p_xlwpid; /* (c) Thread corresponding p_xstat. */
int p_numthreads; /* (j) Number of threads. */
int p_numksegrps; /* (?) number of ksegrps */
struct mdproc p_md; /* Any machine-dependent fields. */
@@ -937,6 +939,7 @@ void upcall_stash(struct kse_upcall *ke);
void thread_sanity_check(struct thread *td, char *);
void thread_stopped(struct proc *p);
void thread_switchout(struct thread *td);
+void thread_continued(struct proc *p);
void thr_exit1(void);
#endif /* _KERNEL */
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 1fa4b86cfbba..83301c81eb5b 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -271,7 +271,7 @@ void siginit(struct proc *p);
void signotify(struct thread *td);
void tdsignal(struct thread *td, int sig, sigtarget_t target);
void trapsignal(struct thread *td, int sig, u_long code);
-void ptracestop(struct thread *td, int sig);
+int ptracestop(struct thread *td, int sig);
* Machine-dependent functions: