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
This commit is contained in:
David Xu 2004-08-08 22:37:53 +00:00
parent 604be46d1e
commit 3e93cc3ae3
5 changed files with 127 additions and 33 deletions

View File

@ -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

View File

@ -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
ret = ps_lcontinue(ta->ph, lwp);
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,

View File

@ -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

View File

@ -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);

View File

@ -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);