2007-05-16 Roland McGrath <roland@redhat.com>
authorroland <roland>
Tue, 26 Jun 2007 06:47:34 +0000 (06:47 +0000)
committerroland <roland>
Tue, 26 Jun 2007 06:47:34 +0000 (06:47 +0000)
* 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.

nptl_db/td_thr_get_info.c
nptl_db/td_thr_getfpregs.c
nptl_db/td_thr_getgregs.c
nptl_db/td_thr_setfpregs.c
nptl_db/td_thr_setgregs.c
nptl_db/td_thr_tlsbase.c
nptl_db/td_thr_validate.c

index bb13888..99e5e19 100644 (file)
@@ -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.
 
@@ -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;
 
@@ -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)
index 7760512..f943fd6 100644 (file)
@@ -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.
 
@@ -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);
index 4c2373e..8d83a80 100644 (file)
@@ -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@redhat.com>, 1999.
 
@@ -29,6 +29,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);
index 01bdb53..1ec4b1f 100644 (file)
@@ -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@redhat.com>, 1999.
 
@@ -29,6 +29,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);
index 2a9ce7e..f842f7c 100644 (file)
@@ -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@redhat.com>, 1999.
 
@@ -29,6 +29,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);
index aaeda6f..85c7f01 100644 (file)
@@ -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
@@ -30,8 +30,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;
 
index 3d560a6..9a77250 100644 (file)
@@ -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@redhat.com>, 1999.
 
@@ -75,16 +75,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;