Update.
authorUlrich Drepper <drepper@redhat.com>
Wed, 3 Nov 1999 06:13:09 +0000 (06:13 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 3 Nov 1999 06:13:09 +0000 (06:13 +0000)
* internals.h: Declare __pthread_last_event.
* manager.c: Define __pthread_last_event.
(pthread_handle_create): Set __pthread_last_event.
(pthread_exited): Likewise.
* join.c (pthread_exit): Likewise.

16 files changed:
linuxthreads/ChangeLog
linuxthreads/internals.h
linuxthreads/join.c
linuxthreads/manager.c
linuxthreads_db/ChangeLog
linuxthreads_db/Makefile
linuxthreads_db/td_ta_clear_event.c [new file with mode: 0644]
linuxthreads_db/td_ta_event_getmsg.c [new file with mode: 0644]
linuxthreads_db/td_ta_new.c
linuxthreads_db/td_ta_set_event.c
linuxthreads_db/td_ta_thr_iter.c
linuxthreads_db/td_thr_clear_event.c
linuxthreads_db/td_thr_get_info.c
linuxthreads_db/td_thr_set_event.c
linuxthreads_db/thread_db.h
linuxthreads_db/thread_dbP.h

index 6d00c17..a670e9f 100644 (file)
@@ -1,5 +1,11 @@
 1999-11-02  Ulrich Drepper  <drepper@cygnus.com>
 
+       * internals.h: Declare __pthread_last_event.
+       * manager.c: Define __pthread_last_event.
+       (pthread_handle_create): Set __pthread_last_event.
+       (pthread_exited): Likewise.
+       * join.c (pthread_exit): Likewise.
+
        * Makefile (libpthread-routines): Add events.
        * events.c: New file.
        * internals.h: Protect against multiple inclusion.
index 531b042..f9eba6b 100644 (file)
@@ -229,6 +229,9 @@ extern volatile int __pthread_threads_debug;
 /* Globally enabled events.  */
 extern volatile td_thr_events_t __pthread_threads_events;
 
+/* Pointer to descriptor of thread with last event.  */
+extern volatile pthread_descr __pthread_last_event;
+
 /* Return the handle corresponding to a thread id */
 
 static inline pthread_handle thread_handle(pthread_t id)
index a2c8b20..71db541 100644 (file)
@@ -54,6 +54,7 @@ void pthread_exit(void * retval)
          /* Yep, we have to signal the death.  */
          THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH);
          THREAD_SETMEM(self, p_eventbuf.eventdata, self);
+         __pthread_last_event = self;
 
          /* Now call the function to signal the event.  */
          __linuxthreads_death_event();
index 3b70097..21a3f68 100644 (file)
@@ -55,6 +55,9 @@ volatile int __pthread_threads_debug;
 /* Globally enabled events.  */
 volatile td_thr_events_t __pthread_threads_events;
 
+/* Pointer to thread descriptor with last event.  */
+volatile pthread_descr __pthread_last_event;
+
 /* Mapping from stack segment to thread descriptor. */
 /* Stack segment numbers are also indices into the __pthread_handles array. */
 /* Stack segment number 0 is reserved for the initial thread. */
@@ -422,6 +425,7 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
                 already scheduled when we send the event.  */
              new_thread->p_eventbuf.eventdata = new_thread;
              new_thread->p_eventbuf.eventnum = TD_CREATE;
+             __pthread_last_event = new_thread;
 
              /* Now call the function which signals the event.  */
              __linuxthreads_create_event ();
@@ -523,6 +527,7 @@ static void pthread_exited(pid_t pid)
              /* Yep, we have to signal the death.  */
              th->p_eventbuf.eventnum = TD_DEATH;
              th->p_eventbuf.eventdata = th;
+             __pthread_last_event = th;
 
              /* Now call the function to signal the event.  */
              __linuxthreads_reap_event();
index 723f9a4..0922e9e 100644 (file)
@@ -1,5 +1,26 @@
 1999-11-02  Ulrich Drepper  <drepper@cygnus.com>
 
