2003-08-14 Roland McGrath <roland@redhat.com>
authorroland <roland>
Tue, 9 Sep 2003 06:57:51 +0000 (06:57 +0000)
committerroland <roland>
Tue, 9 Sep 2003 06:57:51 +0000 (06:57 +0000)
* thread_dbP.h: Mostly rewritten with many new macros and decls.
* td_ta_new.c (td_ta_new): Don't cache a lot of symbol values.
* structs.def: New file.
* db_info.c: New file.
* td_symbol_list.c (symbol_list_arr): Define with structs.def macros.
* td_ta_clear_event.c: Rewritten.
* td_ta_event_addr.c: Rewritten.
* td_ta_event_getmsg.c: Rewritten.
* td_ta_get_nthreads.c: Rewritten.
* td_ta_map_lwp2thr.c: New file.
* td_ta_set_event.c: Rewritten.
* td_ta_thr_iter.c: Rewritten.
* td_ta_tsd_iter.c: Rewritten.
* td_thr_clear_event.c: Rewritten.
* td_thr_event_enable.c: Rewritten.
* td_thr_event_getmsg.c: Rewritten.
* td_thr_get_info.c: Rewritten.
* td_thr_getfpregs.c: Rewritten.
* td_thr_getgregs.c: Rewritten.
* td_thr_set_event.c: Rewritten.
* td_thr_setfpregs.c: Rewritten.
* td_thr_setgregs.c: Rewritten.
* td_thr_tlsbase.c: Rewritten.
* td_thr_tsd.c: Rewritten.
* td_thr_validate.c: Rewritten.
* Makefile (distribute): Add them.
* fetch-value.c: New file.
* Makefile (libthread_db-routines): Add it.

22 files changed:
nptl_db/Makefile
nptl_db/td_symbol_list.c
nptl_db/td_ta_event_addr.c
nptl_db/td_ta_event_getmsg.c
nptl_db/td_ta_get_nthreads.c
nptl_db/td_ta_map_lwp2thr.c [new file with mode: 0644]
nptl_db/td_ta_new.c
nptl_db/td_ta_set_event.c
nptl_db/td_ta_thr_iter.c
nptl_db/td_ta_tsd_iter.c
nptl_db/td_thr_clear_event.c
nptl_db/td_thr_event_enable.c
nptl_db/td_thr_event_getmsg.c
nptl_db/td_thr_get_info.c
nptl_db/td_thr_getfpregs.c
nptl_db/td_thr_getgregs.c
nptl_db/td_thr_set_event.c
nptl_db/td_thr_setfpregs.c
nptl_db/td_thr_setgregs.c
nptl_db/td_thr_tlsbase.c
nptl_db/td_thr_tsd.c
nptl_db/td_thr_validate.c

index d6dcec5..5c73ff2 100644 (file)
@@ -42,14 +42,15 @@ libthread_db-routines = td_init td_log td_ta_new td_ta_delete \
                        td_thr_clear_event td_thr_event_getmsg \
                        td_ta_set_event td_ta_event_getmsg \
                        td_ta_clear_event td_symbol_list \
-                       td_thr_tlsbase td_thr_tls_get_addr
+                       td_thr_tlsbase td_thr_tls_get_addr \
+                       fetch-value
 
 libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes))
 
 # The ps_* callback functions are not defined.
 libthread_db.so-no-z-defs = yes
 
-distribute = thread_dbP.h shlib-versions proc_service.h
+distribute = thread_dbP.h shlib-versions proc_service.h db_info.c structs.def
 include ../Rules
 
 # Depend on libc.so so a DT_NEEDED is generated in the shared objects.
