1 /* Report on what a thread in our task is waiting for.
2 Copyright (C) 1996,1997,1999,2002,2005,2009 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
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
21 #include <hurd/signal.h>
25 #include <hurd/msg_server.h>
26 #include <thread_state.h>
30 describe_number (string_t description
, const char *flavor
, long int i
)
33 char *p
= flavor
== NULL
? description
: __stpcpy (description
, flavor
);
43 /* Allocate space for the number at the end of DESCRIPTION. */
44 for (j
= i
; j
>= 10; j
/= 10)
59 describe_port (string_t description
, mach_port_t port
)
63 if (port
== MACH_PORT_NULL
)
64 return __stpcpy (description
, "(null)");
65 if (port
== MACH_PORT_DEAD
)
66 return __stpcpy (description
, "(dead)");
68 if (port
== __mach_task_self ())
69 return __stpcpy (description
, "task-self");
71 for (i
= 0; i
< _hurd_nports
; ++i
)
72 if (port
== _hurd_ports
[i
].port
)
73 return describe_number (description
, "init#", i
);
75 if (_hurd_init_dtable
)
77 for (i
= 0; i
< _hurd_init_dtablesize
; ++i
)
78 if (port
== _hurd_init_dtable
[i
])
79 return describe_number (description
, "fd#", i
);
81 else if (_hurd_dtable
)
83 for (i
= 0; i
< _hurd_dtablesize
; ++i
)
84 if (_hurd_dtable
[i
] == NULL
)
86 else if (port
== _hurd_dtable
[i
]->port
.port
)
87 return describe_number (description
, "fd#", i
);
88 else if (port
== _hurd_dtable
[i
]->ctty
.port
)
89 return describe_number (description
, "bgfd#", i
);
92 return describe_number (description
, "port#", port
);
96 /* We want _HURD_ITIMER_THREAD, but don't want to link in the itimer code
98 #if 0 /* libc.so.0.0 needs this defined, so make it a weak alias for now. */
99 extern thread_t _hurd_itimer_thread
; /* XXX */
100 weak_extern (_hurd_itimer_thread
)
102 static thread_t default_hurd_itimer_thread
;
103 weak_alias (default_hurd_itimer_thread
, _hurd_itimer_thread
)
107 _S_msg_report_wait (mach_port_t msgport
, thread_t thread
,
108 string_t description
, mach_msg_id_t
*msgid
)
112 if (thread
== _hurd_msgport_thread
)
114 strcpy (description
, "msgport");
115 else if (&_hurd_itimer_thread
&& thread
== _hurd_itimer_thread
)
116 strcpy (description
, "itimer");
119 /* Make sure this is really one of our threads. */
121 struct hurd_sigstate
*ss
;
123 __mutex_lock (&_hurd_siglock
);
124 for (ss
= _hurd_sigstates
; ss
!= NULL
; ss
= ss
->next
)
125 if (ss
->thread
== thread
)
127 __mutex_unlock (&_hurd_siglock
);
129 /* To hell with you. */
132 if (ss
->suspended
!= MACH_PORT_NULL
)
133 strcpy (description
, "sigsuspend");
136 /* Examine the thread's state to see if it is blocked in an RPC. */
138 struct machine_thread_state state
;
139 mach_msg_type_number_t count
= MACHINE_THREAD_STATE_COUNT
;
142 err
= __thread_get_state (thread
, MACHINE_THREAD_STATE_FLAVOR
,
143 (natural_t
*) &state
, &count
);
146 assert (count
== MACHINE_THREAD_STATE_COUNT
);
147 if (SYSCALL_EXAMINE (&state
, msgid
))
149 mach_port_t send_port
, rcv_port
;
150 mach_msg_option_t option
;
151 mach_msg_timeout_t timeout
;
153 /* Blocked in a system call. */
155 /* mach_msg system call. Examine its parameters. */
156 && MSG_EXAMINE (&state
, msgid
, &send_port
, &rcv_port
,
157 &option
, &timeout
) == 0)
160 if (send_port
!= MACH_PORT_NULL
&& *msgid
!= 0)
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
167 if (send_port
== ss
->intr_port
)
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
);
178 (void) describe_port (description
, send_port
);
180 else if (rcv_port
!= MACH_PORT_NULL
)
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");
190 else if ((option
& (MACH_RCV_MSG
|MACH_RCV_TIMEOUT
))
191 == (MACH_RCV_MSG
|MACH_RCV_TIMEOUT
))
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");
202 strcpy (description
, "mach_msg");
206 else /* Some other system call. */
208 (void) describe_number (description
, "syscall#", *msgid
);
213 description
[0] = '\0';
217 __mach_port_deallocate (__mach_task_self (), thread
);
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
)
228 if (__USEPORT (AUTH
, msgport
!= port
))
231 end
= *desc
+ *desclen
;
236 describe_port (this, *ports
++);
237 p
= __stpncpy (p
, this, end
- p
);
238 if (p
== end
&& p
[-1] != '\0')
242 *desclen
= p
- *desc
;