+       * td_ta_thr_iter.c (td_ta_thr_iter): Optimize a bit.  Read all
+       handles at once.
+
+       * thread_dbP.h (struct th_thragent): Add pthread_handle_num.
+       * td_ta_new.c: Initialize pthread_handle_num.
+       * td_ta_event_getmsg.c: If last event was already reported search
+       for another unreported event.
+
+       * td_thr_get_info.c (td_thr_get_info): Initialize ti_events.
+
+       * Makefile (libthread_db-routines): Add td_ta_set_event,
+       td_ta_event_getmsg, and td_ta_clear_event.
+       * td_ta_clear_event.c: New file.
+       * td_ta_event_getmsg.c: New file.
+       * td_ta_new.c: Get address of __pthread_last_event in target.
+       * td_ta_set_event.c: Don't overwrite old mask, set additional bits.
+       * td_thr_set_event.c: Likewise.
+       * td_thr_clear_event.c: Implement.
+       * thread_db.h: Declare td_ta_clear_event and td_ta_event_getmsg.
+       * thread_dbP.h (struct td_thragent): Add pthread_last_event.
+
        * td_ta_new.c: Don't test for __pthread_threads_debug.  Get address
        of __pthread_threads_events and fail if this is not possible.
        * td_ta_event_addr.c: Implement.
index fb2825c..fa6b3bc 100644 (file)
@@ -37,7 +37,9 @@ libthread_db-routines = td_init td_log td_ta_delete td_ta_get_nthreads      \
                        td_ta_setconcurrency td_ta_enable_stats             \
                        td_ta_reset_stats td_ta_get_stats td_ta_event_addr  \
                        td_thr_event_enable td_thr_set_event                \
-                       td_thr_clear_event td_thr_event_getmsg
+                       td_thr_clear_event td_thr_event_getmsg              \
+                       td_ta_set_event td_ta_event_getmsg                  \
+                       td_ta_clear_event
 
 libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes))
 