index 252faa4..061767e 100644 (file)
 
 static const char *symbol_list_arr[] =
 {
-  [SYM_PTHREAD_THREADS_EVENTS] = "__nptl_threads_events",
-  [SYM_PTHREAD_LAST_EVENT] = "__nptl_last_event",
-  [SYM_PTHREAD_NTHREADS] = "__nptl_nthreads",
-  [SYM_PTHREAD_STACK_USED] = "stack_used",
-  [SYM_PTHREAD_STACK_USER] = "__stack_user",
-  [SYM_PTHREAD_KEYS] = "__pthread_keys",
-  [SYM_PTHREAD_KEYS_MAX] = "__pthread_pthread_keys_max",
-  [SYM_PTHREAD_SIZEOF_DESCR] = "__pthread_pthread_sizeof_descr",
-  [SYM_PTHREAD_CREATE_EVENT] = "__nptl_create_event",
-  [SYM_PTHREAD_DEATH_EVENT] = "__nptl_death_event",
-  [SYM_PTHREAD_VERSION] = "nptl_version",
+# define DB_STRUCT(type) \
+  [SYM_SIZEOF_##type] = "_thread_db_sizeof_" #type,
+# define DB_STRUCT_FIELD(type, field) \
+  [SYM_##type##_FIELD_##field] = "_thread_db_" #type "_" #field,
+# define DB_SYMBOL(name) \
+  [SYM_##name] = #name,
+# define DB_VARIABLE(name) \
+  [SYM_##name] = #name, \
+  [SYM_DESC_##name] = "_thread_db_" #name,
+# include "structs.def"
+# undef DB_STRUCT
+# undef DB_SYMBOL
+# undef DB_VARIABLE
+
+  [SYM_TH_UNIQUE_CONST_THREAD_AREA] = "_thread_db_const_thread_area",
+  [SYM_TH_UNIQUE_REGISTER64] = "_thread_db_register64",
+  [SYM_TH_UNIQUE_REGISTER32] = "_thread_db_register32",
+  [SYM_TH_UNIQUE_REGISTER32_THREAD_AREA] = "_thread_db_register32_thread_area",
+  [SYM_TH_UNIQUE_REGISTER64_THREAD_AREA] = "_thread_db_register64_thread_area",
+
   [SYM_NUM_MESSAGES] = NULL
 };
 
@@ -47,7 +56,7 @@ td_symbol_list (void)
 }
 
 
-int
+ps_err_e
 td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr)
 {
   assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
index 906835d..37196e6 100644 (file)
@@ -1,5 +1,5 @@
 /* Get event address.
-   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
 
 
 td_err_e
-td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr)
+td_ta_event_addr (const td_thragent_t *ta_arg,
+                 td_event_e event, td_notify_t *addr)
 {
-  td_err_e res = TD_NOEVENT;
-  int idx = -1;
+  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+  td_err_e err;
+  psaddr_t taddr;
 
   LOG ("td_ta_event_addr");
 
@@ -36,34 +38,24 @@ td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr)
   switch (event)
     {
     case TD_CREATE:
-      idx = SYM_PTHREAD_CREATE_EVENT;
+      err = DB_GET_SYMBOL (taddr, ta, __nptl_create_event);
       break;
 
     case TD_DEATH:
-      idx = SYM_PTHREAD_DEATH_EVENT;
+      err = DB_GET_SYMBOL (taddr, ta, __nptl_death_event);
       break;
 
     default:
       /* Event cannot be handled.  */
-      break;
+      return TD_NOEVENT;
     }
 
-  /* Now get the address.  */
-  if (idx != -1)
+  if (err == TD_OK)
     {
-      psaddr_t taddr;
-
-      if (td_lookup (ta->ph, idx, &taddr) == PS_OK)
-       {
-         /* Success, we got the address.  */
-         addr->type = NOTIFY_BPT;
-         addr->u.bptaddr = taddr;
-
-         res = TD_OK;
-       }
-      else
-       res = TD_ERR;
+      /* Success, we got the address.  */
+      addr->type = NOTIFY_BPT;
+      addr->u.bptaddr = taddr;
     }
 
-  return res;
+  return err;
 }
index bab44cd..6e68ff4 100644 (file)
 
 
 td_err_e
-td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg)
+td_ta_event_getmsg (const td_thragent_t *ta_arg, td_event_msg_t *msg)
 {
+  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+  td_err_e err;
+  psaddr_t eventbuf, eventnum, eventdata;
+  psaddr_t thp, next;
+  void *copy;
+
   /* XXX I cannot think of another way but using a static variable.  */
   /* XXX Use at least __thread once it is possible.  */
   static td_thrhandle_t th;
 
-  LOG ("td_ta_event_getmsg");
+  LOG ("td_thr_event_getmsg");
 
   /* Test whether the TA parameter is ok.  */
   if (! ta_ok (ta))
     return TD_BADTA;
 
   /* Get the pointer to the thread descriptor with the last event.  */
-  psaddr_t addr;
-  if (ps_pdread (ta->ph, ta->pthread_last_event,
-                &addr, sizeof (struct pthread *)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  err = DB_GET_VALUE (thp, ta, __nptl_last_event, 0);
+  if (err != TD_OK)
+    return err;
 
-  if (addr == 0)
+  if (thp == 0)
     /* Nothing waiting.  */
     return TD_NOMSG;
 
-  /* Read the event structure from the target.  */
-  td_eventbuf_t event;
-  if (ps_pdread (ta->ph, (char *) addr + offsetof (struct pthread, eventbuf),
-                &event, sizeof (td_eventbuf_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
+  /* Copy the event message buffer in from the inferior.  */
+  err = DB_GET_FIELD_ADDRESS (eventbuf, ta, thp, pthread, eventbuf, 0);
+  if (err == TD_OK)
+    err = DB_GET_STRUCT (copy, ta, eventbuf, td_eventbuf_t);
+  if (err != TD_OK)
+    return err;
+
+  /* Read the event details from the target thread.  */
+  err = DB_GET_FIELD_LOCAL (eventnum, ta, copy, td_eventbuf_t, eventnum, 0);
+  if (err != TD_OK)
+    return err;
   /* If the structure is on the list there better be an event recorded.  */
-  if (event.eventnum == TD_EVENT_NONE)
+  if ((int) (uintptr_t) eventnum == TD_EVENT_NONE)
     return TD_DBERR;
 
+  /* Fill the user's data structure.  */
+  err = DB_GET_FIELD_LOCAL (eventdata, ta, copy, td_eventbuf_t, eventdata, 0);
+  if (err != TD_OK)
+    return err;
+
   /* Generate the thread descriptor.  */
   th.th_ta_p = (td_thragent_t *) ta;
-  th.th_unique = addr;
+  th.th_unique = thp;
 
   /* Fill the user's data structure.  */
-  msg->event = event.eventnum;
+  msg->msg.data = (uintptr_t) eventdata;
+  msg->event = (uintptr_t) eventnum;
   msg->th_p = &th;
-  msg->msg.data = (uintptr_t) event.eventdata;
 
   /* And clear the event message in the target.  */
-  memset (&event, '\0', sizeof (td_eventbuf_t));
-  if (ps_pdwrite (ta->ph, (char *) addr + offsetof (struct pthread, eventbuf),
-                 &event, sizeof (td_eventbuf_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  memset (copy, 0, ta->ta_sizeof_td_eventbuf_t);
+  err = DB_PUT_STRUCT (ta, eventbuf, td_eventbuf_t, copy);
+  if (err != TD_OK)
+    return err;
 
   /* Get the pointer to the next descriptor with an event.  */
-  psaddr_t next;
-  if (ps_pdread (ta->ph, (char *) addr + offsetof (struct pthread, nextevent),
-                &next, sizeof (struct pthread *)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  if (next == addr)
-    return TD_DBERR;
+  err = DB_GET_FIELD (next, ta, thp, pthread, nextevent, 0);
+  if (err != TD_OK)
+    return err;
 
   /* Store the pointer in the list head variable.  */
-  if (ps_pdwrite (ta->ph, ta->pthread_last_event,
-                 &next, sizeof (struct pthread *)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  if (next != NULL)
-    {
-      /* Clear the next pointer in the current descriptor.  */
-      next = NULL;
-      if (ps_pdwrite (ta->ph,
-                     (char *) addr + offsetof (struct pthread, nextevent),
-                     &next, sizeof (struct pthread *)) != PS_OK)
-       return TD_ERR;  /* XXX Other error value?  */
-    }
-
-  return TD_OK;
+  err = DB_PUT_VALUE (ta, __nptl_last_event, 0, next);
+  if (err != TD_OK)
+    return err;
+
+  if (next != 0)
+    /* Clear the next pointer in the current descriptor.  */
+    err = DB_PUT_FIELD (ta, thp, pthread, nextevent, 0, 0);
+
+  return err;
 }
index cfe93d1..ffe78bd 100644 (file)
@@ -1,5 +1,5 @@
 /* Get the number of threads in the process.
-   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
 #include "thread_dbP.h"
 
 td_err_e
-td_ta_get_nthreads (const td_thragent_t *ta, int *np)
+td_ta_get_nthreads (const td_thragent_t *ta_arg, int *np)
 {
+  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+  td_err_e err;
+  psaddr_t n;
+
   LOG ("td_ta_get_nthreads");
 
   /* Test whether the TA parameter is ok.  */
   if (! ta_ok (ta))
     return TD_BADTA;
 
-  /* Access the variable `__pthread_handles_num'.  */
-  psaddr_t addr;
-  if (td_lookup (ta->ph, SYM_PTHREAD_NTHREADS, &addr) != PS_OK)
-     return TD_ERR;    /* XXX Other error value?  */
-
-  if (ps_pdread (ta->ph, addr, np, sizeof (int)) != PS_OK)
-     return TD_ERR;    /* XXX Other error value?  */
+  /* Access the variable in the inferior that tells us.  */
+  err = DB_GET_VALUE (n, ta, __nptl_nthreads, 0);
+  if (err == TD_OK)
+    *np = (uintptr_t) n;
 
-  return TD_OK;
+  return err;
 }
diff --git a/nptl_db/td_ta_map_lwp2thr.c b/nptl_db/td_ta_map_lwp2thr.c
new file mode 100644 (file)
index 0000000..1e47528
--- /dev/null
@@ -0,0 +1,179 @@
+/* Which thread is running on an LWP?
+   Copyright (C) 2003 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include "thread_dbP.h"
+#include <stdlib.h>
+#include <byteswap.h>
+#include <sys/procfs.h>
+
+
+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;
+  ps_err_e err;
+  td_err_e terr;
+  prgregset_t regs;
+  psaddr_t addr;
+
+  LOG ("td_ta_map_lwp2thr");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  if (ta->ta_howto == ta_howto_unknown)
+    {
+      /* We need to read in from the inferior the instructions what to do.  */
+      psaddr_t howto;
+
+      err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto);
+      if (err == PS_OK)
+       {
+         err = ps_pdread (ta->ph, howto,
+                          &ta->ta_howto_data.const_thread_area,
+                          sizeof ta->ta_howto_data.const_thread_area);
+         if (err != PS_OK)
+           return TD_ERR;
+         ta->ta_howto = ta_howto_const_thread_area;
+         if (ta->ta_howto_data.const_thread_area & 0xff000000U)
+           ta->ta_howto_data.const_thread_area
+             = bswap_32 (ta->ta_howto_data.const_thread_area);
+       }
+      else
+       {
+         switch (sizeof (regs[0]))
+           {
+           case 8:
+             err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto);
+             if (err == PS_OK)
+               ta->ta_howto = ta_howto_reg;
+             else if (err == PS_NOSYM)
+               {
+                 err = td_lookup (ta->ph,
+                                  SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
+                                  &howto);
+                 if (err == PS_OK)
+                   ta->ta_howto = ta_howto_reg_thread_area;
+               }
+             break;
+
+           case 4:
+             err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto);
+             if (err == PS_OK)
+               ta->ta_howto = ta_howto_reg;
+             else if (err == PS_NOSYM)
+               {
+                 err = td_lookup (ta->ph,
+                                  SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
+                                  &howto);
+                 if (err == PS_OK)
+                   ta->ta_howto = ta_howto_reg_thread_area;
+               }
+             break;
+
+           default:
+             abort ();
+             return TD_DBERR;
+           }
+
+         if (err != PS_OK)
+           return TD_DBERR;
+
+         /* For either of these methods we read in the same descriptor.  */
+         err = ps_pdread (ta->ph, howto,
+                          ta->ta_howto_data.reg, DB_SIZEOF_DESC);
+         if (err != PS_OK)
+           return TD_ERR;
+         if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0)
+           return TD_DBERR;
+         if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U)
+           {
+             /* Byte-swap these words, though we leave the size word
+                in native order as the handy way to distinguish.  */
+             DB_DESC_OFFSET (ta->ta_howto_data.reg)
+               = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg));
+             DB_DESC_NELEM (ta->ta_howto_data.reg)
+               = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg));
+           }
+       }
+    }
+
+  switch (ta->ta_howto)
+    {
+    case ta_howto_unknown:
+      return TD_DBERR;
+
+    default:
+      abort ();
+      return TD_DBERR;
+
+    case ta_howto_reg:
+      /* On most machines, we are just looking at a register.  */
+      if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
+       return TD_ERR;
+      terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1,
+                                   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;
+      break;
+
+    case ta_howto_const_thread_area:
+      /* Some hosts don't have this call and this case won't be used.  */
+# pragma weak ps_get_thread_area
+      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;
+
+     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);
+      if (terr != TD_OK)
+       return terr;
+      /* In this descriptor the nelem word is overloaded as scale factor.  */
+      if (ps_get_thread_area
+         (ta->ph, lwpid,
+          ((addr - (psaddr_t) 0)
+           >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)),
+          &th->th_unique) != PS_OK)
+       return TD_ERR;  /* XXX Other error value?  */
+      break;
+    }
+
+  /* Found it.  Now complete the `td_thrhandle_t' object.  */
+  th->th_ta_p = (td_thragent_t *) ta;
+
+  return TD_OK;
+}
index de564ed..f84049a 100644 (file)
@@ -1,5 +1,5 @@
 /* Attach to target process.
-   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -34,30 +34,23 @@ LIST_HEAD (__td_agent_list);
 td_err_e
 td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
 {
-  psaddr_t addr;
   psaddr_t versaddr;
   char versbuf[sizeof (VERSION)];
 
   LOG ("td_ta_new");
 
-  /* Get the global event mask.  This is one of the variables which
-     are new in the thread library to enable debugging.  If it is
-     not available we cannot debug.  */
-  if (td_lookup (ps, SYM_PTHREAD_THREADS_EVENTS, &addr) != PS_OK)
-    return TD_NOLIBTHREAD;
-
   /* Check whether the versions match.  */
