New file.
[kopensolaris-gnu/glibc.git] / hurd / report-wait.c
1 /* Report on what a thread in our task is waiting for.
2 Copyright (C) 1996 Free Software Foundation, Inc.
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
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
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>
26 #include "thread_state.h"
27 #include "intr-msg.h"
28
29 static void
30 describe_number (string_t description, const char *flavor, int i)
31 {
32   char *p = __stpcpy (description, flavor);
33   p += i / 10 + 1;
34   *p = '\0';
35   do
36     {
37       *--p = '0' + i % 10;
38       i /= 10;
39     } while (i != 0);
40   assert (p[-1] == '#');
41 }
42
43 static void
44 describe_port (string_t description, mach_port_t port)
45 {
46   int i;
47
48   if (port == __mach_task_self ())
49     {
50       strcpy (description, "task-self");
51       return;
52     }
53
54   for (i = 0; i < _hurd_nports; ++i)
55     if (port == _hurd_ports[i].port)
56       {
57         describe_number (description, "init#", i);
58         return;
59       }
60
61   if (_hurd_init_dtable)
62     {
63       for (i = 0; i < _hurd_init_dtablesize; ++i)
64         if (port == _hurd_init_dtable[i])
65           {
66             describe_number (description, "fd#", i);
67             return;
68           }
69     }
70   else if (_hurd_dtable)
71     {
72       for (i = 0; i < _hurd_dtablesize; ++i)
73         if (_hurd_dtable[i] == NULL)
74           continue;
75         else if (port == _hurd_dtable[i]->port.port)
76           {
77             describe_number (description, "fd#", i);
78             return;
79           }
80         else if (port == _hurd_dtable[i]->ctty.port)
81           {
82             describe_number (description, "bgfd#", i);
83             return;
84           }
85     }
86
87   describe_number (description, "port#", port);
88 }
89
90
91 kern_return_t
92 _S_msg_report_wait (mach_port_t msgport, thread_t thread,
93                     string_t description, int *msgid)
94 {
95   *msgid = 0;
96
97   if (thread == _hurd_msgport_thread)
98     /* Cute.  */
99     strcpy (description, "msgport");
100   else
101     {
102       /* Make sure this is really one of our threads.  */
103
104       struct hurd_sigstate *ss;
105
106       __mutex_lock (&_hurd_siglock);
107       for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
108         if (ss->thread == thread)
109           break;
110       __mutex_unlock (&_hurd_siglock);
111       if (ss == NULL)
112         /* To hell with you.  */
113         return EINVAL;
114
115       if (ss->suspended != MACH_PORT_NULL)
116         strcpy (description, "sigsuspend");
117       else
118         {
119           /* Examine the thread's state to see if it is blocked in an RPC.  */
120
121           struct machine_thread_state state;
122           mach_msg_type_number_t count = MACHINE_THREAD_STATE_COUNT;
123           error_t err;
124
125           err = __thread_get_state (thread, MACHINE_THREAD_STATE_FLAVOR,
126                                     (integer_t *) &state, &count);
127           if (err)
128             return err;
129           assert (count == MACHINE_THREAD_STATE_COUNT);
130           if (SYSCALL_EXAMINE (&state, msgid))
131             {
132               /* Blocked in a system call.  */
133               if (*msgid == -25)
134                 /* mach_msg system call.  Examine its parameters.  */
135                 describe_port (description, MSG_EXAMINE (&state, msgid));
136               else
137                 strcpy (description, "kernel");
138             }
139           else
140             description[0] = '\0';
141         }
142     }
143
144   __mach_port_deallocate (__mach_task_self (), thread);
145   return 0;
146 }