diff --git a/linuxthreads_db/td_ta_clear_event.c b/linuxthreads_db/td_ta_clear_event.c
new file mode 100644 (file)
index 0000000..ec7770e
--- /dev/null
@@ -0,0 +1,49 @@
+/* Globally disable events.
+   Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_clear_event (ta, event)
+     const td_thragent_t *ta;
+     td_thr_events_t *event;
+{
+  td_thr_events_t old_event;
+  int i;
+
+  LOG (__FUNCTION__);
+
+  /* Write the new value into the thread data structure.  */
+  if (ps_pdread (ta->ph, ta->pthread_threads_eventsp,
+                &old_event, sizeof (td_thrhandle_t)) != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
+  /* Remove the set bits in.  */
+  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?  */
+
+  return TD_OK;
+}
diff --git a/linuxthreads_db/td_ta_event_getmsg.c b/linuxthreads_db/td_ta_event_getmsg.c
new file mode 100644 (file)
index 0000000..6b56e0d
--- /dev/null
@@ -0,0 +1,124 @@
+/* Retrieve event.
+   Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg)
+{
+  /* XXX I cannot think of another way but using a static variable.  */
+  static td_thrhandle_t th;
+  td_eventbuf_t event;
+  psaddr_t addr;
+
+  LOG (__FUNCTION__);
+
+  /* Get the pointer to the thread descriptor with the last event.  */
+  if (ps_pdread (ta->ph, ta->pthread_last_event,
+                &addr, sizeof (void *)) != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
+  /* If the pointer is NULL no event occurred.  */
+  if (addr == 0)
+    return TD_NOMSG;
+
+  /* Read the even structure from the target.  */
+  if (ps_pdread (ta->ph,
+                ((char *) addr
+                 + offsetof (struct _pthread_descr_struct, p_eventbuf)),
+                &event, sizeof (td_eventbuf_t)) != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
+  /* Check whether an event occurred.  */
+  if (event.eventnum == TD_EVENT_NONE)
+    {
+      /* Oh well, this means the last event was already read.  So
+        we have to look for any other event.  */
+      struct pthread_handle_struct handles[ta->pthread_threads_max];
+      int num;
+      int i;
+
+      /* Read the number of currently active threads.  */
+      if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int))
+         != PS_OK)
+       return TD_ERR;  /* XXX Other error value?  */
+
+      /* Now read the handles.  */
+      if (ps_pdread (ta->ph, ta->handles, handles,
+                    ta->pthread_threads_max * sizeof (handles[0])) != PS_OK)
+       return TD_ERR;  /* XXX Other error value?  */
+
+      for (i = 0; i < ta->pthread_threads_max && num > 0; ++i)
+       {
+         if (handles[i].h_descr == NULL)
+           /* No entry here.  */
+           continue;
+
+         /* First count this active thread.  */
+         --num;
+
+         if (handles[i].h_descr == addr)
+           /* We already handled this.  */
+           continue;
+
+         /* Read the event data for this thread.  */
+         if (ps_pdread (ta->ph,
+                        ((char *) handles[i].h_descr
+                         + offsetof (struct _pthread_descr_struct,
+                                     p_eventbuf)),
+                        &event, sizeof (td_eventbuf_t)) != PS_OK)
+           return TD_ERR;
+
+         if (event.eventnum != TD_EVENT_NONE)
+           {
+             /* We found a thread with an unreported event.  */
+             addr = handles[i].h_descr;
+             break;
+           }
+       }
+
+      /* If we haven't found any other event signal this to the user.  */
+      if (event.eventnum == TD_EVENT_NONE)
+       return TD_NOMSG;
+    }
+
+  /* Generate the thread descriptor.  */
+  th.th_ta_p = (td_thragent_t *) ta;
+  th.th_unique = addr;
+
+  /* Fill the user's data structure.  */
+  msg->event = event.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_descr_struct, p_eventbuf)),
+                 &event, sizeof (td_eventbuf_t)) != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
+  return TD_OK;
+}
index eeaf0cb..65535f8 100644 (file)
@@ -51,15 +51,29 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
   /* Remember the address.  */
   (*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr;
 
-  /* See whether the library contains the necessary symbols.  */
-  if (ps_pglobal_lookup (ps, LIBPTHREAD_SO, "__pthread_handles",
-                        &addr) != PS_OK)
+  /* Get the pointer to the variable pointing to the thread descriptor
+     with the last event.  */
+  if (ps_pglobal_lookup (ps, LIBPTHREAD_SO,
+                        "__pthread_last_event",
+                        &(*ta)->pthread_last_event) != PS_OK)
     {
     free_return:
       free (*ta);
       return TD_ERR;
     }
 
+  /* Get the pointer to the variable containing the number of active
+     threads.  */
+  if (ps_pglobal_lookup (ps, LIBPTHREAD_SO,
+                        "__pthread_handles_num",
+                        &(*ta)->pthread_handles_num) != PS_OK)
+    goto free_return;
+
+  /* See whether the library contains the necessary symbols.  */
+  if (ps_pglobal_lookup (ps, LIBPTHREAD_SO, "__pthread_handles",
+                        &addr) != PS_OK)
+    goto free_return;
+
   (*ta)->handles = (struct pthread_handle_struct *) addr;
 
 
index 10adbdf..f783d75 100644 (file)
@@ -26,11 +26,23 @@ td_ta_set_event (ta, event)
      const td_thragent_t *ta;
      td_thr_events_t *event;
 {
+  td_thr_events_t old_event;
+  int i;
+
   LOG (__FUNCTION__);
 
   /* Write the new value into the thread data structure.  */
+  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.  */
+  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,
-                 event, sizeof (td_thrhandle_t)) != PS_OK)
+                 &old_event, sizeof (td_thrhandle_t)) != PS_OK)
     return TD_ERR;     /* XXX Other error value?  */
 
   return TD_OK;
