thr_info.c revision 174112
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 31590Srgrimes * All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. Neither the name of the author nor the names of any co-contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes * 291590Srgrimes * $FreeBSD: head/lib/libkse/thread/thr_info.c 174112 2007-11-30 17:20:29Z deischen $ 301590Srgrimes */ 311590Srgrimes 321590Srgrimes#include "namespace.h" 331590Srgrimes#include <stdio.h> 341590Srgrimes#include <stdlib.h> 351590Srgrimes#include <fcntl.h> 361590Srgrimes#include <string.h> 3762833Swsanchez#include <unistd.h> 3862833Swsanchez#include <pthread.h> 391590Srgrimes#include <errno.h> 401590Srgrimes#include "un-namespace.h" 4162833Swsanchez#include "thr_private.h" 4294587Sobrien 431590Srgrimes#ifndef NELEMENTS 441590Srgrimes#define NELEMENTS(arr) (sizeof(arr) / sizeof(arr[0])) 451590Srgrimes#endif 461590Srgrimes 471590SrgrimesLT10_COMPAT_PRIVATE(_pthread_set_name_np); 481590SrgrimesLT10_COMPAT_DEFAULT(pthread_set_name_np); 491590Srgrimes 501590Srgrimesstatic void dump_thread(int fd, pthread_t pthread, int long_version); 511590Srgrimesvoid _pthread_set_name_np(pthread_t thread, char *name); 521590Srgrimes 531590Srgrimes__weak_reference(_pthread_set_name_np, pthread_set_name_np); 541590Srgrimes 551590Srgrimesstruct s_thread_info { 561590Srgrimes enum pthread_state state; 571590Srgrimes const char *name; 58126824Sru}; 59126824Sru 60126824Sru/* Static variables: */ 611590Srgrimesstatic const struct s_thread_info thread_info[] = { 621590Srgrimes {PS_RUNNING , "Running"}, 631590Srgrimes {PS_LOCKWAIT , "Waiting on an internal lock"}, 641590Srgrimes {PS_MUTEX_WAIT , "Waiting on a mutex"}, 651590Srgrimes {PS_COND_WAIT , "Waiting on a condition variable"}, 661590Srgrimes {PS_SLEEP_WAIT , "Sleeping"}, 675814Sjkh {PS_SIGSUSPEND , "Suspended, waiting for a signal"}, 685814Sjkh {PS_SIGWAIT , "Waiting for a signal"}, 691590Srgrimes {PS_JOIN , "Waiting to join"}, 701590Srgrimes {PS_SUSPENDED , "Suspended"}, 711590Srgrimes {PS_DEAD , "Dead"}, 721590Srgrimes {PS_DEADLOCK , "Deadlocked"}, 731590Srgrimes {PS_STATE_MAX , "Not a real state!"} 741590Srgrimes}; 751590Srgrimes 761590Srgrimesvoid 771590Srgrimes_thread_dump_info(void) 781590Srgrimes{ 791590Srgrimes char s[512], tempfile[128]; 801590Srgrimes pthread_t pthread; 811590Srgrimes int fd, i; 821590Srgrimes 831590Srgrimes for (i = 0; i < 100000; i++) { 841590Srgrimes snprintf(tempfile, sizeof(tempfile), "/tmp/pthread.dump.%u.%i", 851590Srgrimes getpid(), i); 861590Srgrimes /* Open the dump file for append and create it if necessary: */ 8727644Scharnier if ((fd = __sys_open(tempfile, O_RDWR | O_CREAT | O_EXCL, 8827644Scharnier 0666)) < 0) { 891590Srgrimes /* Can't open the dump file. */ 901590Srgrimes if (errno == EEXIST) 911590Srgrimes continue; 921590Srgrimes /* 931590Srgrimes * We only need to continue in case of 941590Srgrimes * EEXIT error. Most other error 951590Srgrimes * codes means that we will fail all 961590Srgrimes * the times. 971590Srgrimes */ 981590Srgrimes return; 991590Srgrimes } else { 1001590Srgrimes break; 1011590Srgrimes } 1021590Srgrimes } 1031590Srgrimes if (i==100000) { 1041590Srgrimes /* all 100000 possibilities are in use :( */ 1055814Sjkh return; 1061590Srgrimes } else { 1071590Srgrimes /* Dump the active threads. */ 1081590Srgrimes strcpy(s, "\n\n========\nACTIVE THREADS\n\n"); 1091590Srgrimes __sys_write(fd, s, strlen(s)); 1101590Srgrimes 1111590Srgrimes /* Enter a loop to report each thread in the global list: */ 1121590Srgrimes TAILQ_FOREACH(pthread, &_thread_list, tle) { 1131590Srgrimes if (pthread->state != PS_DEAD) 114132439Sharti dump_thread(fd, pthread, /*long_verson*/ 1); 115126824Sru } 1161590Srgrimes 1171590Srgrimes /* 1181590Srgrimes * Dump the ready threads. 1191590Srgrimes * XXX - We can't easily do this because the run queues 1201590Srgrimes * are per-KSEG. 1211590Srgrimes */ 1221590Srgrimes strcpy(s, "\n\n========\nREADY THREADS - unimplemented\n\n"); 1231590Srgrimes __sys_write(fd, s, strlen(s)); 1241590Srgrimes 1251590Srgrimes 1261590Srgrimes /* 1271590Srgrimes * Dump the waiting threads. 1281590Srgrimes * XXX - We can't easily do this because the wait queues 1291590Srgrimes * are per-KSEG. 1301590Srgrimes */ 1311590Srgrimes strcpy(s, "\n\n========\nWAITING THREADS - unimplemented\n\n"); 1321590Srgrimes __sys_write(fd, s, strlen(s)); 1331590Srgrimes 1341590Srgrimes /* Close the dump file. */ 1351590Srgrimes __sys_close(fd); 1361590Srgrimes } 1371590Srgrimes} 1381590Srgrimes 1391590Srgrimesstatic void 1401590Srgrimesdump_thread(int fd, pthread_t pthread, int long_version) 1411590Srgrimes{ 1421590Srgrimes struct pthread *curthread = _get_curthread(); 14318730Ssteve char s[512]; 1441590Srgrimes int i; 14518730Ssteve 14619344Ssteve /* Find the state: */ 1471590Srgrimes for (i = 0; i < (int)NELEMENTS(thread_info) - 1; i++) 1481590Srgrimes if (thread_info[i].state == pthread->state) 1491590Srgrimes break; 1501590Srgrimes 1511590Srgrimes /* Output a record for the thread: */ 15218730Ssteve snprintf(s, sizeof(s), 1531590Srgrimes "--------------------\n" 1541590Srgrimes "Thread %p (%s), scope %s, prio %3d, blocked %s, state %s [%s:%d]\n", 1551590Srgrimes pthread, (pthread->name == NULL) ? "" : pthread->name, 1561590Srgrimes pthread->attr.flags & PTHREAD_SCOPE_SYSTEM ? "system" : "process", 15718730Ssteve pthread->active_priority, (pthread->blocked != 0) ? "yes" : "no", 1581590Srgrimes thread_info[i].name, pthread->fname, pthread->lineno); 1591590Srgrimes __sys_write(fd, s, strlen(s)); 16069527Swill 1611590Srgrimes if (long_version != 0) { 1621590Srgrimes /* Check if this is the running thread: */ 1631590Srgrimes if (pthread == curthread) { 1641590Srgrimes /* Output a record for the running thread: */ 1651590Srgrimes strcpy(s, "This is the running thread\n"); 1661590Srgrimes __sys_write(fd, s, strlen(s)); 1671590Srgrimes } 1681590Srgrimes /* Check if this is the initial thread: */ 1691590Srgrimes if (pthread == _thr_initial) { 1701590Srgrimes /* Output a record for the initial thread: */ 1711590Srgrimes strcpy(s, "This is the initial thread\n"); 1721590Srgrimes __sys_write(fd, s, strlen(s)); 1731590Srgrimes } 1741590Srgrimes 1751590Srgrimes /* Process according to thread state: */ 1761590Srgrimes switch (pthread->state) { 1771590Srgrimes case PS_SIGWAIT: 1781590Srgrimes snprintf(s, sizeof(s), "sigmask (hi) "); 1791590Srgrimes __sys_write(fd, s, strlen(s)); 1801590Srgrimes for (i = _SIG_WORDS - 1; i >= 0; i--) { 1811590Srgrimes snprintf(s, sizeof(s), "%08x ", 1821590Srgrimes pthread->sigmask.__bits[i]); 1831590Srgrimes __sys_write(fd, s, strlen(s)); 1841590Srgrimes } 1851590Srgrimes snprintf(s, sizeof(s), "(lo)\n"); 1861590Srgrimes __sys_write(fd, s, strlen(s)); 1871590Srgrimes 1881590Srgrimes snprintf(s, sizeof(s), "waitset (hi) "); 1891590Srgrimes __sys_write(fd, s, strlen(s)); 1901590Srgrimes for (i = _SIG_WORDS - 1; i >= 0; i--) { 1911590Srgrimes snprintf(s, sizeof(s), "%08x ", 1921590Srgrimes pthread->data.sigwait->waitset->__bits[i]); 19318730Ssteve __sys_write(fd, s, strlen(s)); 1941590Srgrimes } 1959254Sache snprintf(s, sizeof(s), "(lo)\n"); 1961590Srgrimes __sys_write(fd, s, strlen(s)); 19718730Ssteve break; 1981590Srgrimes /* 19918730Ssteve * Trap other states that are not explicitly 20019344Ssteve * coded to dump information: 2011590Srgrimes */ 2021590Srgrimes default: 2031590Srgrimes snprintf(s, sizeof(s), "sigmask (hi) "); 2041590Srgrimes __sys_write(fd, s, strlen(s)); 2051590Srgrimes for (i = _SIG_WORDS - 1; i >= 0; i--) { 2061590Srgrimes snprintf(s, sizeof(s), "%08x ", 2071590Srgrimes pthread->sigmask.__bits[i]); 20818730Ssteve __sys_write(fd, s, strlen(s)); 2091590Srgrimes } 2101590Srgrimes snprintf(s, sizeof(s), "(lo)\n"); 21192921Simp __sys_write(fd, s, strlen(s)); 21292921Simp break; 21392921Simp } 21492921Simp } 21592921Simp} 21692921Simp 21792921Simp/* Set the thread name for debug: */ 21892921Simpvoid 21992921Simp_pthread_set_name_np(pthread_t thread, char *name) 22092921Simp{ 22192921Simp struct pthread *curthread = _get_curthread(); 22292921Simp char *new_name; 22392921Simp char *prev_name; 22492921Simp int ret; 22592921Simp 226128160Sru new_name = strdup(name); 2271590Srgrimes /* Add a reference to the target thread. */ 22892921Simp if (_thr_ref_add(curthread, thread, 0) != 0) { 2291590Srgrimes free(new_name); 23092921Simp ret = ESRCH; 23192921Simp } 232126824Sru else { 23392921Simp THR_THREAD_LOCK(curthread, thread); 2341590Srgrimes prev_name = thread->name; 2351590Srgrimes thread->name = new_name; 2361590Srgrimes THR_THREAD_UNLOCK(curthread, thread); 2371590Srgrimes _thr_ref_delete(curthread, thread); 2381590Srgrimes if (prev_name != NULL) { 2391590Srgrimes /* Free space for previous name. */ 2401590Srgrimes free(prev_name); 2411590Srgrimes } 2421590Srgrimes ret = 0; 2431590Srgrimes } 2441590Srgrimes#if 0 2451590Srgrimes /* XXX - Should return error code. */ 2461590Srgrimes return (ret); 2471590Srgrimes#endif 248138232Sharti} 2491590Srgrimes