summaryrefslogtreecommitdiffstats
path: root/lib/libkse/thread/thr_info.c
diff options
context:
space:
mode:
authordeischen <deischen@FreeBSD.org>2000-11-09 05:08:26 +0000
committerdeischen <deischen@FreeBSD.org>2000-11-09 05:08:26 +0000
commit69c0393f8e4b9bd522c1e9afe2f481e040dcbac3 (patch)
treea9d526e7ccca466ce303b1c6202f807942d274db /lib/libkse/thread/thr_info.c
parente1d8dafb1c246b5ecfd3bf52b6e9ff947e171314 (diff)
downloadFreeBSD-src-69c0393f8e4b9bd522c1e9afe2f481e040dcbac3.zip
FreeBSD-src-69c0393f8e4b9bd522c1e9afe2f481e040dcbac3.tar.gz
Don't needlessly poll file descriptors when there are no
file descriptors needing to be polled (Doh!). Reported by Dan Nelson <dnelson@emsphone.com>. Don't install and start the scheduling timer until the first thread is created. This prevents the overhead of having a periodic scheduling signal in a single threaded program. Reported by Dan Nelson <dnelson@emsphone.com>. Allow builtin longjmps out of application installed signal handlers without the need perform any post-handler cleanup: o Change signal handling to save the threads interrupted context on the stack. The threads current context is now always stored in the same place (in the pthread). If and when a signal handler returns, the interrupted context is copied back to the storage area in the pthread. o Before calling invoking a signal handler for a thread, back the thread out of any internal waiting queues (mutex, CV, join, etc) to which it belongs. Rework uthread_info.c a bit to make it easier to change the format of a thread dump. Use an alternal signal stack for the thread library's signal handler. This allows us to fiddle with the main threads stack without fear of it being in use. Reviewed by: jasone
Diffstat (limited to 'lib/libkse/thread/thr_info.c')
-rw-r--r--lib/libkse/thread/thr_info.c225
1 files changed, 100 insertions, 125 deletions
diff --git a/lib/libkse/thread/thr_info.c b/lib/libkse/thread/thr_info.c
index ca91512..956ae7c 100644
--- a/lib/libkse/thread/thr_info.c
+++ b/lib/libkse/thread/thr_info.c
@@ -41,6 +41,13 @@
#include <errno.h>
#include "pthread_private.h"
+#ifndef NELEMENTS
+#define NELEMENTS(arr) (sizeof(arr) / sizeof(arr[0]))
+#endif
+
+static void dump_thread(int fd, pthread_t pthread, int long_version);
+
+
struct s_thread_info {
enum pthread_state state;
char *name;
@@ -77,12 +84,11 @@ _thread_dump_info(void)
char s[512];
int fd;
int i;
- int j;
pthread_t pthread;
char tmpfile[128];
pq_list_t *pq_list;
- for (i = 0; i < 100000; i++) {
+ for (i = 0; i < 100000; i++) {
snprintf(tmpfile, sizeof(tmpfile), "/tmp/uthread.dump.%u.%i",
getpid(), i);
/* Open the dump file for append and create it if necessary: */
@@ -112,70 +118,7 @@ _thread_dump_info(void)
/* Enter a loop to report each thread in the global list: */
TAILQ_FOREACH(pthread, &_thread_list, tle) {
- /* Find the state: */
- for (j = 0; j < (sizeof(thread_info) /
- sizeof(struct s_thread_info)) - 1; j++)
- if (thread_info[j].state == pthread->state)
- break;
- /* Output a record for the current thread: */
- snprintf(s, sizeof(s),
- "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n",
- pthread, (pthread->name == NULL) ?
- "":pthread->name, pthread->base_priority,
- thread_info[j].name,
- pthread->fname,pthread->lineno);
- _thread_sys_write(fd, s, strlen(s));
-
- /* Check if this is the running thread: */
- if (pthread == _thread_run) {
- /* Output a record for the running thread: */
- strcpy(s, "This is the running thread\n");
- _thread_sys_write(fd, s, strlen(s));
- }
- /* Check if this is the initial thread: */
- if (pthread == _thread_initial) {
- /* Output a record for the initial thread: */
- strcpy(s, "This is the initial thread\n");
- _thread_sys_write(fd, s, strlen(s));
- }
- /* Process according to thread state: */
- switch (pthread->state) {
- /* File descriptor read lock wait: */
- case PS_FDLR_WAIT:
- case PS_FDLW_WAIT:
- case PS_FDR_WAIT:
- case PS_FDW_WAIT:
- /* Write the lock details: */
- snprintf(s, sizeof(s), "fd %d[%s:%d]",
- pthread->data.fd.fd,
- pthread->data.fd.fname,
- pthread->data.fd.branch);
- _thread_sys_write(fd, s, strlen(s));
- snprintf(s, sizeof(s), "owner %pr/%pw\n",
- _thread_fd_table[pthread->data.fd.fd]->r_owner,
- _thread_fd_table[pthread->data.fd.fd]->w_owner);
- _thread_sys_write(fd, s, strlen(s));
- break;
- case PS_SIGWAIT:
- snprintf(s, sizeof(s), "sigmask (hi)");
- _thread_sys_write(fd, s, strlen(s));
- for (i = _SIG_WORDS - 1; i >= 0; i--) {
- snprintf(s, sizeof(s), "%08x\n",
- pthread->sigmask.__bits[i]);
- _thread_sys_write(fd, s, strlen(s));
- }
- snprintf(s, sizeof(s), "(lo)\n");
- _thread_sys_write(fd, s, strlen(s));
- break;
-
- /*
- * Trap other states that are not explicitly
- * coded to dump information:
- */
- default:
- /* Nothing to do here. */
- break;
- }
+ dump_thread(fd, pthread, /*long_verson*/ 1);
}
/* Output a header for ready threads: */
@@ -185,19 +128,7 @@ _thread_dump_info(void)
/* Enter a loop to report each thread in the ready queue: */
TAILQ_FOREACH (pq_list, &_readyq.pq_queue, pl_link) {
TAILQ_FOREACH(pthread, &pq_list->pl_head, pqe) {
- /* Find the state: */
- for (j = 0; j < (sizeof(thread_info) /
- sizeof(struct s_thread_info)) - 1; j++)
- if (thread_info[j].state == pthread->state)
- break;
- /* Output a record for the current thread: */
- snprintf(s, sizeof(s),
- "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n",
- pthread, (pthread->name == NULL) ?
- "":pthread->name, pthread->base_priority,
- thread_info[j].name,
- pthread->fname,pthread->lineno);
- _thread_sys_write(fd, s, strlen(s));
+ dump_thread(fd, pthread, /*long_version*/ 0);
}
}
@@ -207,19 +138,7 @@ _thread_dump_info(void)
/* Enter a loop to report each thread in the waiting queue: */
TAILQ_FOREACH (pthread, &_waitingq, pqe) {
- /* Find the state: */
- for (j = 0; j < (sizeof(thread_info) /
- sizeof(struct s_thread_info)) - 1; j++)
- if (thread_info[j].state == pthread->state)
- break;
- /* Output a record for the current thread: */
- snprintf(s, sizeof(s),
- "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n",
- pthread, (pthread->name == NULL) ?
- "":pthread->name, pthread->base_priority,
- thread_info[j].name,
- pthread->fname,pthread->lineno);
- _thread_sys_write(fd, s, strlen(s));
+ dump_thread(fd, pthread, /*long_version*/ 0);
}
/* Output a header for threads in the work queue: */
@@ -228,19 +147,7 @@ _thread_dump_info(void)
/* Enter a loop to report each thread in the waiting queue: */
TAILQ_FOREACH (pthread, &_workq, qe) {
- /* Find the state: */
- for (j = 0; j < (sizeof(thread_info) /
- sizeof(struct s_thread_info)) - 1; j++)
- if (thread_info[j].state == pthread->state)
- break;
- /* Output a record for the current thread: */
- snprintf(s, sizeof(s),
- "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n",
- pthread, (pthread->name == NULL) ?
- "":pthread->name, pthread->base_priority,
- thread_info[j].name,
- pthread->fname,pthread->lineno);
- _thread_sys_write(fd, s, strlen(s));
+ dump_thread(fd, pthread, /*long_version*/ 0);
}
/* Check if there are no dead threads: */
@@ -255,42 +162,38 @@ _thread_dump_info(void)
/*
* Enter a loop to report each thread in the global
- * dead thread list:
+ * dead thread list:
*/
TAILQ_FOREACH(pthread, &_dead_list, dle) {
- /* Output a record for the current thread: */
- snprintf(s, sizeof(s),
- "Thread %p prio %3d [%s:%d]\n",
- pthread, pthread->base_priority,
- pthread->fname,pthread->lineno);
- _thread_sys_write(fd, s, strlen(s));
+ dump_thread(fd, pthread, /*long_version*/ 0);
}
}
/* Output a header for file descriptors: */
- snprintf(s, sizeof(s), "\n\n=============\nFILE DESCRIPTOR TABLE (table size %d)\n\n",_thread_dtablesize);
+ snprintf(s, sizeof(s), "\n\n=============\nFILE DESCRIPTOR "
+ "TABLE (table size %d)\n\n", _thread_dtablesize);
_thread_sys_write(fd, s, strlen(s));
/* Enter a loop to report file descriptor lock usage: */
for (i = 0; i < _thread_dtablesize; i++) {
/*
* Check if memory is allocated for this file
- * descriptor:
+ * descriptor:
*/
if (_thread_fd_table[i] != NULL) {
/* Report the file descriptor lock status: */
snprintf(s, sizeof(s),
- "fd[%3d] read owner %p count %d [%s:%d]\n write owner %p count %d [%s:%d]\n",
- i,
- _thread_fd_table[i]->r_owner,
- _thread_fd_table[i]->r_lockcount,
- _thread_fd_table[i]->r_fname,
- _thread_fd_table[i]->r_lineno,
- _thread_fd_table[i]->w_owner,
- _thread_fd_table[i]->w_lockcount,
- _thread_fd_table[i]->w_fname,
- _thread_fd_table[i]->w_lineno);
- _thread_sys_write(fd, s, strlen(s));
+ "fd[%3d] read owner %p count %d [%s:%d]\n"
+ " write owner %p count %d [%s:%d]\n",
+ i, _thread_fd_table[i]->r_owner,
+ _thread_fd_table[i]->r_lockcount,
+ _thread_fd_table[i]->r_fname,
+ _thread_fd_table[i]->r_lineno,
+ _thread_fd_table[i]->w_owner,
+ _thread_fd_table[i]->w_lockcount,
+ _thread_fd_table[i]->w_fname,
+ _thread_fd_table[i]->w_lineno);
+ _thread_sys_write(fd, s, strlen(s));
}
}
@@ -299,6 +202,78 @@ _thread_dump_info(void)
}
}
+static void
+dump_thread(int fd, pthread_t pthread, int long_version)
+{
+ char s[512];
+ int i;
+
+ /* Find the state: */
+ for (i = 0; i < NELEMENTS(thread_info) - 1; i++)
+ if (thread_info[i].state == pthread->state)
+ break;
+
+ /* Output a record for the thread: */
+ snprintf(s, sizeof(s),
+ "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n",
+ pthread, (pthread->name == NULL) ? "" : pthread->name,
+ pthread->active_priority, thread_info[i].name, pthread->fname,
+ pthread->lineno);
+ _thread_sys_write(fd, s, strlen(s));
+
+ if (long_version != 0) {
+ /* Check if this is the running thread: */
+ if (pthread == _thread_run) {
+ /* Output a record for the running thread: */
+ strcpy(s, "This is the running thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Check if this is the initial thread: */
+ if (pthread == _thread_initial) {
+ /* Output a record for the initial thread: */
+ strcpy(s, "This is the initial thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* File descriptor read lock wait: */
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_FDR_WAIT:
+ case PS_FDW_WAIT:
+ /* Write the lock details: */
+ snprintf(s, sizeof(s), "fd %d[%s:%d]",
+ pthread->data.fd.fd,
+ pthread->data.fd.fname,
+ pthread->data.fd.branch);
+ _thread_sys_write(fd, s, strlen(s));
+ snprintf(s, sizeof(s), "owner %pr/%pw\n",
+ _thread_fd_table[pthread->data.fd.fd]->r_owner,
+ _thread_fd_table[pthread->data.fd.fd]->w_owner);
+ _thread_sys_write(fd, s, strlen(s));
+ break;
+ case PS_SIGWAIT:
+ snprintf(s, sizeof(s), "sigmask (hi)");
+ _thread_sys_write(fd, s, strlen(s));
+ for (i = _SIG_WORDS - 1; i >= 0; i--) {
+ snprintf(s, sizeof(s), "%08x\n",
+ pthread->sigmask.__bits[i]);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ snprintf(s, sizeof(s), "(lo)\n");
+ _thread_sys_write(fd, s, strlen(s));
+ break;
+ /*
+ * Trap other states that are not explicitly
+ * coded to dump information:
+ */
+ default:
+ /* Nothing to do here. */
+ break;
+ }
+ }
+}
+
/* Set the thread name for debug: */
void
pthread_set_name_np(pthread_t thread, char *name)
OpenPOWER on IntegriCloud