-  if (td_lookup (ps, SYM_PTHREAD_VERSION, &versaddr) != PS_OK)
-    return TD_VERSION;
+  if (td_lookup (ps, SYM_nptl_version, &versaddr) != PS_OK)
+    return TD_NOLIBTHREAD;
   if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK)
     return TD_ERR;
 
-  if (versbuf[sizeof (versbuf) - 1] != '\0' || strcmp (versbuf, VERSION) != 0)
+  if (memcmp (versbuf, VERSION, sizeof VERSION) != 0)
     /* Not the right version.  */
     return TD_VERSION;
 
   /* Fill in the appropriate information.  */
-  *ta = (td_thragent_t *) malloc (sizeof (td_thragent_t));
+  *ta = (td_thragent_t *) calloc (1, sizeof (td_thragent_t));
   if (*ta == NULL)
     return TD_MALLOC;
 
@@ -65,49 +58,6 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
      back into the debugger.  */
   (*ta)->ph = ps;
 
-  /* Remember the address.  */
-  (*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr;
-
-  /* Get the pointer to the variable pointing to the thread descriptor
-     with the last event.  */
-  if (td_lookup (ps, SYM_PTHREAD_LAST_EVENT, &(*ta)->pthread_last_event)
-      != PS_OK)
-    {
-    free_return:
-      free (*ta);
-      return TD_ERR;
-    }
-
-
-  if (td_lookup (ps, SYM_PTHREAD_STACK_USER, &addr) != PS_OK)
-    goto free_return;
-  /* Cast to the right type.  */
-  (*ta)->stack_user = (list_t *) addr;
-
-  if (td_lookup (ps, SYM_PTHREAD_STACK_USED, &addr) != PS_OK)
-    goto free_return;
-  /* Cast to the right type.  */
-  (*ta)->stack_used = (list_t *) addr;
-
-
-  if (td_lookup (ps, SYM_PTHREAD_KEYS, &addr) != PS_OK)
-    goto free_return;
-  /* Cast to the right type.  */
-  (*ta)->keys = (struct pthread_key_struct *) addr;
-
-
-  /* Similarly for the maximum number of thread local data keys.  */
-  if (td_lookup (ps, SYM_PTHREAD_KEYS_MAX, &addr) != PS_OK
-      || ps_pdread (ps, addr, &(*ta)->pthread_keys_max, sizeof (int)) != PS_OK)
-    goto free_return;
-
-
-  /* And for the size of the second level arrays for the keys.  */
-  if (td_lookup (ps, SYM_PTHREAD_SIZEOF_DESCR, &addr) != PS_OK
-      || ps_pdread (ps, addr, &(*ta)->sizeof_descr, sizeof (int)) != PS_OK)
-    goto free_return;
-
-
   /* Now add the new agent descriptor to the list.  */
   list_add (&(*ta)->list, &__td_agent_list);
 
index 5e2cca7..4fcc934 100644 (file)
@@ -1,5 +1,5 @@
 /* Globally enable events.
-   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
 
 
 td_err_e
-td_ta_set_event (ta, event)
-     const td_thragent_t *ta;
+td_ta_set_event (ta_arg, event)
+     const td_thragent_t *ta_arg;
      td_thr_events_t *event;
 {
+  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+  td_err_e err;
+  psaddr_t eventmask;
+  void *copy;
+
   LOG ("td_ta_set_event");
 
   /* Test whether the TA parameter is ok.  */
   if (! ta_ok (ta))
     return TD_BADTA;
 
-  /* Write the new value into the thread data structure.  */
-  td_thr_events_t old_event;
-  if (ps_pdread (ta->ph, ta->pthread_threads_eventsp,
-                &old_event, sizeof (td_thrhandle_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  /* Or the new bits in.  */
-  int i;
-  for (i = 0; i < TD_EVENTSIZE; ++i)
-    old_event.event_bits[i] |= event->event_bits[i];
-
-  /* Write the new value into the thread data structure.  */
-  if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp,
-                 &old_event, sizeof (td_thrhandle_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  /* Fetch the old event mask from the inferior and modify it in place.  */
+  err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events);
+  if (err == TD_OK)
+    err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t);
+  if (err == TD_OK)
+    {
+      uint32_t idx;
+      for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+       {
+         psaddr_t word;
+         uint32_t mask;
+         err = DB_GET_FIELD_LOCAL (word, ta, copy,
+                                   td_thr_events_t, event_bits, idx);
+         if (err != TD_OK)
+           break;
+         mask = (uintptr_t) word;
+         mask |= event->event_bits[idx];
+         word = (psaddr_t) (uintptr_t) mask;
+         err = DB_PUT_FIELD_LOCAL (ta, copy,
+                                   td_thr_events_t, event_bits, idx, word);
+         if (err != TD_OK)
+           break;
+       }
+      if (err == TD_NOAPLIC)
+       {
+         err = TD_OK;
+         while (idx < TD_EVENTSIZE)
+           if (event->event_bits[idx++] != 0)
+             {
+               err = TD_NOEVENT;
+               break;
+             }
+       }
+      if (err == TD_OK)
+       /* Now write it back to the inferior.  */
+       err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy);
+    }
 
-  return TD_OK;
+  return err;
 }
index 6348a97..18c5f2e 100644 (file)
    02111-1307 USA.  */
 
 #include "thread_dbP.h"
-#include <nptl/descr.h>
 
 
 static td_err_e
-iterate_thread_list (const td_thragent_t *ta, td_thr_iter_f *callback,
+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)
+                    psaddr_t head, int fake_empty)
 {
-  list_t list;
-  td_err_e result = TD_OK;
+  td_err_e err;
+  psaddr_t next, ofs;
+  void *copy;
 
   /* Test the state.
      XXX This is incomplete.  Normally this test should be in the loop.  */
   if (state != TD_THR_ANY_STATE)
     return TD_OK;
 
-  if (ps_pdread (ta->ph, head, &list, sizeof (list_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  err = DB_GET_FIELD (next, ta, head, list_t, next, 0);
+  if (err != TD_OK)
+    return err;
 
-  if (list.next == 0 && list.prev == 0 && head == ta->stack_user)
+  if (next == 0 && fake_empty)
     {
       /* __pthread_initialize_minimal has not run.
         There is just the main thread to return.  */
       td_thrhandle_t th;
-      td_err_e err = td_ta_map_lwp2thr (ta, ps_getpid (ta->ph), &th);
-      return (err != TD_OK ? err
-             : callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK);
+      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;
     }
 
-  while (list.next != head)
+  /* Cache the offset from struct pthread to its list_t member.  */
+  err = DB_GET_FIELD_ADDRESS (ofs, ta, 0, pthread, list, 0);
+  if (err != TD_OK)
+    return err;
+
+  if (ta->ta_sizeof_pthread == 0)
     {
-      psaddr_t addr = ((psaddr_t) list.next - offsetof (struct pthread, list));
+      err = _td_check_sizeof (ta, &ta->ta_sizeof_pthread, SYM_SIZEOF_pthread);
+      if (err != TD_OK)
+       return err;
+    }
+  copy = __alloca (ta->ta_sizeof_pthread);
 
-      int schedpolicy;
-      if (ps_pdread (ta->ph, &((struct pthread *) addr)->schedpolicy,
-                    &schedpolicy, sizeof (int)) != PS_OK)
-       {
-         result = TD_ERR;      /* XXX Other error value?  */
-         break;
-       }
+  while (next != head)
+    {
+      psaddr_t addr, schedpolicy, schedprio;
 
-      struct sched_param schedparam;
-      if (ps_pdread (ta->ph, &((struct pthread *) addr)->schedparam,
-                    &schedparam, sizeof (struct sched_param)) != PS_OK)
-       {
-         result = TD_ERR;      /* XXX Other error value?  */
-         break;
-       }
+      addr = next - (ofs - (psaddr_t) 0);
+      if (next == 0 || addr == 0) /* Sanity check.  */
+       return TD_DBERR;
+
+      /* 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.  */
+      if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK)
+       return TD_ERR;
+
+      err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
+                               schedpolicy, 0);
+      if (err != TD_OK)
+       break;
+      err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
+                               schedparam_sched_priority, 0);
+      if (err != TD_OK)
+       break;
 
-      /* Now test whether this thread matches the specified
-        conditions.  */
+      /* Now test whether this thread matches the specified conditions.  */
 
       /* Only if the priority level is as high or higher.  */
-      int descr_pri = (schedpolicy == SCHED_OTHER
-                      ? 0 : schedparam.sched_priority);
+      int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
+                      ? 0 : (uintptr_t) schedprio);
       if (descr_pri >= ti_pri)
        {
-         /* XXX For now we ignore threads which are not running anymore.
-            The reason is that gdb tries to get the registers and fails.
-            In future we should have a special mode of the thread library
-            in which we keep the process around until the actual join
-            operation happened.  */
-         int cancelhandling;
-         if (ps_pdread (ta->ph, &((struct pthread *) addr)->cancelhandling,
-                        &cancelhandling, sizeof (int)) != PS_OK)
-           {
-             result = TD_ERR;  /* XXX Other error value?  */
-             break;
-           }
-
-         if ((cancelhandling & TERMINATED_BITMASK) == 0)
-           {
-             /* Yep, it matches.  Call the callback function.  */
-             td_thrhandle_t th;
-             th.th_ta_p = (td_thragent_t *) ta;
-             th.th_unique = addr;
-             if (callback (&th, cbdata_p) != 0)
-               return TD_DBERR;
-           }
+         /* Yep, it matches.  Call the callback function.  */
+         td_thrhandle_t th;
+         th.th_ta_p = (td_thragent_t *) ta;
+         th.th_unique = addr;
+         if (callback (&th, cbdata_p) != 0)
+           return TD_DBERR;
        }
 
       /* Get the pointer to the next element.  */
-      if (ps_pdread (ta->ph, &((struct pthread *) addr)->list,
-                    &list, sizeof (list_t)) != PS_OK)
-       return TD_ERR;  /* XXX Other error value?  */
+      err = DB_GET_FIELD_LOCAL (next, ta, copy + (ofs - (psaddr_t) 0), list_t,
+                               next, 0);
+      if (err != TD_OK)
+       break;
     }
 
