Update.
[kopensolaris-gnu/glibc.git] / linuxthreads_db / td_ta_event_getmsg.c
1 /* Retrieve event.
2    Copyright (C) 1999 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include <stddef.h>
22 #include <string.h>
23
24 #include "thread_dbP.h"
25
26
27 td_err_e
28 td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg)
29 {
30   /* XXX I cannot think of another way but using a static variable.  */
31   static td_thrhandle_t th;
32   td_eventbuf_t event;
33   psaddr_t addr;
34
35   LOG (__FUNCTION__);
36
37   /* Test whether the TA parameter is ok.  */
38   if (! ta_ok (ta))
39     return TD_BADTA;
40
41   /* Get the pointer to the thread descriptor with the last event.  */
42   if (ps_pdread (ta->ph, ta->pthread_last_event,
43                  &addr, sizeof (void *)) != PS_OK)
44     return TD_ERR;      /* XXX Other error value?  */
45
46   /* If the pointer is NULL no event occurred.  */
47   if (addr == 0)
48     return TD_NOMSG;
49
50   /* Read the even structure from the target.  */
51   if (ps_pdread (ta->ph,
52                  ((char *) addr
53                   + offsetof (struct _pthread_descr_struct, p_eventbuf)),
54                  &event, sizeof (td_eventbuf_t)) != PS_OK)
55     return TD_ERR;      /* XXX Other error value?  */
56
57   /* Check whether an event occurred.  */
58   if (event.eventnum == TD_EVENT_NONE)
59     {
60       /* Oh well, this means the last event was already read.  So
61          we have to look for any other event.  */
62       struct pthread_handle_struct handles[ta->pthread_threads_max];
63       int num;
64       int i;
65
66       /* Read the number of currently active threads.  */
67       if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int))
68           != PS_OK)
69         return TD_ERR;  /* XXX Other error value?  */
70
71       /* Now read the handles.  */
72       if (ps_pdread (ta->ph, ta->handles, handles,
73                      ta->pthread_threads_max * sizeof (handles[0])) != PS_OK)
74         return TD_ERR;  /* XXX Other error value?  */
75
76       for (i = 0; i < ta->pthread_threads_max && num > 0; ++i)
77         {
78           if (handles[i].h_descr == NULL)
79             /* No entry here.  */
80             continue;
81
82           /* First count this active thread.  */
83           --num;
84
85           if (handles[i].h_descr == addr)
86             /* We already handled this.  */
87             continue;
88
89           /* Read the event data for this thread.  */
90           if (ps_pdread (ta->ph,
91                          ((char *) handles[i].h_descr
92                           + offsetof (struct _pthread_descr_struct,
93                                       p_eventbuf)),
94                          &event, sizeof (td_eventbuf_t)) != PS_OK)
95             return TD_ERR;
96
97           if (event.eventnum != TD_EVENT_NONE)
98             {
99               /* We found a thread with an unreported event.  */
100               addr = handles[i].h_descr;
101               break;
102             }
103         }
104
105       /* If we haven't found any other event signal this to the user.  */
106       if (event.eventnum == TD_EVENT_NONE)
107         return TD_NOMSG;
108     }
109
110   /* Generate the thread descriptor.  */
111   th.th_ta_p = (td_thragent_t *) ta;
112   th.th_unique = addr;
113
114   /* Fill the user's data structure.  */
115   msg->event = event.eventnum;
116   msg->th_p = &th;
117   msg->msg.data = (uintptr_t) event.eventdata;
118
119   /* And clear the event message in the target.  */
120   memset (&event, '\0', sizeof (td_eventbuf_t));
121   if (ps_pdwrite (ta->ph,
122                   ((char *) addr
123                    + offsetof (struct _pthread_descr_struct, p_eventbuf)),
124                   &event, sizeof (td_eventbuf_t)) != PS_OK)
125     return TD_ERR;      /* XXX Other error value?  */
126
127   return TD_OK;
128 }