2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include "namespace.h"
40 #include "un-namespace.h"
41 #include "thr_private.h"
44 #define NELEMENTS(arr) (sizeof(arr) / sizeof(arr[0]))
47 static void dump_thread(int fd, pthread_t pthread, int long_version);
48 void _pthread_set_name_np(pthread_t thread, char *name);
50 __weak_reference(_pthread_set_name_np, pthread_set_name_np);
52 struct s_thread_info {
53 enum pthread_state state;
57 /* Static variables: */
58 static const struct s_thread_info thread_info[] = {
59 {PS_RUNNING , "Running"},
60 {PS_LOCKWAIT , "Waiting on an internal lock"},
61 {PS_MUTEX_WAIT , "Waiting on a mutex"},
62 {PS_COND_WAIT , "Waiting on a condition variable"},
63 {PS_SLEEP_WAIT , "Sleeping"},
64 {PS_SIGSUSPEND , "Suspended, waiting for a signal"},
65 {PS_SIGWAIT , "Waiting for a signal"},
66 {PS_JOIN , "Waiting to join"},
67 {PS_SUSPENDED , "Suspended"},
69 {PS_DEADLOCK , "Deadlocked"},
70 {PS_STATE_MAX , "Not a real state!"}
74 _thread_dump_info(void)
76 char s[512], tempfile[128];
80 for (i = 0; i < 100000; i++) {
81 snprintf(tempfile, sizeof(tempfile), "/tmp/pthread.dump.%u.%i",
83 /* Open the dump file for append and create it if necessary: */
84 if ((fd = __sys_open(tempfile, O_RDWR | O_CREAT | O_EXCL,
86 /* Can't open the dump file. */
90 * We only need to continue in case of
91 * EEXIT error. Most other error
92 * codes means that we will fail all
101 /* all 100000 possibilities are in use :( */
104 /* Dump the active threads. */
105 strcpy(s, "\n\n========\nACTIVE THREADS\n\n");
106 __sys_write(fd, s, strlen(s));
108 /* Enter a loop to report each thread in the global list: */
109 TAILQ_FOREACH(pthread, &_thread_list, tle) {
110 if (pthread->state != PS_DEAD)
111 dump_thread(fd, pthread, /*long_verson*/ 1);
115 * Dump the ready threads.
116 * XXX - We can't easily do this because the run queues
119 strcpy(s, "\n\n========\nREADY THREADS - unimplemented\n\n");
120 __sys_write(fd, s, strlen(s));
124 * Dump the waiting threads.
125 * XXX - We can't easily do this because the wait queues
128 strcpy(s, "\n\n========\nWAITING THREADS - unimplemented\n\n");
129 __sys_write(fd, s, strlen(s));
131 /* Close the dump file. */
137 dump_thread(int fd, pthread_t pthread, int long_version)
139 struct pthread *curthread = _get_curthread();
143 /* Find the state: */
144 for (i = 0; i < (int)NELEMENTS(thread_info) - 1; i++)
145 if (thread_info[i].state == pthread->state)
148 /* Output a record for the thread: */
149 snprintf(s, sizeof(s),
150 "--------------------\n"
151 "Thread %p (%s), scope %s, prio %3d, blocked %s, state %s [%s:%d]\n",
152 pthread, (pthread->name == NULL) ? "" : pthread->name,
153 pthread->attr.flags & PTHREAD_SCOPE_SYSTEM ? "system" : "process",
154 pthread->active_priority, (pthread->blocked != 0) ? "yes" : "no",
155 thread_info[i].name, pthread->fname, pthread->lineno);
156 __sys_write(fd, s, strlen(s));
158 if (long_version != 0) {
159 /* Check if this is the running thread: */
160 if (pthread == curthread) {
161 /* Output a record for the running thread: */
162 strcpy(s, "This is the running thread\n");
163 __sys_write(fd, s, strlen(s));
165 /* Check if this is the initial thread: */
166 if (pthread == _thr_initial) {
167 /* Output a record for the initial thread: */
168 strcpy(s, "This is the initial thread\n");
169 __sys_write(fd, s, strlen(s));
172 /* Process according to thread state: */
173 switch (pthread->state) {
175 snprintf(s, sizeof(s), "sigmask (hi) ");
176 __sys_write(fd, s, strlen(s));
177 for (i = _SIG_WORDS - 1; i >= 0; i--) {
178 snprintf(s, sizeof(s), "%08x ",
179 pthread->sigmask.__bits[i]);
180 __sys_write(fd, s, strlen(s));
182 snprintf(s, sizeof(s), "(lo)\n");
183 __sys_write(fd, s, strlen(s));
185 snprintf(s, sizeof(s), "waitset (hi) ");
186 __sys_write(fd, s, strlen(s));
187 for (i = _SIG_WORDS - 1; i >= 0; i--) {
188 snprintf(s, sizeof(s), "%08x ",
189 pthread->data.sigwait->waitset->__bits[i]);
190 __sys_write(fd, s, strlen(s));
192 snprintf(s, sizeof(s), "(lo)\n");
193 __sys_write(fd, s, strlen(s));
196 * Trap other states that are not explicitly
197 * coded to dump information:
200 snprintf(s, sizeof(s), "sigmask (hi) ");
201 __sys_write(fd, s, strlen(s));
202 for (i = _SIG_WORDS - 1; i >= 0; i--) {
203 snprintf(s, sizeof(s), "%08x ",
204 pthread->sigmask.__bits[i]);
205 __sys_write(fd, s, strlen(s));
207 snprintf(s, sizeof(s), "(lo)\n");
208 __sys_write(fd, s, strlen(s));
214 /* Set the thread name for debug: */
216 _pthread_set_name_np(pthread_t thread, char *name)
218 struct pthread *curthread = _get_curthread();
223 new_name = strdup(name);
224 /* Add a reference to the target thread. */
225 if (_thr_ref_add(curthread, thread, 0) != 0) {
230 THR_THREAD_LOCK(curthread, thread);
231 prev_name = thread->name;
232 thread->name = new_name;
233 THR_THREAD_UNLOCK(curthread, thread);
234 _thr_ref_delete(curthread, thread);
235 if (prev_name != NULL) {
236 /* Free space for previous name. */
242 /* XXX - Should return error code. */