Skip to content

Commit

Permalink
* init.c (__nptl_initial_report_events): New variable.
Browse files Browse the repository at this point in the history
	(__pthread_initialize_minimal_internal): Initialize pd->report_events
	to that.
  • Loading branch information
Roland McGrath committed Jun 26, 2007
1 parent 0ecf9c1 commit 7d9d8bd
Show file tree
Hide file tree
Showing 15 changed files with 223 additions and 86 deletions.
6 changes: 6 additions & 0 deletions nptl/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2007-05-16 Roland McGrath <roland@redhat.com>

* init.c (__nptl_initial_report_events): New variable.
(__pthread_initialize_minimal_internal): Initialize pd->report_events
to that.

2007-06-22 Jakub Jelinek <jakub@redhat.com>

* pthread_getattr_np.c (pthread_getattr_np): Clear cpuset and
Expand Down
23 changes: 23 additions & 0 deletions nptl_db/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
2007-05-16 Roland McGrath <roland@redhat.com>

* td_thr_get_info.c: Fake the results for TH->th_unique == 0.
* td_thr_validate.c: Likewise.
* td_thr_setgregs.c: Likewise.
* td_thr_setfpregs.c: Likewise.
* td_thr_getgregs.c: Likewise.
* td_thr_getfpregs.c: Likewise.
* td_thr_tlsbase.c: Likewise.

* structs.def: Add DB_VARIABLE (__nptl_initial_report_events).
* db_info.c: Add necessary declaration.
* td_thr_event_enable.c: Set __nptl_initial_report_events too.

* td_ta_thr_iter.c (iterate_thread_list): Make FAKE_EMPTY bool.
Use th_unique=0 in fake descriptor before initialization.

* td_ta_map_lwp2thr.c (__td_ta_lookup_th_unique): New function, broken
out of ...
(td_ta_map_lwp2thr): ... here, call it. But don't before __stack_user
is initialized, then fake a handle with th_unique=0.
* thread_dbP.h: Declare it.

2006-10-26 Pete Eberlein <eberlein@us.ibm.com>

* nptl_db/db_info.c [TLS_DTV_AT_TP]: Fixed size init for dtvp
Expand Down
4 changes: 3 additions & 1 deletion nptl_db/db_info.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* This file is included by pthread_create.c to define in libpthread
all the magic symbols required by libthread_db.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
Expand Down Expand Up @@ -38,6 +38,8 @@ typedef struct

typedef struct link_map link_map;

/* Actually static in nptl/init.c, but we only need it for typeof. */
extern bool __nptl_initial_report_events;

#define schedparam_sched_priority schedparam.sched_priority

Expand Down
3 changes: 2 additions & 1 deletion nptl_db/structs.def
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* List of types and symbols in libpthread examined by libthread_db.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.

The GNU C Library is free software; you can redistribute it and/or
Expand Down Expand Up @@ -56,6 +56,7 @@ DB_FUNCTION (__nptl_death_event)
DB_SYMBOL (__nptl_threads_events)
DB_VARIABLE (__nptl_nthreads)
DB_VARIABLE (__nptl_last_event)
DB_VARIABLE (__nptl_initial_report_events)

DB_ARRAY_VARIABLE (__pthread_keys)
DB_STRUCT (pthread_key_struct)
Expand Down
69 changes: 50 additions & 19 deletions nptl_db/td_ta_map_lwp2thr.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Which thread is running on an LWP?
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
Expand All @@ -24,8 +24,8 @@


