[PATCH] init.c (__nptl_initial_report_events): New variable.

Sheng Yong shengyong1 at huawei.com
Tue May 5 01:19:18 UTC 2015


Ping.

On 4/28/2015 11:07 AM, Sheng Yong wrote:
> From: Roland McGrath <roland at gnu.org>
> 
> 	(__pthread_initialize_minimal_internal): Initialize pd->report_events
> 	to that.
> 
> This patch helps NPTL report TD_CREATE event, so that GDB could catch the
> event and update its thread_list.
> Link: http://lists.uclibc.org/pipermail/uclibc/2015-April/048921.html
> [shengyong:
>  - original patch from glibc: commit 7d9d8bd18906fdd17364f372b160d7ab896ce909
>  - context adjust
>  - update nptl_db/ChangeLog]
> Signed-off-by: Sheng Yong <shengyong1 at huawei.com>
> ---
>  libpthread/nptl_db/ChangeLog             | 23 +++++++++
>  libpthread/nptl_db/db_info.c             |  4 +-
>  libpthread/nptl_db/structs.def           |  3 +-
>  libpthread/nptl_db/td_ta_map_lwp2thr.c   | 69 +++++++++++++++++++--------
>  libpthread/nptl_db/td_ta_thr_iter.c      | 25 +++++-----
>  libpthread/nptl_db/td_thr_event_enable.c | 24 ++++++++--
>  libpthread/nptl_db/td_thr_get_info.c     | 81 +++++++++++++++++++-------------
>  libpthread/nptl_db/td_thr_getfpregs.c    |  7 ++-
>  libpthread/nptl_db/td_thr_getgregs.c     |  7 ++-
>  libpthread/nptl_db/td_thr_setfpregs.c    |  7 ++-
>  libpthread/nptl_db/td_thr_setgregs.c     |  7 ++-
>  libpthread/nptl_db/td_thr_tlsbase.c      | 25 +++++++++-
>  libpthread/nptl_db/td_thr_validate.c     | 16 ++-----
>  libpthread/nptl_db/thread_dbP.h          |  5 +-
>  14 files changed, 217 insertions(+), 86 deletions(-)
> 
> diff --git a/libpthread/nptl_db/ChangeLog b/libpthread/nptl_db/ChangeLog
> index 52c8491..92021cb 100644
> --- a/libpthread/nptl_db/ChangeLog
> +++ b/libpthread/nptl_db/ChangeLog
> @@ -1,3 +1,26 @@
> +2007-05-16  Roland McGrath  <roland at 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.
> +
>  2004-09-09  Roland McGrath  <roland at redhat.com>
> 
>  	* td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Don't abort if inferior's
> diff --git a/libpthread/nptl_db/db_info.c b/libpthread/nptl_db/db_info.c
> index 521ad78..a57a053 100644
> --- a/libpthread/nptl_db/db_info.c
> +++ b/libpthread/nptl_db/db_info.c
> @@ -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
> @@ -37,6 +37,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
> 
> diff --git a/libpthread/nptl_db/structs.def b/libpthread/nptl_db/structs.def
> index 915867b..bb571d4 100644
> --- a/libpthread/nptl_db/structs.def
> +++ b/libpthread/nptl_db/structs.def
> @@ -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
> @@ -55,6 +55,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)
> diff --git a/libpthread/nptl_db/td_ta_map_lwp2thr.c b/libpthread/nptl_db/td_ta_map_lwp2thr.c
> index 9709777..6b4382f 100644
> --- a/libpthread/nptl_db/td_ta_map_lwp2thr.c
> +++ b/libpthread/nptl_db/td_ta_map_lwp2thr.c
> @@ -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
> @@ -23,8 +23,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;
> @@ -117,9 +117,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;
> 
> @@ -131,6 +128,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;
> @@ -142,22 +140,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.  */
> @@ -171,7 +169,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);
> +}
> diff --git a/libpthread/nptl_db/td_ta_thr_iter.c b/libpthread/nptl_db/td_ta_thr_iter.c
> index 1fd02ef..0f1b2bf 100644
> --- a/libpthread/nptl_db/td_ta_thr_iter.c
> +++ b/libpthread/nptl_db/td_ta_thr_iter.c
> @@ -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 at redhat.com>, 1999.
> 
> @@ -23,7 +24,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;
> @@ -40,13 +41,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.  */
> @@ -135,13 +136,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;
>  }
> diff --git a/libpthread/nptl_db/td_thr_event_enable.c b/libpthread/nptl_db/td_thr_event_enable.c
> index f49682d..fd94580 100644
> --- a/libpthread/nptl_db/td_thr_event_enable.c
> +++ b/libpthread/nptl_db/td_thr_event_enable.c
> @@ -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 at redhat.com>, 1999.
> 
> @@ -25,7 +25,25 @@ td_thr_event_enable (const td_thrhandle_t *th, int 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));
>  }
> diff --git a/libpthread/nptl_db/td_thr_get_info.c b/libpthread/nptl_db/td_thr_get_info.c
> index 09d0d1a..27d5d70 100644
> --- a/libpthread/nptl_db/td_thr_get_info.c
> +++ b/libpthread/nptl_db/td_thr_get_info.c
> @@ -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 at redhat.com>, 1999.
> 
> @@ -31,35 +31,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;
> 
> @@ -86,9 +100,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)
> diff --git a/libpthread/nptl_db/td_thr_getfpregs.c b/libpthread/nptl_db/td_thr_getfpregs.c
> index ff4b599..4f4742a 100644
> --- a/libpthread/nptl_db/td_thr_getfpregs.c
> +++ b/libpthread/nptl_db/td_thr_getfpregs.c
> @@ -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 at redhat.com>, 1999.
> 
> @@ -28,6 +28,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);
> diff --git a/libpthread/nptl_db/td_thr_getgregs.c b/libpthread/nptl_db/td_thr_getgregs.c
> index 497941b..d5f0f61 100644
> --- a/libpthread/nptl_db/td_thr_getgregs.c
> +++ b/libpthread/nptl_db/td_thr_getgregs.c
> @@ -1,5 +1,5 @@
>  /* Get a thread's general register set.
> -   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 at redhat.com>, 1999.
> 
> @@ -28,6 +28,11 @@ td_thr_getgregs (const td_thrhandle_t *th, prgregset_t regset)
> 
>    LOG ("td_thr_getgregs");
> 
> +  if (th->th_unique == 0)
> +    /* Special case for the main thread before initialization.  */
> +    return ps_lgetregs (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);
> diff --git a/libpthread/nptl_db/td_thr_setfpregs.c b/libpthread/nptl_db/td_thr_setfpregs.c
> index 3c4e8ed..3154953 100644
> --- a/libpthread/nptl_db/td_thr_setfpregs.c
> +++ b/libpthread/nptl_db/td_thr_setfpregs.c
> @@ -1,5 +1,5 @@
>  /* Set 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 at redhat.com>, 1999.
> 
> @@ -28,6 +28,11 @@ td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs)
> 
>    LOG ("td_thr_setfpregs");
> 
> +  if (th->th_unique == 0)
> +    /* Special case for the main thread before initialization.  */
> +    return ps_lsetfpregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
> +			  fpregs) != 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);
> diff --git a/libpthread/nptl_db/td_thr_setgregs.c b/libpthread/nptl_db/td_thr_setgregs.c
> index 83d2cd9..5945dea 100644
> --- a/libpthread/nptl_db/td_thr_setgregs.c
> +++ b/libpthread/nptl_db/td_thr_setgregs.c
> @@ -1,5 +1,5 @@
>  /* Set a thread's general 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 at redhat.com>, 1999.
> 
> @@ -28,6 +28,11 @@ td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs)
> 
>    LOG ("td_thr_setgregs");
> 
> +  if (th->th_unique == 0)
> +    /* Special case for the main thread before initialization.  */
> +    return ps_lsetregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
> +			gregs) != 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);
> diff --git a/libpthread/nptl_db/td_thr_tlsbase.c b/libpthread/nptl_db/td_thr_tlsbase.c
> index f7d4c29..9f98bd9 100644
> --- a/libpthread/nptl_db/td_thr_tlsbase.c
> +++ b/libpthread/nptl_db/td_thr_tlsbase.c
> @@ -1,5 +1,5 @@
>  /* Locate TLS data for a thread.
> -   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
> @@ -29,8 +29,29 @@ td_thr_tlsbase (const td_thrhandle_t *th,
>    if (modid < 1)
>      return TD_NOTLS;
> 
> +  psaddr_t pd = th->th_unique;
> +  if (pd == 0)
> +    {
> +      /* This is the fake handle for the main thread before libpthread
> +	 initialization.  We are using 0 for its th_unique because we can't
> +	 trust that its thread register has been initialized.  But we need
> +	 a real pointer to have any TLS access work.  In case of dlopen'd
> +	 libpthread, initialization might not be for quite some time.  So
> +	 try looking up the thread register now.  Worst case, it's nonzero
> +	 uninitialized garbage and we get bogus results for TLS access
> +	 attempted too early.  Tough.  */
> +
> +      td_thrhandle_t main_th;
> +      err = __td_ta_lookup_th_unique (th->th_ta_p, ps_getpid (th->th_ta_p->ph),
> +				      &main_th);
> +      if (err == 0)
> +	pd = main_th.th_unique;
> +      if (pd == 0)
> +	return TD_TLSDEFER;
> +    }
> +
>    /* Get the DTV pointer from the thread descriptor.  */
> -  err = DB_GET_FIELD (dtv, th->th_ta_p, th->th_unique, pthread, dtvp, 0);
> +  err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
>    if (err != TD_OK)
>      return err;
> 
> diff --git a/libpthread/nptl_db/td_thr_validate.c b/libpthread/nptl_db/td_thr_validate.c
> index 49c30c1..1b96b51 100644
> --- a/libpthread/nptl_db/td_thr_validate.c
> +++ b/libpthread/nptl_db/td_thr_validate.c
> @@ -1,5 +1,5 @@
>  /* Validate a thread handle.
> -   Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
> +   Copyright (C) 1999,2001,2002,2003,2004,2007 Free Software Foundation, Inc.
>     This file is part of the GNU C Library.
>     Contributed by Ulrich Drepper <drepper at redhat.com>, 1999.
> 
> @@ -74,16 +74,10 @@ td_thr_validate (const td_thrhandle_t *th)
>        if (err == TD_OK)
>  	err = check_thread_list (th, list, &uninit);
> 
> -      if (err == TD_NOTHR && uninit)
> -	{
> -	  /* __pthread_initialize_minimal has not run yet.
> -	     But the main thread still has a valid ID.  */
> -	  td_thrhandle_t main_th;
> -	  err = td_ta_map_lwp2thr (th->th_ta_p,
> -				   ps_getpid (th->th_ta_p->ph), &main_th);
> -	  if (err == TD_OK && th->th_unique != main_th.th_unique)
> -	    err = TD_NOTHR;
> -	}
> +      if (err == TD_NOTHR && uninit && th->th_unique == 0)
> +	/* __pthread_initialize_minimal has not run yet.
> +	   There is only the special case thread handle.  */
> +	err = TD_OK;
>      }
> 
>    return err;
> diff --git a/libpthread/nptl_db/thread_dbP.h b/libpthread/nptl_db/thread_dbP.h
> index 24623ef..b8399f7 100644
> --- a/libpthread/nptl_db/thread_dbP.h
> +++ b/libpthread/nptl_db/thread_dbP.h
> @@ -1,5 +1,5 @@
>  /* Private header for thread debug library
> -   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
> @@ -254,4 +254,7 @@ extern td_err_e _td_store_value_local (td_thragent_t *ta,
>  extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep,
>  				  int sizep_name) attribute_hidden;
> 
> +extern td_err_e __td_ta_lookup_th_unique (const td_thragent_t *ta,
> +					  lwpid_t lwpid, td_thrhandle_t *th);
> +
>  #endif /* thread_dbP.h */
> 



More information about the uClibc mailing list