]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/report-wait.c
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
[thirdparty/glibc.git] / hurd / report-wait.c
CommitLineData
a482b5a5 1/* Report on what a thread in our task is waiting for.
8f480b4b 2 Copyright (C) 1996,1997,1999,2002,2005 Free Software Foundation, Inc.
c84142e8
UD
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
c84142e8
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
c84142e8 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
a482b5a5
RM
19
20#include <hurd.h>
21#include <hurd/signal.h>
22#include <hurd/fd.h>
23#include <string.h>
24#include <assert.h>
25#include <hurd/msg_server.h>
8f480b4b
RM
26#include <thread_state.h>
27#include <intr-msg.h>
a482b5a5 28
0bd01927
RM
29static char *
30describe_number (string_t description, const char *flavor, long int i)
a482b5a5 31{
cf725107 32 unsigned long int j;
0bd01927
RM
33 char *p = flavor ? description : __stpcpy (description, flavor);
34 char *end;
35
36 /* Handle sign. */
37 if (i < 0)
38 {
39 i = -i;
40 *p++ = '-';
41 }
d3dc731b
MB
42
43 /* Allocate space for the number at the end of DESCRIPTION. */
44 for (j = i; j >= 10; j /= 10)
45 p++;
0bd01927
RM
46 end = p + 1;
47 *end = '\0';
d3dc731b 48
a482b5a5
RM
49 do
50 {
d3dc731b 51 *p-- = '0' + i % 10;
a482b5a5
RM
52 i /= 10;
53 } while (i != 0);
0bd01927
RM
54
55 return end;
a482b5a5
RM
56}
57
0bd01927 58static char *
a482b5a5
RM
59describe_port (string_t description, mach_port_t port)
60{
61 int i;
62
0bd01927
RM
63 if (port == MACH_PORT_NULL)
64 return __stpcpy (description, "(null)");
65 if (port == MACH_PORT_DEAD)
66 return __stpcpy (description, "(dead)");
67
a482b5a5 68 if (port == __mach_task_self ())
0bd01927 69 return __stpcpy (description, "task-self");
a482b5a5
RM
70
71 for (i = 0; i < _hurd_nports; ++i)
72 if (port == _hurd_ports[i].port)
0bd01927 73 return describe_number (description, "init#", i);
a482b5a5
RM
74
75 if (_hurd_init_dtable)
76 {
77 for (i = 0; i < _hurd_init_dtablesize; ++i)
78 if (port == _hurd_init_dtable[i])
0bd01927 79 return describe_number (description, "fd#", i);
a482b5a5
RM
80 }
81 else if (_hurd_dtable)
82 {
83 for (i = 0; i < _hurd_dtablesize; ++i)
84 if (_hurd_dtable[i] == NULL)
85 continue;
86 else if (port == _hurd_dtable[i]->port.port)
0bd01927 87 return describe_number (description, "fd#", i);
a482b5a5 88 else if (port == _hurd_dtable[i]->ctty.port)
0bd01927 89 return describe_number (description, "bgfd#", i);
a482b5a5
RM
90 }
91
0bd01927 92 return describe_number (description, "port#", port);
a482b5a5
RM
93}
94
95
6bac11d9
MB
96/* We want _HURD_ITIMER_THREAD, but don't want to link in the itimer code
97 unnecessarily. */
98#if 0 /* libc.so.0.0 needs this defined, so make it a weak alias for now. */
99extern thread_t _hurd_itimer_thread; /* XXX */
100weak_extern (_hurd_itimer_thread)
101#else
102static thread_t default_hurd_itimer_thread;
103weak_alias (default_hurd_itimer_thread, _hurd_itimer_thread)
104#endif
c3352e62 105
a482b5a5
RM
106kern_return_t
107_S_msg_report_wait (mach_port_t msgport, thread_t thread,
cca6915e 108 string_t description, mach_msg_id_t *msgid)
a482b5a5
RM
109{
110 *msgid = 0;
111
112 if (thread == _hurd_msgport_thread)
113 /* Cute. */
114 strcpy (description, "msgport");
72e1a750 115 else if (&_hurd_itimer_thread && thread == _hurd_itimer_thread)
c3352e62 116 strcpy (description, "itimer");
a482b5a5
RM
117 else
118 {
119 /* Make sure this is really one of our threads. */
120
121 struct hurd_sigstate *ss;
122
123 __mutex_lock (&_hurd_siglock);
124 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
125 if (ss->thread == thread)
126 break;
127 __mutex_unlock (&_hurd_siglock);
128 if (ss == NULL)
129 /* To hell with you. */
130 return EINVAL;
131
132 if (ss->suspended != MACH_PORT_NULL)
133 strcpy (description, "sigsuspend");
134 else
135 {
136 /* Examine the thread's state to see if it is blocked in an RPC. */
137
138 struct machine_thread_state state;
139 mach_msg_type_number_t count = MACHINE_THREAD_STATE_COUNT;
140 error_t err;
141
142 err = __thread_get_state (thread, MACHINE_THREAD_STATE_FLAVOR,
a334319f 143 (integer_t *) &state, &count);
a482b5a5
RM
144 if (err)
145 return err;
146 assert (count == MACHINE_THREAD_STATE_COUNT);
147 if (SYSCALL_EXAMINE (&state, msgid))
148 {
0bd01927
RM
149 mach_port_t send_port, rcv_port;
150 mach_msg_option_t option;
151 mach_msg_timeout_t timeout;
152
a482b5a5 153 /* Blocked in a system call. */
0bd01927
RM
154 if (*msgid == -25
155 /* mach_msg system call. Examine its parameters. */
156 && MSG_EXAMINE (&state, msgid, &send_port, &rcv_port,
157 &option, &timeout) == 0)
158 {
159 char *p;
160 if (send_port != MACH_PORT_NULL && *msgid != 0)
161 {
162 /* For the normal case of RPCs, we consider the
163 destination port to be the interesting thing
164 whether we are in fact sending or receiving at the
165 moment. That tells us who we are waiting for the
166 reply from. */
167 if (send_port == ss->intr_port)
168 {
169 /* This is a Hurd interruptible RPC.
170 Mark it by surrounding the port description
171 string with [...] brackets. */
172 description[0] = '[';
173 p = describe_port (description + 1, send_port);
174 *p++ = ']';
175 *p = '\0';
176 }
177 else
178 (void) describe_port (description, send_port);
179 }
180 else if (rcv_port != MACH_PORT_NULL)
181 {
182 /* This system call had no send port, but had a
183 receive port. The msgid we extracted is then just
184 some garbage or perhaps the msgid of the last
185 message this thread received, but it's not a
186 helpful thing to return. */
187 strcpy (describe_port (description, rcv_port), ":rcv");
188 *msgid = 0;
189 }
190 else if ((option & (MACH_RCV_MSG|MACH_RCV_TIMEOUT))
191 == (MACH_RCV_MSG|MACH_RCV_TIMEOUT))
192 {
193 /* A receive with no valid port can be used for a
194 pure timeout. Report the timeout value (counted
195 in milliseconds); note this is the original total
196 time, not the time remaining. */
197 strcpy (describe_number (description, 0, timeout), "ms");
198 *msgid = 0;
199 }
200 else
201 {
202 strcpy (description, "mach_msg");
203 *msgid = 0;
204 }
205 }
206 else /* Some other system call. */
207 {
208 (void) describe_number (description, "syscall#", *msgid);
209 *msgid = 0;
210 }
a482b5a5
RM
211 }
212 else
213 description[0] = '\0';
214 }
215 }
216
217 __mach_port_deallocate (__mach_task_self (), thread);
218 return 0;
219}
0e3426bb
RM
220
221kern_return_t
222_S_msg_describe_ports (mach_port_t msgport, mach_port_t refport,
223 mach_port_t *ports, mach_msg_type_number_t nports,
224 char **desc, mach_msg_type_number_t *desclen)
225{
226 char *p, *end;
227
228 if (__USEPORT (AUTH, msgport != port))
229 return EPERM;
230
231 end = *desc + *desclen;
232 p = *desc;
233 while (nports-- > 0)
234 {
235 char this[200];
236 describe_port (this, *ports++);
237 p = __stpncpy (p, this, end - p);
238 if (p == end && p[-1] != '\0')
239 return ENOMEM;
240 }
241
242 *desclen = p - *desc;
243 return 0;
244}