index f9b5673..1fe871f 100644 (file)
@@ -26,64 +26,72 @@ td_ta_thr_iter (const td_thragent_t *ta, 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)
 {
-  struct pthread_handle_struct *handles = ta->handles;
   int pthread_threads_max = ta->pthread_threads_max;
   size_t sizeof_descr = ta->sizeof_descr;
+  struct pthread_handle_struct phc[pthread_threads_max];
+  int num;
   int cnt;
 
   LOG (__FUNCTION__);
 
+  /* Read all the descriptors.  */
+  if (ps_pdread (ta->ph, ta->handles, phc,
+                sizeof (struct pthread_handle_struct) * pthread_threads_max)
+      != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
+  /* Read the number of currently active threads.  */
+  if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int))
+      != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
   /* Now get all descriptors, one after the other.  */
-  for (cnt = 0; cnt < pthread_threads_max; ++cnt, ++handles)
-    {
-      struct pthread_handle_struct phc;
-
-      if (ps_pdread (ta->ph, handles, &phc,
-                    sizeof (struct pthread_handle_struct)) != PS_OK)
-       return TD_ERR;  /* XXX Other error value?  */
-
-      if (phc.h_descr != NULL)
-       {
-         struct _pthread_descr_struct pds;
-         td_thrhandle_t th;
-
-         if (ps_pdread (ta->ph, phc.h_descr, &pds, sizeof_descr) != PS_OK)
-           return TD_ERR;      /* XXX Other error value?  */
-
-         /* The manager thread must be handled special.  The descriptor
-            exists but the thread only gets created when the first
-            `pthread_create' call is issued.  A clear indication that
-            this happened is when the p_pid field is non-zero.  */
-         if (cnt == 1 && pds.p_pid == 0)
-           continue;
-
-         /* Now test whether this thread matches the specified
-            conditions.  */
-
-         /* Only if the priority level is as high or higher.  */
-         if (pds.p_priority < ti_pri)
-           continue;
-
-         /* Test the state.
-            XXX This is incomplete.  */
-         if (state != TD_THR_ANY_STATE)
-           continue;
-
-         /* 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.  */
-         if (pds.p_exited != 0)
-           continue;
-
-         /* Yep, it matches.  Call the callback function.  */
-         th.th_ta_p = (td_thragent_t *) ta;
-         th.th_unique = phc.h_descr;
-         if (callback (&th, cbdata_p) != 0)
-           return TD_DBERR;
-       }
-    }
+  for (cnt = 0; cnt < pthread_threads_max && num > 0; ++cnt)
+    if (phc[cnt].h_descr != NULL)
+      {
+       struct _pthread_descr_struct pds;
+       td_thrhandle_t th;
+
+       /* First count this active thread.  */
+       --num;
+
+       if (ps_pdread (ta->ph, phc[cnt].h_descr, &pds, sizeof_descr)
+           != PS_OK)
+         return TD_ERR;        /* XXX Other error value?  */
+
+       /* The manager thread must be handled special.  The descriptor
+          exists but the thread only gets created when the first
+          `pthread_create' call is issued.  A clear indication that
+          this happened is when the p_pid field is non-zero.  */
+       if (cnt == 1 && pds.p_pid == 0)
+         continue;
+
+       /* Now test whether this thread matches the specified
+          conditions.  */
+
+       /* Only if the priority level is as high or higher.  */
+       if (pds.p_priority < ti_pri)
+         continue;
+
+       /* Test the state.
+          XXX This is incomplete.  */
+       if (state != TD_THR_ANY_STATE)
+         continue;
+
+       /* 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.  */
+       if (pds.p_exited != 0)
+         continue;
+
+       /* Yep, it matches.  Call the callback function.  */
+       th.th_ta_p = (td_thragent_t *) ta;
+       th.th_unique = phc[cnt].h_descr;
+       if (callback (&th, cbdata_p) != 0)
+         return TD_DBERR;
+      }
 
   return TD_OK;
 }
