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