-  return result;
+  return err;
 }
 
 
 td_err_e
-td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback,
+td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback,
                void *cbdata_p, td_thr_state_e state, int ti_pri,
                sigset_t *ti_sigmask_p, unsigned int ti_user_flags)
 {
+  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+  td_err_e err;
+  psaddr_t list;
+
   LOG ("td_ta_thr_iter");
 
   /* Test whether the TA parameter is ok.  */
@@ -127,13 +133,16 @@ td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback,
      threads for which the thread library allocated the stacks.  We
      have to iterate over both lists separately.  We start with the
      list of threads with user-defined stacks.  */
-  td_err_e result = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
-                                        ta->stack_user);
+
+  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);
 
   /* And the threads with stacks allocated by the implementation.  */
-  if (result == TD_OK)
-    result = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
-                                 ta->stack_used);
+  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);
 
-  return result;
+  return err;
 }
index cbc2f37..9cfb1e8 100644 (file)
@@ -1,5 +1,5 @@
 /* Iterate over a process's thread-specific data.
-   Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
 #include <alloca.h>
 
 td_err_e
-td_ta_tsd_iter (const td_thragent_t *ta, td_key_iter_f *callback,
+td_ta_tsd_iter (const td_thragent_t *ta_arg, td_key_iter_f *callback,
                void *cbdata_p)
 {
+  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+  td_err_e err;
+  void *keys;
+  size_t keys_nb, keys_elemsize;
+  psaddr_t addr;
+  uint32_t idx;
+
   LOG ("td_ta_tsd_iter");
 
   /* Test whether the TA parameter is ok.  */
   if (! ta_ok (ta))
     return TD_BADTA;
 
