From 45c29f5ba21efd8d40de3d60be84a35dcdae9668 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Mon, 3 Dec 2007 21:21:15 +0000 Subject: [PATCH] Display per-thread command line in TDNAME field for -k and -t; if no per-thread name is available or the name is identical to the process name, display "-" instead. Very slightly shrink the COMM entry to make a bit more room, although this doesn't help with stack traces much. Suggested by: thompsa --- usr.bin/procstat/procstat_kstack.c | 83 ++++++++++++++++++++++------- usr.bin/procstat/procstat_threads.c | 9 ++-- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/usr.bin/procstat/procstat_kstack.c b/usr.bin/procstat/procstat_kstack.c index c36720af10d..c152388d330 100644 --- a/usr.bin/procstat/procstat_kstack.c +++ b/usr.bin/procstat/procstat_kstack.c @@ -127,62 +127,108 @@ void procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag) { struct kinfo_kstack *kkstp, *kkstp_free; + struct kinfo_proc *kip, *kip_free; char trace[KKST_MAXLEN]; - int error, i, name[4]; - size_t len; + int error, i, j, name[4]; + size_t kip_len, kstk_len; if (!hflag) - printf("%5s %6s %-20s %-45s\n", "PID", "TID", "COMM", - "KSTACK"); + printf("%5s %6s %-16s %-16s %-29s\n", "PID", "TID", "COMM", + "TDNAME", "KSTACK"); name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_KSTACK; name[3] = pid; - len = 0; - error = sysctl(name, 4, NULL, &len, NULL, 0); + kstk_len = 0; + error = sysctl(name, 4, NULL, &kstk_len, NULL, 0); if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) { warn("sysctl: kern.proc.kstack: %d", pid); return; } - if (error < 0 && errno == ENOENT) - errx(-1, "kern.proc.kstack sysctl unavailable; options DDB " - "is required."); + if (error < 0 && errno == ENOENT) { + warnx("sysctl: kern.proc.kstack unavailable"); + errx(-1, "options DDB or options STACK required in kernel"); + } if (error < 0) return; - kkstp = kkstp_free = malloc(len); + kkstp = kkstp_free = malloc(kstk_len); if (kkstp == NULL) err(-1, "malloc"); - if (sysctl(name, 4, kkstp, &len, NULL, 0) < 0) { + if (sysctl(name, 4, kkstp, &kstk_len, NULL, 0) < 0) { warn("sysctl: kern.proc.pid: %d", pid); free(kkstp); return; } - kinfo_kstack_sort(kkstp, len / sizeof(*kkstp)); - for (i = 0; i < len / sizeof(*kkstp); i++) { + /* + * We need to re-query for thread information, so don't use *kipp. + */ + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD; + name[3] = pid; + + kip_len = 0; + error = sysctl(name, 4, NULL, &kip_len, NULL, 0); + if (error < 0 && errno != ESRCH) { + warn("sysctl: kern.proc.pid: %d", pid); + return; + } + if (error < 0) + return; + + kip = kip_free = malloc(kip_len); + if (kip == NULL) + err(-1, "malloc"); + + if (sysctl(name, 4, kip, &kip_len, NULL, 0) < 0) { + warn("sysctl: kern.proc.pid: %d", pid); + free(kip); + return; + } + + kinfo_kstack_sort(kkstp, kstk_len / sizeof(*kkstp)); + for (i = 0; i < kstk_len / sizeof(*kkstp); i++) { kkstp = &kkstp_free[i]; + + /* + * Look up the specific thread using its tid so we can + * display the per-thread command line. + */ + kipp = NULL; + for (j = 0; j < kip_len / sizeof(*kipp); j++) { + kipp = &kip_free[j]; + if (kkstp->kkst_tid == kipp->ki_tid) + break; + } + if (kipp == NULL) + continue; + printf("%5d ", pid); printf("%6d ", kkstp->kkst_tid); - printf("%-20s ", kipp->ki_comm); + printf("%-16s ", kipp->ki_comm); + printf("%-16s ", (strlen(kipp->ki_ocomm) && + (strcmp(kipp->ki_comm, kipp->ki_ocomm) != 0)) ? + kipp->ki_ocomm : "-"); switch (kkstp->kkst_state) { case KKST_STATE_RUNNING: - printf("%-45s\n", ""); + printf("%-29s\n", ""); continue; case KKST_STATE_SWAPPED: - printf("%-45s\n", ""); + printf("%-29s\n", ""); continue; case KKST_STATE_STACKOK: break; default: - printf("%-45s\n", ""); + printf("%-29s\n", ""); continue; } @@ -192,7 +238,8 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag) * returns to spaces. */ kstack_cleanup(kkstp->kkst_trace, trace, kflag); - printf("%-45s\n", trace); + printf("%-29s\n", trace); } + free(kip_free); free(kkstp_free); } diff --git a/usr.bin/procstat/procstat_threads.c b/usr.bin/procstat/procstat_threads.c index dbfde79203d..a1cd6e50890 100644 --- a/usr.bin/procstat/procstat_threads.c +++ b/usr.bin/procstat/procstat_threads.c @@ -47,8 +47,8 @@ procstat_threads(pid_t pid, struct kinfo_proc *kipp) size_t len; if (!hflag) - printf("%5s %6s %-20s %2s %4s %-7s %-9s\n", "PID", "TID", - "COMM", "CPU", "PRI", "STATE", "WCHAN"); + printf("%5s %6s %-16s %-16s %2s %4s %-7s %-9s\n", "PID", + "TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN"); /* * We need to re-query for thread information, so don't use *kipp. @@ -82,8 +82,11 @@ procstat_threads(pid_t pid, struct kinfo_proc *kipp) kipp = &kip[i]; printf("%5d ", pid); printf("%6d ", kipp->ki_tid); - printf("%-20s ", strlen(kipp->ki_comm) ? + printf("%-16s ", strlen(kipp->ki_comm) ? kipp->ki_comm : "-"); + printf("%-16s ", (strlen(kipp->ki_ocomm) && + (strcmp(kipp->ki_comm, kipp->ki_ocomm) != 0)) ? + kipp->ki_ocomm : "-"); if (kipp->ki_oncpu != 255) printf("%3d ", kipp->ki_oncpu); else if (kipp->ki_lastcpu != 255)