Blame nptl_db/td_thr_event_getmsg.c

Packit 6c4009
/* Retrieve event.
Packit 6c4009
   Copyright (C) 1999-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include "thread_dbP.h"
Packit 6c4009
#include <assert.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
td_err_e
Packit 6c4009
td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg)
Packit 6c4009
{
Packit 6c4009
  td_err_e err;
Packit 6c4009
  psaddr_t eventbuf, eventnum, eventdata;
Packit 6c4009
  psaddr_t thp, prevp;
Packit 6c4009
  void *copy;
Packit 6c4009
Packit 6c4009
  LOG ("td_thr_event_getmsg");
Packit 6c4009
Packit 6c4009
  /* Copy the event message buffer in from the inferior.  */
Packit 6c4009
  err = DB_GET_FIELD_ADDRESS (eventbuf, th->th_ta_p, th->th_unique, pthread,
Packit 6c4009
			      eventbuf, 0);
Packit 6c4009
  if (err == TD_OK)
Packit 6c4009
    err = DB_GET_STRUCT (copy, th->th_ta_p, eventbuf, td_eventbuf_t);
Packit 6c4009
  if (err != TD_OK)
Packit 6c4009
    return err;
Packit 6c4009
Packit 6c4009
  /* Check whether an event occurred.  */
Packit 6c4009
  err = DB_GET_FIELD_LOCAL (eventnum, th->th_ta_p, copy,
Packit 6c4009
			    td_eventbuf_t, eventnum, 0);
Packit 6c4009
  if (err != TD_OK)
Packit 6c4009
    return err;
Packit 6c4009
  if ((int) (uintptr_t) eventnum == TD_EVENT_NONE)
Packit 6c4009
    /* Nothing.  */
Packit 6c4009
    return TD_NOMSG;
Packit 6c4009
Packit 6c4009
  /* Fill the user's data structure.  */
Packit 6c4009
  err = DB_GET_FIELD_LOCAL (eventdata, th->th_ta_p, copy,
Packit 6c4009
			    td_eventbuf_t, eventdata, 0);
Packit 6c4009
  if (err != TD_OK)
Packit 6c4009
    return err;
Packit 6c4009
Packit 6c4009
  msg->msg.data = (uintptr_t) eventdata;
Packit 6c4009
  msg->event = (uintptr_t) eventnum;
Packit 6c4009
  msg->th_p = th;
Packit 6c4009
Packit 6c4009
  /* And clear the event message in the target.  */
Packit 6c4009
  memset (copy, 0, th->th_ta_p->ta_sizeof_td_eventbuf_t);
Packit 6c4009
  err = DB_PUT_STRUCT (th->th_ta_p, eventbuf, td_eventbuf_t, copy);
Packit 6c4009
  if (err != TD_OK)
Packit 6c4009
    return err;
Packit 6c4009
Packit 6c4009
  /* Get the pointer to the thread descriptor with the last event.
Packit 6c4009
     If it doesn't match TH, then walk down the list until we find it.
Packit 6c4009
     We must splice it out of the list so that there is no dangling
Packit 6c4009
     pointer to it later when it dies.  */
Packit 6c4009
  err = DB_GET_SYMBOL (prevp, th->th_ta_p, __nptl_last_event);
Packit 6c4009
  if (err != TD_OK)
Packit 6c4009
    return err;
Packit 6c4009
  err = DB_GET_VALUE (thp, th->th_ta_p, __nptl_last_event, 0);
Packit 6c4009
  if (err != TD_OK)
Packit 6c4009
    return err;
Packit 6c4009
Packit 6c4009
  while (thp != 0)
Packit 6c4009
    {
Packit 6c4009
      psaddr_t next;
Packit 6c4009
      err = DB_GET_FIELD (next, th->th_ta_p, th->th_unique, pthread,
Packit 6c4009
			  nextevent, 0);
Packit 6c4009
      if (err != TD_OK)
Packit 6c4009
	return err;
Packit 6c4009
Packit 6c4009
      if (next == thp)
Packit 6c4009
	return TD_DBERR;
Packit 6c4009
Packit 6c4009
      if (thp == th->th_unique)
Packit 6c4009
	{
Packit 6c4009
	  /* PREVP points at this thread, splice it out.  */
Packit 6c4009
	  psaddr_t next_nextp;
Packit 6c4009
	  err = DB_GET_FIELD_ADDRESS (next_nextp, th->th_ta_p, next, pthread,
Packit 6c4009
				      nextevent, 0);
Packit 6c4009
	  assert (err == TD_OK); /* We used this field before.  */
Packit 6c4009
	  if (prevp == next_nextp)
Packit 6c4009
	    return TD_DBERR;
Packit 6c4009
Packit 6c4009
	  err = _td_store_value (th->th_ta_p,
Packit 6c4009
				 th->th_ta_p->ta_var___nptl_last_event, -1,
Packit 6c4009
				 0, prevp, next);
Packit 6c4009
	  if (err != TD_OK)
Packit 6c4009
	    return err;
Packit 6c4009
Packit 6c4009
	  /* Now clear this thread's own next pointer so it's not dangling
Packit 6c4009
	     when the thread resumes and then chains on for its next event.  */
Packit 6c4009
	  return DB_PUT_FIELD (th->th_ta_p, thp, pthread, nextevent, 0, 0);
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      err = DB_GET_FIELD_ADDRESS (prevp, th->th_ta_p, thp, pthread,
Packit 6c4009
				  nextevent, 0);
Packit 6c4009
      assert (err == TD_OK); /* We used this field before.  */
Packit 6c4009
      thp = next;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Ack!  This should not happen.  */
Packit 6c4009
  return TD_DBERR;
Packit 6c4009
}