-  int pthread_keys_max = ta->pthread_keys_max;
-  struct pthread_key_struct *keys;
-  keys = (struct pthread_key_struct *) alloca (sizeof (keys[0])
-                                              * pthread_keys_max);
+  /* This makes sure we have the size information on hand.  */
+  addr = 0;
+  err = _td_locate_field (ta,
+                         ta->ta_var___pthread_keys, SYM_DESC___pthread_keys,
+                         (psaddr_t) 0 + 1, &addr);
+  if (err != TD_OK)
+    return err;
 
-  /* Read all the information about the keys.  */
-  if (ps_pdread (ta->ph, ta->keys, keys,
-                sizeof (keys[0]) * pthread_keys_max) != PS_OK)
-       return TD_ERR;  /* XXX Other error value?  */
+  /* Now copy in the entire array of key descriptors.  */
+  keys_elemsize = (addr - (psaddr_t) 0) / 8;
+  keys_nb = keys_elemsize * DB_DESC_NELEM (ta->ta_var___pthread_keys);
+  keys = __alloca (keys_nb);
+  err = DB_GET_SYMBOL (addr, ta, __pthread_keys);
+  if (err != TD_OK)
+    return err;
+  if (ps_pdread (ta->ph, addr, keys, keys_nb) != PS_OK)
+    return TD_ERR;
 
   /* Now get all descriptors, one after the other.  */
-  int cnt;
-  for (cnt = 0; cnt < pthread_keys_max; ++cnt)
-    if (!KEY_UNUSED (keys[cnt].seq)
-       /* Return with an error if the callback returns a nonzero value.  */
-       && callback (cnt, keys[cnt].destr, cbdata_p) != 0)
-      return TD_DBERR;
+  for (idx = 0; idx < DB_DESC_NELEM (ta->ta_var___pthread_keys); ++idx)
+    {
+      psaddr_t seq, destr;
+      err = DB_GET_FIELD_LOCAL (seq, ta, keys, pthread_key_struct, seq, 0);
+      if (err != TD_OK)
+       return err;
+      if (((uintptr_t) seq) & 1)
+       {
+         err = DB_GET_FIELD_LOCAL (destr, ta, keys, pthread_key_struct,
+                                   destr, 0);
+         if (err != TD_OK)
+           return err;
+         /* Return with an error if the callback returns a nonzero value.  */
+         if (callback ((thread_key_t) idx, destr, cbdata_p) != 0)
+           return TD_DBERR;
+       }
+      /* Advance to the next element in the copied array.  */
+      keys += keys_elemsize;
+    }
 
   return TD_OK;
 }
index e729b52..fc999df 100644 (file)
@@ -1,5 +1,5 @@
 /* Disable specific event for thread.
-   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -28,27 +28,50 @@ td_thr_clear_event (th, event)
      const td_thrhandle_t *th;
      td_thr_events_t *event;
 {
+  td_err_e err;
+  psaddr_t eventmask;
+  void *copy;
+
   LOG ("td_thr_clear_event");
 
-  /* Write the new value into the thread data structure.  */
-  td_thr_events_t old_event;
-  if (ps_pdread (th->th_ta_p->ph,
-                ((char *) th->th_unique
-                 + offsetof (struct pthread, eventbuf.eventmask)),
-                &old_event, sizeof (td_thrhandle_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  /* Remove the set bits in.  */
-  int i;
-  for (i = 0; i < TD_EVENTSIZE; ++i)
-    old_event.event_bits[i] &= ~event->event_bits[i];
-
-  /* Write the new value into the thread data structure.  */
-  if (ps_pdwrite (th->th_ta_p->ph,
-                 ((char *) th->th_unique
-                  + offsetof (struct pthread, eventbuf.eventmask)),
-                 &old_event, sizeof (td_thrhandle_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  return TD_OK;
+  /* Fetch the old event mask from the inferior and modify it in place.  */
+  err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p,
+                             th->th_unique, pthread, eventbuf_eventmask, 0);
+  if (err == TD_OK)
+    err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t);
+  if (err == TD_OK)
+    {
+      uint32_t idx;
+      for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+       {
+         psaddr_t word;
+         uint32_t mask;
+         err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy,
+                                   td_thr_events_t, event_bits, idx);
+         if (err != TD_OK)
+           break;
+         mask = (uintptr_t) word;
+         mask &= ~event->event_bits[idx];
+         word = (psaddr_t) (uintptr_t) mask;
+         err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy,
+                                   td_thr_events_t, event_bits, idx, word);
+         if (err != TD_OK)
+           break;
+       }
+      if (err == TD_NOAPLIC)
+       {
+         err = TD_OK;
+         while (idx < TD_EVENTSIZE)
+           if (event->event_bits[idx++] != 0)
+             {
+               err = TD_NOEVENT;
+               break;
+             }
+       }
+      if (err == TD_OK)
+       /* Now write it back to the inferior.  */
+       err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy);
+    }
+
+  return err;
 }
index badaab0..a02be5d 100644 (file)
@@ -18,8 +18,6 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <stddef.h>
-
 #include "thread_dbP.h"
 
 
@@ -31,12 +29,6 @@ td_thr_event_enable (th, onoff)
   LOG ("td_thr_event_enable");
 
   /* Write the new value into the thread data structure.  */
-  const bool value = onoff != 0;
-  if (ps_pdwrite (th->th_ta_p->ph,
-                 ((char *) th->th_unique
-                  + offsetof (struct pthread, report_events)),
-                 &value, sizeof value) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  return TD_OK;
+  return DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread, report_events, 0,
+                      (psaddr_t) 0 + (onoff != 0));
 }
index 9008633..70ea695 100644 (file)
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <stddef.h>
-#include <string.h>
-
 #include "thread_dbP.h"
