summaryrefslogtreecommitdiffstats
path: root/lib/libthread_db
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2004-08-08 22:37:53 +0000
committerdavidxu <davidxu@FreeBSD.org>2004-08-08 22:37:53 +0000
commitd29ded002bcddf2cd1977bb8d7ccb65487590ee8 (patch)
treeef2fbec2f4813f6b13a05ff5f301e393a7edfaf1 /lib/libthread_db
parent634d20a05ea861318018f78b9103d3f57baf97f4 (diff)
downloadFreeBSD-src-d29ded002bcddf2cd1977bb8d7ccb65487590ee8.zip
FreeBSD-src-d29ded002bcddf2cd1977bb8d7ccb65487590ee8.tar.gz
1.Use new way to check if a thread is in critical region, defer suspending
if it is true. 2.Add thread_db api td_thr_tls_get_addr to get tls address, the real code is commented out util tls patch is committed. Reviewed by: deischen
Diffstat (limited to 'lib/libthread_db')
-rw-r--r--lib/libthread_db/Makefile8
-rw-r--r--lib/libthread_db/libpthread_db.c139
-rw-r--r--lib/libthread_db/thread_db.c8
-rw-r--r--lib/libthread_db/thread_db.h1
-rw-r--r--lib/libthread_db/thread_db_int.h2
5 files changed, 126 insertions, 32 deletions
diff --git a/lib/libthread_db/Makefile b/lib/libthread_db/Makefile
index c94636b..bf8e338 100644
--- a/lib/libthread_db/Makefile
+++ b/lib/libthread_db/Makefile
@@ -11,7 +11,13 @@ SRCS+= libthr_db.c
INCS= thread_db.h
WARNS?= 1
-CFLAGS+=-I. -I${.CURDIR}
+CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../../libexec/rtld-elf
+CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf/${MACHINE_ARCH}
+.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
+CFLAGS+=-DTLS_DTV_AT_TCB
+.else
+CFLAGS+=-DTLS_DTV_AT_TP
+.endif
SRCS+= libpthread.h
CLEANFILES+= libpthread.h
diff --git a/lib/libthread_db/libpthread_db.c b/lib/libthread_db/libpthread_db.c
index c5ef5ce..239b846 100644
--- a/lib/libthread_db/libpthread_db.c
+++ b/lib/libthread_db/libpthread_db.c
@@ -27,6 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <link.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@@ -38,6 +39,8 @@ __FBSDID("$FreeBSD$");
#include <proc_service.h>
#include <thread_db.h>
+#include "rtld.h"
+
#include "libpthread.h"
#include "libpthread_db.h"
@@ -413,8 +416,7 @@ pt_dbsuspend(const td_thrhandle_t *th, int suspend)
psaddr_t tcb_addr, tmbx_addr, ptr;
lwpid_t lwp;
uint32_t dflags;
- int attrflags;
- int ret;
+ int attrflags, locklevel, ret;
TDBG_FUNC();
@@ -445,40 +447,57 @@ pt_dbsuspend(const td_thrhandle_t *th, int suspend)
ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
if (ret != 0)
return (P2T(ret));
- /*
- * Don't stop lwp assigned to a M:N thread, it belongs
- * to UTS, UTS shouldn't be stopped.
- */
- if (lwp != 0 && (attrflags & PTHREAD_SCOPE_SYSTEM)) {
- /* dont' suspend signal thread */
+
+ if (lwp != 0) {
+ /* don't suspend signal thread */
if (attrflags & THR_SIGNAL_THREAD)
- return 0;
- ptr = ta->map[th->th_tid].thr +
- offsetof(struct pthread, kse);
- /* Too many indirect level :-( */
- /* read struct kse * */
- ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr));
- if (ret != 0)
- return (P2T(ret));
- ptr = ptr + offsetof(struct kse, k_kcb);
- /* read k_kcb * */
- ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr));
- if (ret != 0)
- return (P2T(ret));
- /* read kcb.kcb_kmbx.km_curthread */
- ptr = ptr + offsetof(struct kcb, kcb_kmbx.km_curthread);
- ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr));
- if (ret != 0)
- return (P2T(ret));
- if (ptr != 0) { /* not in critical */
- if (suspend)
- ret = ps_lstop(ta->ph, lwp);
- else
+ return (0);
+ if (attrflags & PTHREAD_SCOPE_SYSTEM) {
+ /*
+ * don't suspend system scope thread if it is holding
+ * some low level locks
+ */
+ ptr = ta->map[th->th_tid].thr +
+ offsetof(struct pthread, kse);
+ ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr));
+ if (ret != 0)
+ return (P2T(ret));
+ ret = ps_pread(ta->ph, ptr + offsetof(struct kse,
+ k_locklevel), &locklevel, sizeof(int));
+ if (ret != 0)
+ return (P2T(ret));
+ if (locklevel <= 0) {
+ ptr = ta->map[th->th_tid].thr +
+ offsetof(struct pthread, locklevel);
+ ret = ps_pread(ta->ph, ptr, &locklevel,
+ sizeof(int));
+ if (ret != 0)
+ return (P2T(ret));
+ }
+ if (suspend) {
+ if (locklevel <= 0)
+ ret = ps_lstop(ta->ph, lwp);
+ } else {
ret = ps_lcontinue(ta->ph, lwp);
+ }
if (ret != 0)
return (P2T(ret));
+ /* FALLTHROUGH */
+ } else {
+ struct ptrace_lwpinfo pl;
+
+ if (ptrace(PT_LWPINFO, lwp, (caddr_t) &pl, sizeof(pl)))
+ return (TD_ERR);
+ if (suspend) {
+ if (!(pl.pl_flags & PL_FLAG_BOUND))
+ ret = ps_lstop(ta->ph, lwp);
+ } else {
+ ret = ps_lcontinue(ta->ph, lwp);
+ }
+ if (ret != 0)
+ return (P2T(ret));
+ /* FALLTHROUGH */
}
- /* FALLTHROUGH */
}
/* read tm_dflags */
ret = ps_pread(ta->ph,
@@ -899,6 +918,63 @@ pt_validate(const td_thrhandle_t *th)
return (TD_OK);
}
+td_err_e
+pt_thr_tls_get_addr(const td_thrhandle_t *th, void *_linkmap, size_t offset,
+ void **address)
+{
+#if 0
+ Obj_Entry *obj_entry;
+ const td_thragent_t *ta = th->th_ta;
+ psaddr_t tcb_addr, *dtv_addr, tcb_tp;
+ int tls_index, ret;
+
+ /* linkmap is a member of Obj_Entry */
+ obj_entry = (Obj_Entry *)
+ (((char *)_linkmap) - offsetof(Obj_Entry, linkmap));
+
+ /* get tlsindex of the object file */
+ ret = ps_pread(ta->ph,
+ ((char *)obj_entry) + offsetof(Obj_Entry, tlsindex),
+ &tls_index, sizeof(tls_index));
+ if (ret != 0)
+ return (P2T(ret));
+
+ /* get thread tcb */
+ ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
+ offsetof(struct pthread, tcb),
+ &tcb_addr, sizeof(tcb_addr));
+ if (ret != 0)
+ return (P2T(ret));
+
+#ifdef TLS_DTV_AT_TCB
+ /* get dtv array address */
+ ret = ps_pread(ta->ph, tcb_addr + offsetof(struct tcb, tcb_dtv),
+ &dtv_addr, sizeof(dtv_addr));
+ if (ret != 0)
+ return (P2T(ret));
+#else
+ #ifdef TLS_DTV_AT_TP
+ ret = ps_pread(ta->ph, tcb_addr + offsetof(struct tcb, tcb_tp),
+ &tcb_tp, sizeof(tcb_tp));
+ if (ret != 0)
+ return (P2T(ret));
+ ret = ps_pread(ta->ph, tcb_tp + offsetof(struct tp, tp_dtv),
+ &dtv_addr, sizeof(dtv_addr));
+ #else
+ #error "Either TLS_DTV_AT_TP or TLS_DTV_AT_TCB must be defined."
+ #endif
+#endif
+ /* now get the object's tls block base address */
+ ret = ps_pread(ta->ph, &dtv_addr[tls_index+1], address,
+ sizeof(*address));
+ if (ret != 0)
+ return (P2T(ret));
+
+ *address += offset;
+#endif
+ return (TD_OK);
+}
+
struct ta_ops libpthread_db_ops = {
.to_init = pt_init,
.to_ta_clear_event = pt_ta_clear_event,
@@ -923,6 +999,7 @@ struct ta_ops libpthread_db_ops = {
.to_thr_setfpregs = pt_thr_setfpregs,
.to_thr_setgregs = pt_thr_setgregs,
.to_thr_validate = pt_thr_validate,
+ .to_thr_tls_get_addr = pt_thr_tls_get_addr,
/* FreeBSD specific extensions. */
.to_thr_sstep = pt_thr_sstep,
diff --git a/lib/libthread_db/thread_db.c b/lib/libthread_db/thread_db.c
index e92d4ff..b1b1bcc 100644
--- a/lib/libthread_db/thread_db.c
+++ b/lib/libthread_db/thread_db.c
@@ -226,6 +226,14 @@ td_thr_validate(const td_thrhandle_t *th)
return (ta->ta_ops->to_thr_validate(th));
}
+td_err_e
+td_thr_tls_get_addr(const td_thrhandle_t *th, void *linkmap, size_t offset,
+ void **address)
+{
+ const td_thragent_t *ta = th->th_ta;
+ return (ta->ta_ops->to_thr_tls_get_addr(th, linkmap, offset, address));
+}
+
/* FreeBSD specific extensions. */
td_err_e
diff --git a/lib/libthread_db/thread_db.h b/lib/libthread_db/thread_db.h
index eaad921..8827dd6 100644
--- a/lib/libthread_db/thread_db.h
+++ b/lib/libthread_db/thread_db.h
@@ -231,6 +231,7 @@ td_err_e td_thr_set_event(const td_thrhandle_t *, td_thr_events_t *);
td_err_e td_thr_setfpregs(const td_thrhandle_t *, const prfpregset_t *);
td_err_e td_thr_setgregs(const td_thrhandle_t *, const prgregset_t);
td_err_e td_thr_validate(const td_thrhandle_t *);
+td_err_e td_thr_tls_get_addr(const td_thrhandle_t *, void *, size_t, void **);
/* FreeBSD specific extensions. */
td_err_e td_thr_sstep(const td_thrhandle_t *, int);
diff --git a/lib/libthread_db/thread_db_int.h b/lib/libthread_db/thread_db_int.h
index 1b56251..7dc152c 100644
--- a/lib/libthread_db/thread_db_int.h
+++ b/lib/libthread_db/thread_db_int.h
@@ -74,6 +74,8 @@ struct ta_ops {
const prfpregset_t *);
td_err_e (*to_thr_setgregs)(const td_thrhandle_t *, const prgregset_t);
td_err_e (*to_thr_validate)(const td_thrhandle_t *);
+ td_err_e (*to_thr_tls_get_addr)(const td_thrhandle_t *,
+ void *, size_t, void **);
/* FreeBSD specific extensions. */
td_err_e (*to_thr_sstep)(const td_thrhandle_t *, int);
OpenPOWER on IntegriCloud