2003-08-14 Roland McGrath <roland@redhat.com>
[kopensolaris-gnu/glibc.git] / nptl_db / td_ta_tsd_iter.c
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;
 }