index c3c633b..8ef8cbb 100644 (file)
@@ -1,4 +1,4 @@
-/* Disable specific event.
+/* Disable specific event for thread.
    Copyright (C) 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <stddef.h>
+
 #include "thread_dbP.h"
 
 
 td_err_e
-td_thr_clear_event (const td_thrhandle_t *th, td_thr_events_t *event)
+td_thr_clear_event (th, event)
+     const td_thrhandle_t *th;
+     td_thr_events_t *event;
 {
-  /* XXX We have to figure out what has to be done.  */
+  td_thr_events_t old_event;
+  int i;
+
   LOG (__FUNCTION__);
-  return TD_NOCAPAB;
+
+  /* Write the new value into the thread data structure.  */
+  if (ps_pdread (th->th_ta_p->ph,
+                ((char *) th->th_unique
+                 + offsetof (struct _pthread_descr_struct,
+                             p_eventbuf.eventmask)),
+                &old_event, sizeof (td_thrhandle_t)) != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
+  /* Remove the set bits in.  */
+  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_descr_struct,
+                              p_eventbuf.eventmask)),
+                 &old_event, sizeof (td_thrhandle_t)) != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
+  return TD_OK;
 }
index 606ca81..1e05d4c 100644 (file)
@@ -19,6 +19,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <stddef.h>
+#include <string.h>
 
 #include "thread_dbP.h"
 
@@ -66,6 +67,8 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
   infop->ti_lid = pds.p_pid;
   infop->ti_ta_p = th->th_ta_p;
   infop->ti_startfunc = pds.p_start_args.start_routine;
+  memcpy (&infop->ti_events, &pds.p_eventbuf.eventmask,
+         sizeof (td_thr_events_t));
 
   return TD_OK;
 }
index e6b6cbc..583a2f8 100644 (file)
@@ -28,14 +28,29 @@ td_thr_set_event (th, event)
      const td_thrhandle_t *th;
      td_thr_events_t *event;
 {
+  td_thr_events_t old_event;
+  int i;
+
   LOG (__FUNCTION__);
 
   /* Write the new value into the thread data structure.  */
+  if (ps_pdread (th->th_ta_p->ph,
+                ((char *) th->th_unique
+                 + offsetof (struct _pthread_descr_struct,
+                             p_eventbuf.eventmask)),
+                &old_event, sizeof (td_thrhandle_t)) != PS_OK)
+    return TD_ERR;     /* XXX Other error value?  */
+
+  /* Or the new bits in.  */
+  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_descr_struct,
                               p_eventbuf.eventmask)),
-                 event, sizeof (td_thrhandle_t)) != PS_OK)
+                 &old_event, sizeof (td_thrhandle_t)) != PS_OK)
     return TD_ERR;     /* XXX Other error value?  */
 
   return TD_OK;
index 8e33a06..6301d7f 100644 (file)
@@ -331,10 +331,18 @@ extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki,
 extern td_err_e td_ta_event_addr (const td_thragent_t *__ta,
                                  td_event_e __event, td_notify_t *__ptr);
 
-/* Enable EVENT for all threads.  */
+/* Enable EVENT in global mask.  */
 extern td_err_e td_ta_set_event (const td_thragent_t *__ta,
                                 td_thr_events_t *__event);
 
+/* Disable EVENT in global mask.  */
+extern td_err_e td_ta_clear_event (const td_thragent_t *__ta,
+                                  td_thr_events_t *__event);
+
+/* Return information about last event.  */
+extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta,
+                                   td_event_msg_t *msg);
+
 
 /* Set suggested concurrency level for process associated with TA.  */
 extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level);
index 5c7fcde..6092183 100644 (file)
@@ -41,6 +41,12 @@ struct td_thragent
 
   /* Pointer to the `__pthread_threads_events' variable in the target.  */
   psaddr_t pthread_threads_eventsp;
+
+  /* Pointer to the `__pthread_last_event' variable in the target.  */
+  psaddr_t pthread_last_event;
+
+  /* Pointer to the `__pthread_handles_num' variable.  */
+  psaddr_t pthread_handles_num;
 };