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