Back to index

glibc  2.9
td_thr_event_getmsg.c
Go to the documentation of this file.
00001 /* Retrieve event.
00002    Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include "thread_dbP.h"
00022 #include <assert.h>
00023 
00024 
00025 td_err_e
00026 td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg)
00027 {
00028   td_err_e err;
00029   psaddr_t eventbuf, eventnum, eventdata;
00030   psaddr_t thp, prevp;
00031   void *copy;
00032 
00033   LOG ("td_thr_event_getmsg");
00034 
00035   /* Copy the event message buffer in from the inferior.  */
00036   err = DB_GET_FIELD_ADDRESS (eventbuf, th->th_ta_p, th->th_unique, pthread,
00037                            eventbuf, 0);
00038   if (err == TD_OK)
00039     err = DB_GET_STRUCT (copy, th->th_ta_p, eventbuf, td_eventbuf_t);
00040   if (err != TD_OK)
00041     return err;
00042 
00043   /* Check whether an event occurred.  */
00044   err = DB_GET_FIELD_LOCAL (eventnum, th->th_ta_p, copy,
00045                          td_eventbuf_t, eventnum, 0);
00046   if (err != TD_OK)
00047     return err;
00048   if ((int) (uintptr_t) eventnum == TD_EVENT_NONE)
00049     /* Nothing.  */
00050     return TD_NOMSG;
00051 
00052   /* Fill the user's data structure.  */
00053   err = DB_GET_FIELD_LOCAL (eventdata, th->th_ta_p, copy,
00054                          td_eventbuf_t, eventdata, 0);
00055   if (err != TD_OK)
00056     return err;
00057 
00058   msg->msg.data = (uintptr_t) eventdata;
00059   msg->event = (uintptr_t) eventnum;
00060   msg->th_p = th;
00061 
00062   /* And clear the event message in the target.  */
00063   memset (copy, 0, th->th_ta_p->ta_sizeof_td_eventbuf_t);
00064   err = DB_PUT_STRUCT (th->th_ta_p, eventbuf, td_eventbuf_t, copy);
00065   if (err != TD_OK)
00066     return err;
00067 
00068   /* Get the pointer to the thread descriptor with the last event.
00069      If it doesn't match TH, then walk down the list until we find it.
00070      We must splice it out of the list so that there is no dangling
00071      pointer to it later when it dies.  */
00072   err = DB_GET_SYMBOL (prevp, th->th_ta_p, __nptl_last_event);
00073   if (err != TD_OK)
00074     return err;
00075   err = DB_GET_VALUE (thp, th->th_ta_p, __nptl_last_event, 0);
00076   if (err != TD_OK)
00077     return err;
00078 
00079   while (thp != 0)
00080     {
00081       psaddr_t next;
00082       err = DB_GET_FIELD (next, th->th_ta_p, th->th_unique, pthread,
00083                        nextevent, 0);
00084       if (err != TD_OK)
00085        return err;
00086 
00087       if (next == thp)
00088        return TD_DBERR;
00089 
00090       if (thp == th->th_unique)
00091        {
00092          /* PREVP points at this thread, splice it out.  */
00093          psaddr_t next_nextp;
00094          err = DB_GET_FIELD_ADDRESS (next_nextp, th->th_ta_p, next, pthread,
00095                                   nextevent, 0);
00096          assert (err == TD_OK); /* We used this field before.  */
00097          if (prevp == next_nextp)
00098            return TD_DBERR;
00099 
00100          err = _td_store_value (th->th_ta_p,
00101                              th->th_ta_p->ta_var___nptl_last_event, -1,
00102                              0, prevp, next);
00103          if (err != TD_OK)
00104            return err;
00105 
00106          /* Now clear this thread's own next pointer so it's not dangling
00107             when the thread resumes and then chains on for its next event.  */
00108          return DB_PUT_FIELD (th->th_ta_p, thp, pthread, nextevent, 0, 0);
00109        }
00110 
00111       err = DB_GET_FIELD_ADDRESS (prevp, th->th_ta_p, thp, pthread,
00112                               nextevent, 0);
00113       assert (err == TD_OK); /* We used this field before.  */
00114       thp = next;
00115     }
00116 
00117   /* Ack!  This should not happen.  */
00118   return TD_DBERR;
00119 }