td_err_e
td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
lwpid_t lwpid, td_thrhandle_t *th)
__td_ta_lookup_th_unique (const td_thragent_t *ta_arg,
lwpid_t lwpid, td_thrhandle_t *th)
{
td_thragent_t *const ta = (td_thragent_t *) ta_arg;
ps_err_e err;
Expand Down Expand Up @@ -118,9 +118,6 @@ td_ta_map_lwp2thr (const td_thragent_t *ta_arg,

switch (ta->ta_howto)
{
case ta_howto_unknown:
return TD_DBERR;

default:
return TD_DBERR;

Expand All @@ -132,6 +129,7 @@ td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
0, regs, &addr);
if (terr != TD_OK)
return terr;

/* In this descriptor the nelem word is overloaded as the bias. */
addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg);
th->th_unique = addr;
Expand All @@ -143,22 +141,22 @@ td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
if (&ps_get_thread_area == NULL)
return TD_NOCAPAB;

/* A la x86-64, there is a constant magic index for get_thread_area. */
if (ps_get_thread_area (ta->ph, lwpid,
ta->ta_howto_data.const_thread_area,
&th->th_unique) != PS_OK)
return TD_ERR; /* XXX Other error value? */
break;
/* A la x86-64, there is a magic index for get_thread_area. */
if (ps_get_thread_area (ta->ph, lwpid,
ta->ta_howto_data.const_thread_area,
&th->th_unique) != PS_OK)
return TD_ERR; /* XXX Other error value? */
break;

case ta_howto_reg_thread_area:
case ta_howto_reg_thread_area:
if (&ps_get_thread_area == NULL)
return TD_NOCAPAB;

/* A la i386, there is a register with an index for get_thread_area. */
if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
return TD_ERR;
terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area, -1,
0, regs, &addr);
/* A la i386, a register holds the index for get_thread_area. */
if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
return TD_ERR;
terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area,
-1, 0, regs, &addr);
if (terr != TD_OK)
return terr;
/* In this descriptor the nelem word is overloaded as scale factor. */
Expand All @@ -172,7 +170,40 @@ td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
}

/* Found it. Now complete the `td_thrhandle_t' object. */
th->th_ta_p = (td_thragent_t *) ta;
th->th_ta_p = ta;

return TD_OK;
}

td_err_e
td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
lwpid_t lwpid, td_thrhandle_t *th)
{
td_thragent_t *const ta = (td_thragent_t *) ta_arg;

/* We cannot rely on thread registers and such information at all
before __pthread_initialize_minimal has gotten far enough. They
sometimes contain garbage that would confuse us, left by the kernel
at exec. So if it looks like initialization is incomplete, we only
fake a special descriptor for the initial thread. */

psaddr_t list;
td_err_e err = DB_GET_SYMBOL (list, ta, __stack_user);
if (err != TD_OK)
return err;

err = DB_GET_FIELD (list, ta, list, list_t, next, 0);
if (err != TD_OK)
return err;

if (list == 0)
{
if (ps_getpid (ta->ph) != lwpid)
return TD_ERR;
th->th_ta_p = ta;
th->th_unique = 0;
return TD_OK;
}

return __td_ta_lookup_th_unique (ta_arg, lwpid, th);
}
25 changes: 14 additions & 11 deletions nptl_db/td_ta_thr_iter.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* Iterate over a process's threads.
Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
Copyright (C) 1999,2000,2001,2002,2003,2004,2007
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
Expand All @@ -24,7 +25,7 @@
static td_err_e
iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
void *cbdata_p, td_thr_state_e state, int ti_pri,
psaddr_t head, int fake_empty)
psaddr_t head, bool fake_empty)
{
td_err_e err;
psaddr_t next, ofs;
Expand All @@ -41,13 +42,13 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,

if (next == 0 && fake_empty)
{
/* __pthread_initialize_minimal has not run.
There is just the main thread to return. */
td_thrhandle_t th;
err = td_ta_map_lwp2thr (ta, ps_getpid (ta->ph), &th);
if (err == TD_OK)
err = callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
return err;
/* __pthread_initialize_minimal has not run. There is just the main
thread to return. We cannot rely on its thread register. They
sometimes contain garbage that would confuse us, left by the
kernel at exec. So if it looks like initialization is incomplete,
we only fake a special descriptor for the initial thread. */
td_thrhandle_t th = { ta, 0 };
return callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
}

/* Cache the offset from struct pthread to its list_t member. */
Expand Down Expand Up @@ -136,13 +137,15 @@ td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback,

err = DB_GET_SYMBOL (list, ta, __stack_user);
if (err == TD_OK)
err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 1);
err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
list, true);

/* And the threads with stacks allocated by the implementation. */
if (err == TD_OK)
err = DB_GET_SYMBOL (list, ta, stack_used);
if (err == TD_OK)
err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 0);
err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
list, false);