+#include <assert.h>
 
 
 td_err_e
 td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg)
 {
-  td_eventbuf_t event;
+  td_err_e err;
+  psaddr_t eventbuf, eventnum, eventdata;
+  psaddr_t thp, prevp;
+  void *copy;
 
   LOG ("td_thr_event_getmsg");
 
-  /* Read the event structure from the target.  */
-  if (ps_pdread (th->th_ta_p->ph,
-                ((char *) th->th_unique
-                 + offsetof (struct pthread, eventbuf)),
-                &event, sizeof (td_eventbuf_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  /* Copy the event message buffer in from the inferior.  */
+  err = DB_GET_FIELD_ADDRESS (eventbuf, th->th_ta_p, th->th_unique, pthread,
+                             eventbuf, 0);
+  if (err == TD_OK)
+    err = DB_GET_STRUCT (copy, th->th_ta_p, eventbuf, td_eventbuf_t);
+  if (err != TD_OK)
+    return err;
 
   /* Check whether an event occurred.  */
-  if (event.eventnum == TD_EVENT_NONE)
+  err = DB_GET_FIELD_LOCAL (eventnum, th->th_ta_p, copy,
+                           td_eventbuf_t, eventnum, 0);
+  if (err != TD_OK)
+    return err;
+  if ((int) (uintptr_t) eventnum == TD_EVENT_NONE)
     /* Nothing.  */
     return TD_NOMSG;
 
   /* Fill the user's data structure.  */
-  msg->event = event.eventnum;
+  err = DB_GET_FIELD_LOCAL (eventdata, th->th_ta_p, copy,
+                           td_eventbuf_t, eventdata, 0);
+  if (err != TD_OK)
+    return err;
+
+  msg->msg.data = (uintptr_t) eventdata;
+  msg->event = (uintptr_t) eventnum;
   msg->th_p = th;
-  msg->msg.data = (uintptr_t) event.eventdata;
 
   /* And clear the event message in the target.  */
-  memset (&event, '\0', sizeof (td_eventbuf_t));
-  if (ps_pdwrite (th->th_ta_p->ph,
-                 ((char *) th->th_unique
-                  + offsetof (struct pthread, eventbuf)),
-                 &event, sizeof (td_eventbuf_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  memset (copy, 0, th->th_ta_p->ta_sizeof_td_eventbuf_t);
+  err = DB_PUT_STRUCT (th->th_ta_p, eventbuf, td_eventbuf_t, copy);
+  if (err != TD_OK)
+    return err;
 
   /* Get the pointer to the thread descriptor with the last event.
      If it doesn't match TH, then walk down the list until we find it.
      We must splice it out of the list so that there is no dangling
      pointer to it later when it dies.  */
-  psaddr_t thp, prevp = th->th_ta_p->pthread_last_event;
-  if (ps_pdread (th->th_ta_p->ph,
-                prevp, &thp, sizeof (struct pthread *)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  err = DB_GET_SYMBOL (prevp, th->th_ta_p, __nptl_last_event);
+  if (err != TD_OK)
+    return err;
+  err = DB_GET_VALUE (thp, th->th_ta_p, __nptl_last_event, 0);
+  if (err != TD_OK)
+    return err;
 
-  psaddr_t next;
   while (thp != 0)
     {
-      if (ps_pdread (th->th_ta_p->ph,
-                    (char *) thp + offsetof (struct pthread, nextevent),
-                    &next, sizeof (struct pthread *)) != PS_OK)
-       return TD_ERR;  /* XXX Other error value?  */
+      psaddr_t next;
+      err = DB_GET_FIELD (next, th->th_ta_p, th->th_unique, pthread,
+                         nextevent, 0);
+      if (err != TD_OK)
+       return err;
 
       if (next == thp)
        return TD_DBERR;
@@ -79,24 +90,27 @@ td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg)
       if (thp == th->th_unique)
        {
          /* PREVP points at this thread, splice it out.  */
-         if (prevp == (char *) next + offsetof (struct pthread, nextevent))
+         psaddr_t next_nextp;
+         err = DB_GET_FIELD_ADDRESS (next_nextp, th->th_ta_p, next, pthread,
+                                     nextevent, 0);
+         assert (err == TD_OK); /* We used this field before.  */
+         if (prevp == next_nextp)
            return TD_DBERR;
 
-         if (ps_pdwrite (th->th_ta_p->ph, prevp, &next, sizeof next) != PS_OK)
-           return TD_ERR;      /* XXX Other error value?  */
+         err = _td_store_value (th->th_ta_p,
+                                th->th_ta_p->ta_var___nptl_last_event, -1,
+                                0, prevp, next);
+         if (err != TD_OK)
+           return err;
 
          /* Now clear this thread's own next pointer so it's not dangling
             when the thread resumes and then chains on for its next event.  */
-         next = NULL;
-         if (ps_pdwrite (th->th_ta_p->ph,
-                         (char *) thp + offsetof (struct pthread, nextevent),
-                         &next, sizeof next) != PS_OK)
-           return TD_ERR;      /* XXX Other error value?  */
-
-         return TD_OK;
+         return DB_PUT_FIELD (th->th_ta_p, thp, pthread, nextevent, 0, 0);
        }
 
-      prevp = (char *) thp + offsetof (struct pthread, nextevent);
+      err = DB_GET_FIELD_ADDRESS (prevp, th->th_ta_p, thp, pthread,
+                                 nextevent, 0);
+      assert (err == TD_OK); /* We used this field before.  */
       thp = next;
     }
 
index 985c8d7..2f9ce01 100644 (file)
 td_err_e
 td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
 {
+  td_err_e err;
+  void *copy;
+  psaddr_t tls, schedpolicy, schedprio, cancelhandling, tid, report_events;
+
   LOG ("td_thr_get_info");
 
-  /* Get the thread descriptor.  */
-  struct pthread pds;
-  if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds,
-                sizeof (struct pthread)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  /* 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;
 
   /* Fill in information.  Clear first to provide reproducable
      results for the fields we do not fill in.  */
   memset (infop, '\0', sizeof (td_thrinfo_t));
 
   infop->ti_tid = th->th_unique;
-  infop->ti_tls = (char *) pds.specific;
-  infop->ti_pri = (pds.schedpolicy == SCHED_OTHER
-                  ? 0 : pds.schedparam.sched_priority);
+  infop->ti_tls = (char *) tls;
+  infop->ti_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
+                  ? 0 : (uintptr_t) schedprio);
   infop->ti_type = TD_THR_USER;
 
-  if ((pds.cancelhandling & EXITING_BITMASK) == 0)
+  if ((((int) (uintptr_t) cancelhandling) & EXITING_BITMASK) == 0)
     /* XXX For now there is no way to get more information.  */
     infop->ti_state = TD_THR_ACTIVE;
-  else if ((pds.cancelhandling & TERMINATED_BITMASK) == 0)
+  else if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
     infop->ti_state = TD_THR_ZOMBIE;
   else
     infop->ti_state = TD_THR_UNKNOWN;
 
   /* Initialization which are the same in both cases.  */
-  infop->ti_lid = pds.tid ?: ps_getpid (th->th_ta_p->ph);
   infop->ti_ta_p = th->th_ta_p;
-  infop->ti_startfunc = pds.start_routine;
-  memcpy (&infop->ti_events, &pds.eventbuf.eventmask,
-         sizeof (td_thr_events_t));
-  infop->ti_traceme = pds.report_events != false;
+  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)
+    {
+      uint32_t idx;
+      for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+       {
+         psaddr_t word;
+         err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, pthread,
+                                   eventbuf_eventmask_event_bits, idx);
+         if (err != TD_OK)
+           break;
+         infop->ti_events.event_bits[idx] = (uintptr_t) word;
+       }
+      if (err == TD_NOAPLIC)
+       memset (&infop->ti_events.event_bits[idx], 0,
+               (TD_EVENTSIZE - idx) * sizeof infop->ti_events.event_bits[0]);
+    }
 
-  return TD_OK;
+  return err;
 }
index 8b68b93..7760512 100644 (file)
 td_err_e
 td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset)
 {
+  psaddr_t cancelhandling, tid;
+  td_err_e err;
+
   LOG ("td_thr_getfpregs");
 
   /* We have to get the state and the PID for this thread.  */
-  int cancelhandling;
-  if (ps_pdread (th->th_ta_p->ph,
-                &((struct pthread *) th->th_unique)->cancelhandling,
-                &cancelhandling, sizeof (int)) != PS_OK)
-    return TD_ERR;
+  err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
+                     cancelhandling, 0);
+  if (err != TD_OK)
+    return err;
 
   /* If the thread already terminated we return all zeroes.  */
-  if (cancelhandling & TERMINATED_BITMASK)
+  if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK)
     memset (regset, '\0', sizeof (*regset));
   /* Otherwise get the register content through the callback.  */
   else
     {
-      pid_t tid;
+      err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
+      if (err != TD_OK)
+       return err;
 
-      if (ps_pdread (th->th_ta_p->ph,
-                    &((struct pthread *) th->th_unique)->tid,
-                    &tid, sizeof (pid_t)) != PS_OK
-         || ps_lgetfpregs (th->th_ta_p->ph, tid, regset) != PS_OK)
+      if (ps_lgetfpregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK)
        return TD_ERR;
     }
 
index 90959c8..4c2373e 100644 (file)
 
 
 td_err_e
-td_thr_getgregs (const td_thrhandle_t *th, prgregset_t gregs)
+td_thr_getgregs (const td_thrhandle_t *th, prgregset_t regset)
 {
+  psaddr_t cancelhandling, tid;
+  td_err_e err;
+
   LOG ("td_thr_getgregs");
 
   /* We have to get the state and the PID for this thread.  */
-  int cancelhandling;
-  if (ps_pdread (th->th_ta_p->ph,
-                &((struct pthread *) th->th_unique)->cancelhandling,
-                &cancelhandling, sizeof (int)) != PS_OK)
-    return TD_ERR;
+  err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
+                     cancelhandling, 0);
+  if (err != TD_OK)
+    return err;
 
   /* If the thread already terminated we return all zeroes.  */
-  if (cancelhandling & TERMINATED_BITMASK)
-    memset (gregs, '\0', sizeof (prgregset_t));
+  if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK)
+    memset (regset, '\0', sizeof (*regset));
   /* Otherwise get the register content through the callback.  */
   else
     {
-      pid_t tid;
+      err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
+      if (err != TD_OK)
+       return err;
 
-      if (ps_pdread (th->th_ta_p->ph,
-                    &((struct pthread *) th->th_unique)->tid,
-                    &tid, sizeof (pid_t)) != PS_OK
-         || ps_lgetregs (th->th_ta_p->ph, tid, gregs) != PS_OK)
+      if (ps_lgetregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK)
        return TD_ERR;
     }
 
index 656728c..2bb0b9d 100644 (file)
@@ -1,5 +1,5 @@
 /* Enable specific event for thread.
-   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -28,27 +28,50 @@ td_thr_set_event (th, event)
      const td_thrhandle_t *th;
      td_thr_events_t *event;
 {
+  td_err_e err;
+  psaddr_t eventmask;
+  void *copy;
+
   LOG ("td_thr_set_event");
 
-  /* Write the new value into the thread data structure.  */
-  td_thr_events_t old_event;
-  if (ps_pdread (th->th_ta_p->ph,
-                ((char *) th->th_unique
-                 + offsetof (struct pthread, eventbuf.eventmask)),
-                &old_event, sizeof (td_thrhandle_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  /* Or the new bits in.  */
-  int i;
-  for (i = 0; i < TD_EVENTSIZE; ++i)
-    old_event.event_bits[i] |= event->event_bits[i];
-
-  /* Write the new value into the thread data structure.  */
-  if (ps_pdwrite (th->th_ta_p->ph,
-                 ((char *) th->th_unique
-                  + offsetof (struct pthread, eventbuf.eventmask)),
-                 &old_event, sizeof (td_thrhandle_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  return TD_OK;
+  /* Fetch the old event mask from the inferior and modify it in place.  */
+  err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p,
+                             th->th_unique, pthread, eventbuf_eventmask, 0);
+  if (err == TD_OK)
+    err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t);
+  if (err == TD_OK)
+    {
+      uint32_t idx;
+      for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+       {
+         psaddr_t word;
+         uint32_t mask;
+         err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy,
+                                   td_thr_events_t, event_bits, idx);
+         if (err != TD_OK)
+           break;
+         mask = (uintptr_t) word;
+         mask |= event->event_bits[idx];
+         word = (psaddr_t) (uintptr_t) mask;
+         err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy,
+                                   td_thr_events_t, event_bits, idx, word);
+         if (err != TD_OK)
+           break;
+       }
+      if (err == TD_NOAPLIC)
+       {
+         err = TD_OK;
+         while (idx < TD_EVENTSIZE)
+           if (event->event_bits[idx++] != 0)
+             {
+               err = TD_NOEVENT;
+               break;
+             }
+       }
+      if (err == TD_OK)
+       /* Now write it back to the inferior.  */
+       err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy);
+    }
+
+  return err;
 }
index fe36445..01bdb53 100644 (file)
 td_err_e
 td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs)
 {
+  psaddr_t cancelhandling, tid;
+  td_err_e err;
+
   LOG ("td_thr_setfpregs");
 
   /* We have to get the state and the PID for this thread.  */
-  int cancelhandling;
-  if (ps_pdread (th->th_ta_p->ph,
-                &((struct pthread *) th->th_unique)->cancelhandling,
-                &cancelhandling, sizeof (int)) != PS_OK)
-    return TD_ERR;
+  err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
+                     cancelhandling, 0);
+  if (err != TD_OK)
+    return err;
 
   /* Only set the registers if the thread hasn't yet terminated.  */
-  if ((cancelhandling & TERMINATED_BITMASK) == 0)
+  if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
     {
-      pid_t tid;
+      err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
+      if (err != TD_OK)
+       return err;
 
-      if (ps_pdread (th->th_ta_p->ph,
-                    &((struct pthread *) th->th_unique)->tid,
-                    &tid, sizeof (pid_t)) != PS_OK
-         || ps_lsetfpregs (th->th_ta_p->ph, tid, fpregs) != PS_OK)
+      if (ps_lsetfpregs (th->th_ta_p->ph, (uintptr_t) tid, fpregs) != PS_OK)
        return TD_ERR;
     }
 
index f20c78f..2a9ce7e 100644 (file)
 td_err_e
 td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs)
 {
+  psaddr_t cancelhandling, tid;
+  td_err_e err;
+
   LOG ("td_thr_setgregs");
 
   /* We have to get the state and the PID for this thread.  */
-  int cancelhandling;
-  if (ps_pdread (th->th_ta_p->ph,
-                &((struct pthread *) th->th_unique)->cancelhandling,
-                &cancelhandling, sizeof (int)) != PS_OK)
-    return TD_ERR;
+  err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
+                     cancelhandling, 0);
+  if (err != TD_OK)
+    return err;
 
   /* Only set the registers if the thread hasn't yet terminated.  */
-  if ((cancelhandling & TERMINATED_BITMASK) == 0)
+  if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
     {
-      pid_t tid;
+      err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
+      if (err != TD_OK)
+       return err;
 
-      if (ps_pdread (th->th_ta_p->ph,
-                    &((struct pthread *) th->th_unique)->tid,
-                    &tid, sizeof (pid_t)) != PS_OK
-         || ps_lsetregs (th->th_ta_p->ph, tid, gregs) != PS_OK)
+      if (ps_lsetregs (th->th_ta_p->ph, tid - (psaddr_t) 0, gregs) != PS_OK)
        return TD_ERR;
     }
 
index ff8f1c7..c57009a 100644 (file)
 
 #include "thread_dbP.h"
 
-/* Value used for dtv entries for which the allocation is delayed.  */
-# define TLS_DTV_UNALLOCATED   ((void *) -1l)
-
 td_err_e
 td_thr_tlsbase (const td_thrhandle_t *th,
                unsigned long int modid,
                psaddr_t *base)
 {
+  td_err_e err;
+  psaddr_t dtv, dtvptr;
+
   if (modid < 1)
     return TD_NOTLS;
 
-#if USE_TLS
-  union dtv pdtv, *dtvp;
-
-  LOG ("td_thr_tlsbase");
-
-  psaddr_t dtvpp = th->th_unique;
-#if TLS_TCB_AT_TP
-  dtvpp += offsetof (struct pthread, header.dtv);
-#elif TLS_DTV_AT_TP
-  dtvpp += TLS_PRE_TCB_SIZE + offsetof (tcbhead_t, dtv);
-#else
-# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined."
-#endif
-
   /* Get the DTV pointer from the thread descriptor.  */
-  if (ps_pdread (th->th_ta_p->ph, dtvpp, &dtvp, sizeof dtvp) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  err = DB_GET_FIELD (dtv, th->th_ta_p, th->th_unique, pthread, dtvp, 0);
+  if (err != TD_OK)
+    return err;
 
   /* Get the corresponding entry in the DTV.  */
-  if (ps_pdread (th->th_ta_p->ph, dtvp + modid,
-                &pdtv, sizeof (union dtv)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtv, dtv, dtv, modid);
+  if (err != TD_OK)
+    return err;
 
   /* It could be that the memory for this module is not allocated for
      the given thread.  */
-  if (pdtv.pointer == TLS_DTV_UNALLOCATED)
+  if ((uintptr_t) dtvptr & 1)
     return TD_TLSDEFER;
 
-  *base = (char *) pdtv.pointer;
-
+  *base = dtvptr;
   return TD_OK;
-#else
-  return TD_ERR;
-#endif
 }
index d1a5453..08f617b 100644 (file)
@@ -1,5 +1,5 @@
 /* Get a thread-specific data pointer for a thread.
-   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
 td_err_e
 td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data)
 {
-  LOG ("td_thr_tsd");
+  td_err_e err;
+  psaddr_t tk_seq, level1, level2, seq, value;
+  void *copy;
+  uint32_t pthread_key_2ndlevel_size, idx1st, idx2nd;
 
-  /* Check correct value of key.  */
-  if (tk >= th->th_ta_p->pthread_keys_max)
-    return TD_BADKEY;
+  LOG ("td_thr_tsd");
 
   /* Get the key entry.  */
-  uintptr_t seq;
-  if (ps_pdread (th->th_ta_p->ph, &th->th_ta_p->keys[tk].seq, &seq,
-                sizeof (uintptr_t)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk);
+  if (err == TD_NOAPLIC)
+    return TD_BADKEY;
+  if (err != TD_OK)
+    return err;
 
   /* Fail if this key is not at all used.  */
-  if (KEY_UNUSED (seq))
+  if (((uintptr_t) tk_seq & 1) == 0)
     return TD_BADKEY;
 
-  /* Compute the indeces.  */
-  int pthread_key_2ndlevel_size = th->th_ta_p->pthread_key_2ndlevel_size;
-  unsigned int idx1st = tk / pthread_key_2ndlevel_size;
-  unsigned int idx2nd = tk % pthread_key_2ndlevel_size;
+  /* This makes sure we have the size information on hand.  */
+  err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, 0, pthread_key_data_level2,
+                             data, 1);
+  if (err != TD_OK)
+    return err;
 
-  struct pthread_key_data *level1;
-  if (ps_pdread (th->th_ta_p->ph,
-                &((struct pthread *) th->th_unique)->specific[idx1st],
-                &level1, sizeof (level1)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  /* Compute the indeces.  */
+  pthread_key_2ndlevel_size
+    = DB_DESC_NELEM (th->th_ta_p->ta_field_pthread_key_data_level2_data);
+  idx1st = tk / pthread_key_2ndlevel_size;
+  idx2nd = tk % pthread_key_2ndlevel_size;
+
+  /* Now fetch the first level pointer.  */
+  err = DB_GET_FIELD (level1, th->th_ta_p, th->th_unique, pthread,
+                     specific, idx1st);
+  if (err == TD_NOAPLIC)
+    return TD_DBERR;
+  if (err != TD_OK)
+    return err;
 
   /* Check the pointer to the second level array.  */
-  if (level1 == NULL)
+  if (level1 == 0)
     return TD_NOTSD;
 
-  struct pthread_key_data level2;
-  if (ps_pdread (th->th_ta_p->ph, &level1[idx2nd], &level2,
-                sizeof (level2)) != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
+  /* Locate the element within the second level array.  */
+  err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p,
+                             level1, pthread_key_data_level2, data, idx2nd);
+  if (err == TD_NOAPLIC)
+    return TD_DBERR;
+  if (err != TD_OK)
+    return err;
+
+  /* Now copy in that whole structure.  */
+  err = DB_GET_STRUCT (copy, th->th_ta_p, level2, pthread_key_data);
+  if (err != TD_OK)
+    return err;
 
   /* Check whether the data is valid.  */
-  if (level2.seq != seq)
+  err = DB_GET_FIELD_LOCAL (seq, th->th_ta_p, copy, pthread_key_data, seq, 0);
+  if (err != TD_OK)
+    return err;
+  if (seq != tk_seq)
     return TD_NOTSD;
 
-  if (level2.data != NULL)
-    *data = level2.data;
+  /* Finally, fetch the value.  */
+  err = DB_GET_FIELD_LOCAL (value, th->th_ta_p, copy, pthread_key_data,
+                           data, 0);
+  if (err == TD_OK)
+    *data = value;
 
-  return TD_OK;
+  return err;
 }
index 28fec6a..e0b05f5 100644 (file)
 static td_err_e
 check_thread_list (const td_thrhandle_t *th, psaddr_t head)
 {
-  list_t list;
-  td_err_e result = TD_NOTHR;
-
-  if (ps_pdread (th->th_ta_p->ph, head, &list.next, sizeof (list.next))
-      != PS_OK)
-    return TD_ERR;     /* XXX Other error value?  */
-
-  while (list.next != head)
-    if ((psaddr_t) list.next - offsetof (struct pthread, list)
-       == th->th_unique)
-      {
-       result = TD_OK;
-       break;
-      }
-    else if (ps_pdread (th->th_ta_p->ph, list.next, &list.next,
-                       sizeof (list.next)) != PS_OK)
-      {
-       result = TD_ERR;        /* XXX Other error value?  */
-       break;
-      }
-
-  return result;
+  td_err_e err;
+  psaddr_t next, ofs;
+
+  err = DB_GET_FIELD (next, th->th_ta_p, head, list_t, next, 0);
+  if (err == TD_OK)
+    {
+      if (next == 0)
+       return TD_NOTHR;
+      err = DB_GET_FIELD_ADDRESS (ofs, th->th_ta_p, 0, pthread, list, 0);
+    }
+
+  while (err == TD_OK)
+    {
+      if (next == head)
+       return TD_NOTHR;
+
+      if (next - (ofs - (psaddr_t) 0) == th->th_unique)
+       return TD_OK;
+
+      err = DB_GET_FIELD (next, th->th_ta_p, next, list_t, next, 0);
+    }
+
+  return err;
 }
 
 
 td_err_e
 td_thr_validate (const td_thrhandle_t *th)
 {
+  td_err_e err;
+  psaddr_t list;
+
   LOG ("td_thr_validate");
 
   /* First check the list with threads using user allocated stacks.  */
-  td_err_e result = check_thread_list (th, th->th_ta_p->stack_user);
+  err = DB_GET_SYMBOL (list, th->th_ta_p, __stack_user);
+  if (err == TD_OK)
+    err = check_thread_list (th, list);
 
   /* If our thread is not on this list search the list with stack
      using implementation allocated stacks.  */
-  if (result == TD_NOTHR)
-    result = check_thread_list (th, th->th_ta_p->stack_used);
+  if (err == TD_NOTHR)
+    {
+      err = DB_GET_SYMBOL (list, th->th_ta_p, stack_used);
+      if (err == TD_OK)
+       err = check_thread_list (th, list);
+    }
 
-  return result;
+  return err;
 }