return err;
}
24 changes: 21 additions & 3 deletions nptl_db/td_thr_event_enable.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Enable event process-wide.
Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 1999, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
Expand Down Expand Up @@ -28,7 +28,25 @@ td_thr_event_enable (th, onoff)
{
LOG ("td_thr_event_enable");

/* Write the new value into the thread data structure. */
return DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread, report_events, 0,
if (th->th_unique != 0)
{
/* Write the new value into the thread data structure. */
td_err_e err = DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread,
report_events, 0,
(psaddr_t) 0 + (onoff != 0));
if (err != TD_OK)
return err;

/* Just in case we are in the window between initializing __stack_user
and copying from __nptl_initial_report_events, we set it too.
It doesn't hurt to do this for non-initial threads, since it
won't be consulted again anyway. It would take another fetch
to get the tid and determine this isn't the initial thread,
so just do it always. */
}

/* We are faking it for the initial thread before its thread
descriptor is set up. */
return DB_PUT_VALUE (th->th_ta_p, __nptl_initial_report_events, 0,
(psaddr_t) 0 + (onoff != 0));
}
81 changes: 48 additions & 33 deletions nptl_db/td_thr_get_info.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Get thread information.
Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 1999,2000,2001,2002,2003,2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
Expand Down Expand Up @@ -32,35 +32,49 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)

LOG ("td_thr_get_info");

/* Copy the whole descriptor in once so we can access the several
fields locally. Excess copying in one go is much better than
multiple ps_pdread calls. */
err = DB_GET_STRUCT (copy, th->th_ta_p, th->th_unique, pthread);
if (err != TD_OK)
return err;

err = DB_GET_FIELD_ADDRESS (tls, th->th_ta_p, th->th_unique,
pthread, specific, 0);
if (err != TD_OK)
return err;

err = DB_GET_FIELD_LOCAL (schedpolicy, th->th_ta_p, copy, pthread,
schedpolicy, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (schedprio, th->th_ta_p, copy, pthread,
schedparam_sched_priority, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (tid, th->th_ta_p, copy, pthread, tid, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (cancelhandling, th->th_ta_p, copy, pthread,
cancelhandling, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread,
report_events, 0);
if (th->th_unique == 0)
{
/* Special case for the main thread before initialization. */
copy = NULL;
tls = 0;
cancelhandling = 0;
schedprio = 0;
tid = 0;
err = DB_GET_VALUE (report_events, th->th_ta_p,
__nptl_initial_report_events, 0);
}
else
{
/* Copy the whole descriptor in once so we can access the several
fields locally. Excess copying in one go is much better than
multiple ps_pdread calls. */
err = DB_GET_STRUCT (copy, th->th_ta_p, th->th_unique, pthread);
if (err != TD_OK)
return err;

err = DB_GET_FIELD_ADDRESS (tls, th->th_ta_p, th->th_unique,
pthread, specific, 0);
if (err != TD_OK)
return err;

err = DB_GET_FIELD_LOCAL (schedpolicy, th->th_ta_p, copy, pthread,
schedpolicy, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (schedprio, th->th_ta_p, copy, pthread,
schedparam_sched_priority, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (tid, th->th_ta_p, copy, pthread, tid, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (cancelhandling, th->th_ta_p, copy, pthread,
cancelhandling, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread,
report_events, 0);
}
if (err != TD_OK)
return err;

Expand All @@ -87,9 +101,10 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
infop->ti_lid = tid == 0 ? ps_getpid (th->th_ta_p->ph) : (uintptr_t) tid;
infop->ti_traceme = report_events != 0;

err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread,
start_routine, 0);
if (err == TD_OK)
if (copy != NULL)
err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread,
start_routine, 0);
if (copy != NULL && err == TD_OK)
{
uint32_t idx;
for (idx = 0; idx < TD_EVENTSIZE; ++idx)
Expand Down
7 changes: 6 additions & 1 deletion nptl_db/td_thr_getfpregs.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Get a thread's floating-point register set.
Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 1999, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
Expand Down Expand Up @@ -29,6 +29,11 @@ td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset)

LOG ("td_thr_getfpregs");

if (th->th_unique == 0)
/* Special case for the main thread before initialization. */
return ps_lgetfpregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
regset) != PS_OK ? TD_ERR : TD_OK;

/* We have to get the state and the PID for this thread. */
err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
cancelhandling, 0);
Expand Down
Loading

0 comments on commit 7d9d8bd

Please sign in to comment.