summaryrefslogtreecommitdiff
path: root/usr/src/cmd/prstat
diff options
context:
space:
mode:
authorJason King <jason.brian.king@gmail.com>2017-05-05 22:58:26 +0000
committerJohn Levon <john.levon@joyent.com>2018-09-26 08:38:04 +0000
commitc113f3b5211bf6ae3ff1ee916a9f9ad0c28b7125 (patch)
treeed3893fad0f78462adf85cf08feb76669ab9abab /usr/src/cmd/prstat
parentdee777b5a3880de62b42997fe61524f95dcc16db (diff)
downloadillumos-joyent-OS-7200.tar.gz
OS-7200 would like thread name APIOS-7200
OS-7205 bhyve makefile uses wrong linker flags
Diffstat (limited to 'usr/src/cmd/prstat')
-rw-r--r--usr/src/cmd/prstat/Makefile.com2
-rw-r--r--usr/src/cmd/prstat/prstat.c140
-rw-r--r--usr/src/cmd/prstat/prstat.h6
-rw-r--r--usr/src/cmd/prstat/prutil.c76
-rw-r--r--usr/src/cmd/prstat/prutil.h3
5 files changed, 171 insertions, 56 deletions
diff --git a/usr/src/cmd/prstat/Makefile.com b/usr/src/cmd/prstat/Makefile.com
index e317483142..96c1450b26 100644
--- a/usr/src/cmd/prstat/Makefile.com
+++ b/usr/src/cmd/prstat/Makefile.com
@@ -21,6 +21,7 @@
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
+# Copyright 2018, Joyent, Inc.
#
# cmd/prstat/Makefile.com
#
@@ -31,6 +32,7 @@ SRCS = $(OBJS:%.o=../%.c)
include ../../Makefile.cmd
+CSTD = $(CSTD_GNU99)
CFLAGS += $(CCVERBOSE)
CERRWARN += -_gcc=-Wno-parentheses
LDLIBS += -lcurses -lproject
diff --git a/usr/src/cmd/prstat/prstat.c b/usr/src/cmd/prstat/prstat.c
index 99fc9ecb28..f40219d75a 100644
--- a/usr/src/cmd/prstat/prstat.c
+++ b/usr/src/cmd/prstat/prstat.c
@@ -26,7 +26,7 @@
* Use is subject to license terms.
*
* Portions Copyright 2009 Chad Mynhier
- * Copyright 2017 Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -87,13 +87,13 @@
#define PSINFO_HEADER_PROC_LGRP \
" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/NLWP "
#define PSINFO_HEADER_LWP \
-" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID "
+" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWP "
#define PSINFO_HEADER_LWP_LGRP \
-" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/LWPID "
+" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/LWP "
#define USAGE_HEADER_PROC \
" PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/NLWP "
#define USAGE_HEADER_LWP \
-" PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID "
+" PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWP "
#define USER_HEADER_PROC \
" NPROC USERNAME SWAP RSS MEMORY TIME CPU "
#define USER_HEADER_LWP \
@@ -111,12 +111,12 @@
#define ZONE_HEADER_LWP \
"ZONEID NLWP SWAP RSS MEMORY TIME CPU ZONE "
#define PSINFO_LINE \
-"%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %-.16s/%d"
+"%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %s"
#define PSINFO_LINE_LGRP \
-"%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %4d %-.16s/%d"
+"%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %4d %s"
#define USAGE_LINE \
"%6d %-8s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s "\
-"%3.3s %3.3s %-.12s/%d"
+"%3.3s %3.3s %s"
#define USER_LINE \
"%6d %-8s %5.5s %5.5s %3.3s%% %9s %3.3s%%"
#define TASK_LINE \
@@ -150,8 +150,8 @@ static table_t prj_tbl = {0, 0, NULL}; /* selected projects */
static table_t tsk_tbl = {0, 0, NULL}; /* selected tasks */
static table_t lgr_tbl = {0, 0, NULL}; /* selected lgroups */
static zonetbl_t zone_tbl = {0, 0, NULL}; /* selected zones */
-static uidtbl_t euid_tbl = {0, 0, NULL}; /* selected effective users */
-static uidtbl_t ruid_tbl = {0, 0, NULL}; /* selected real users */
+static uidtbl_t euid_tbl = {0, 0, NULL}; /* selected effective users */
+static uidtbl_t ruid_tbl = {0, 0, NULL}; /* selected real users */
static uint_t total_procs; /* total number of procs */
static uint_t total_lwps; /* total number of lwps */
@@ -173,7 +173,7 @@ static long pagesize;
/* default settings */
-static optdesc_t opts = {
+optdesc_t opts = {
5, /* interval between updates, seconds */
15, /* number of lines in top part */
5, /* number of lines in bottom part */
@@ -389,11 +389,12 @@ list_print(list_t *list)
char psize[6], prssize[6], pmem[6], pcpu[6], ptime[12];
char pstate[7], pnice[4], ppri[4];
char pname[LOGNAME_MAX+1];
+ char name[PRFNSZ + THREAD_NAME_MAX + 2];
char projname[PROJNAME_MAX+1];
char zonename[ZONENAME_MAX+1];
float cpu, mem;
double loadavg[3] = {0, 0, 0};
- int i, lwpid;
+ int i, n;
if (list->l_size == 0)
return;
@@ -413,54 +414,59 @@ list_print(list_t *list)
(void) putchar('\r');
(void) putp(t_ulon);
+ n = opts.o_cols;
switch (list->l_type) {
case LT_PROJECTS:
if (opts.o_outpmode & OPT_LWPS)
- (void) printf(PROJECT_HEADER_LWP);
+ n = printf(PROJECT_HEADER_LWP);
else
- (void) printf(PROJECT_HEADER_PROC);
+ n = printf(PROJECT_HEADER_PROC);
break;
case LT_TASKS:
if (opts.o_outpmode & OPT_LWPS)
- (void) printf(TASK_HEADER_LWP);
+ n = printf(TASK_HEADER_LWP);
else
- (void) printf(TASK_HEADER_PROC);
+ n = printf(TASK_HEADER_PROC);
break;
case LT_ZONES:
if (opts.o_outpmode & OPT_LWPS)
- (void) printf(ZONE_HEADER_LWP);
+ n = printf(ZONE_HEADER_LWP);
else
- (void) printf(ZONE_HEADER_PROC);
+ n = printf(ZONE_HEADER_PROC);
break;
case LT_USERS:
if (opts.o_outpmode & OPT_LWPS)
- (void) printf(USER_HEADER_LWP);
+ n = printf(USER_HEADER_LWP);
else
- (void) printf(USER_HEADER_PROC);
+ n = printf(USER_HEADER_PROC);
break;
case LT_LWPS:
if (opts.o_outpmode & OPT_LWPS) {
if (opts.o_outpmode & OPT_PSINFO) {
if (opts.o_outpmode & OPT_LGRP)
- (void) printf(PSINFO_HEADER_LWP_LGRP);
+ n = printf(PSINFO_HEADER_LWP_LGRP);
else
- (void) printf(PSINFO_HEADER_LWP);
+ n = printf(PSINFO_HEADER_LWP);
}
if (opts.o_outpmode & OPT_MSACCT)
- (void) printf(USAGE_HEADER_LWP);
+ n = printf(USAGE_HEADER_LWP);
} else {
if (opts.o_outpmode & OPT_PSINFO) {
if (opts.o_outpmode & OPT_LGRP)
- (void) printf(PSINFO_HEADER_PROC_LGRP);
+ n = printf(PSINFO_HEADER_PROC_LGRP);
else
- (void) printf(PSINFO_HEADER_PROC);
+ n = printf(PSINFO_HEADER_PROC);
}
if (opts.o_outpmode & OPT_MSACCT)
- (void) printf(USAGE_HEADER_PROC);
+ n = printf(USAGE_HEADER_PROC);
}
break;
}
+ /* Pad out the header line so the underline spans the whole width */
+ if ((opts.o_outpmode & OPT_TERMCAP) && n < opts.o_cols)
+ (void) printf("%*s", (int)(opts.o_cols - n), "");
+
(void) putp(t_uloff);
(void) putp(t_eol);
(void) putchar('\n');
@@ -527,15 +533,14 @@ list_print(list_t *list)
break;
case LT_LWPS:
lwp = list->l_ptrs[i];
- if (opts.o_outpmode & OPT_LWPS)
- lwpid = lwp->li_info.pr_lwp.pr_lwpid;
- else
- lwpid = lwp->li_info.pr_nlwp +
- lwp->li_info.pr_nzomb;
+
+ format_name(lwp, name, sizeof (name));
+
pwd_getname(lwp->li_info.pr_uid, pname, sizeof (pname),
opts.o_outpmode & OPT_NORESOLVE,
opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
LOGIN_WIDTH);
+
if (opts.o_outpmode & OPT_PSINFO) {
Format_size(psize, lwp->li_info.pr_size, 6);
Format_size(prssize, lwp->li_info.pr_rssize, 6);
@@ -564,21 +569,17 @@ list_print(list_t *list)
lwp->li_info.pr_time.tv_sec, 10);
if (opts.o_outpmode & OPT_TTY)
(void) putchar('\r');
- stripfname(lwp->li_info.pr_fname);
if (opts.o_outpmode & OPT_LGRP) {
(void) printf(PSINFO_LINE_LGRP,
(int)lwp->li_info.pr_pid, pname,
psize, prssize, pstate,
ppri, pnice, ptime, pcpu,
- (int)lwp->li_info.pr_lwp.pr_lgrp,
- lwp->li_info.pr_fname, lwpid);
+ lwp->li_info.pr_lwp.pr_lgrp, name);
} else {
(void) printf(PSINFO_LINE,
(int)lwp->li_info.pr_pid, pname,
- psize, prssize,
- pstate, ppri, pnice,
- ptime, pcpu,
- lwp->li_info.pr_fname, lwpid);
+ psize, prssize, pstate, ppri, pnice,
+ ptime, pcpu, name);
}
(void) putp(t_eol);
(void) putchar('\n');
@@ -598,12 +599,11 @@ list_print(list_t *list)
Format_pct(lat, lwp->li_lat, 4);
if (opts.o_outpmode & OPT_TTY)
(void) putchar('\r');
- stripfname(lwp->li_info.pr_fname);
(void) printf(USAGE_LINE,
(int)lwp->li_info.pr_pid, pname,
usr, sys, trp, tfl, dfl, lck,
slp, lat, vcx, icx, scl, sig,
- lwp->li_info.pr_fname, lwpid);
+ name);
(void) putp(t_eol);
(void) putchar('\n');
}
@@ -905,6 +905,27 @@ add_proc(psinfo_t *psinfo)
}
static void
+get_lwpname(pid_t pid, id_t lwpid, char *buf, size_t bufsize)
+{
+ char *path = NULL;
+ int fd;
+
+ buf[0] = '\0';
+
+ if (asprintf(&path, "/proc/%d/lwp/%d/lwpname",
+ (int)pid, (int)lwpid) == -1)
+ return;
+
+ if ((fd = open(path, O_RDONLY)) != -1) {
+ (void) read(fd, buf, bufsize);
+ buf[bufsize - 1] = '\0';
+ (void) close(fd);
+ }
+
+ free(path);
+}
+
+static void
add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags)
{
lwp_info_t *lwp;
@@ -919,6 +940,7 @@ add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags)
(void) memcpy(&lwp->li_info, psinfo,
sizeof (psinfo_t) - sizeof (lwpsinfo_t));
(void) memcpy(&lwp->li_info.pr_lwp, lwpsinfo, sizeof (lwpsinfo_t));
+ get_lwpname(pid, lwpid, lwp->li_lwpname, sizeof (lwp->li_lwpname));
}
static void
@@ -1141,7 +1163,7 @@ list_refresh(list_t *list)
}
static void
-curses_on()
+curses_on(void)
{
if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) {
(void) initscr();
@@ -1152,7 +1174,7 @@ curses_on()
}
static void
-curses_off()
+curses_off(void)
{
if ((is_curses_on == TRUE) && (opts.o_outpmode & OPT_TERMCAP)) {
(void) putp(t_rmcup);
@@ -1163,26 +1185,40 @@ curses_off()
}
static int
-nlines()
+nlines(int *linesp, int *colsp)
{
struct winsize ws;
char *envp;
int n;
+
+ *linesp = -1;
+ *colsp = -1;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
if (ws.ws_row > 0)
- return (ws.ws_row);
+ *linesp = ws.ws_row;
+ if (ws.ws_col > 0)
+ *colsp = ws.ws_col;
+ if (ws.ws_row > 0 && ws.ws_col > 0)
+ return (0);
}
- if (envp = getenv("LINES")) {
+
+ if ((envp = getenv("LINES")) != NULL) {
if ((n = Atoi(envp)) > 0) {
opts.o_outpmode &= ~OPT_USEHOME;
- return (n);
+ *linesp = n;
+ }
+ }
+ if ((envp = getenv("COLUMNS")) != NULL) {
+ if ((n = Atoi(envp)) > 0) {
+ *colsp = n;
}
}
- return (-1);
+
+ return ((*linesp > 0 && *colsp > 0) ? 0 : -1);
}
static void
-setmovecur()
+setmovecur(void)
{
int i, n;
if ((opts.o_outpmode & OPT_FULLSCREEN) &&
@@ -1212,17 +1248,19 @@ setmovecur()
}
static int
-setsize()
+setsize(void)
{
static int oldn = 0;
- int n;
+ int cols, n, ret;
if (opts.o_outpmode & OPT_FULLSCREEN) {
- n = nlines();
+ ret = nlines(&n, &cols);
+ if (ret != -1)
+ opts.o_cols = cols;
if (n == oldn)
return (0);
oldn = n;
- if (n == -1) {
+ if (ret == -1) {
opts.o_outpmode &= ~OPT_USEHOME;
setmovecur(); /* set default window size */
return (1);
diff --git a/usr/src/cmd/prstat/prstat.h b/usr/src/cmd/prstat/prstat.h
index ddb7416213..7d3913f731 100644
--- a/usr/src/cmd/prstat/prstat.h
+++ b/usr/src/cmd/prstat/prstat.h
@@ -26,7 +26,7 @@
* Use is subject to license terms.
*
* Portions Copyright 2009 Chad Mynhier
- * Copyright 2017 Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc. All rights reserved.
*/
#ifndef _PRSTAT_H
@@ -115,6 +115,7 @@ typedef struct lwp_info {
ulong_t li_icx; /* involuntary context switches */
ulong_t li_scl; /* system calls */
ulong_t li_sig; /* received signals */
+ char li_lwpname[THREAD_NAME_MAX];
struct lwp_info *li_next; /* pointer to next lwp */
struct lwp_info *li_prev; /* pointer to previous lwp */
} lwp_info_t;
@@ -169,8 +170,11 @@ typedef struct optdesc {
int o_count; /* number of iterations */
int o_outpmode; /* selected output mode */
int o_sortorder; /* +1 ascending, -1 descending */
+ int o_cols; /* number of columns */
} optdesc_t;
+extern optdesc_t opts;
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/prstat/prutil.c b/usr/src/cmd/prstat/prutil.c
index 8c90cb2e15..551c72cc8a 100644
--- a/usr/src/cmd/prstat/prutil.c
+++ b/usr/src/cmd/prstat/prutil.c
@@ -25,7 +25,7 @@
* Use is subject to license terms.
*
* Portions Copyright 2009 Chad Mynhier
- * Copyright 2017 Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -325,14 +325,16 @@ getzonename(zoneid_t zoneid, char *str, size_t len, int trunc, size_t width)
/*
* Remove all unprintable characters from process name
*/
-void
-stripfname(char *buf)
+static void
+stripfname(char *buf, size_t bufsize, const char *pname)
{
int bytesleft = PRFNSZ;
wchar_t wchar;
int length;
char *cp;
+ (void) strlcpy(buf, pname, bufsize);
+
buf[bytesleft - 1] = '\0';
for (cp = buf; *cp != '\0'; cp += length) {
@@ -352,3 +354,71 @@ stripfname(char *buf)
bytesleft -= length;
}
}
+
+
+/*
+ * prstat has always implicitly wanted a terminal width of at least 80 columns
+ * (when a TTY is present). If run in a terminal narrower than 80 columns,
+ * prstat output may wrap. For wider terminals, we allow the last column to use
+ * the additional space.
+ *
+ * We never truncate if using -c, or not outputting to a TTY.
+ */
+static int
+format_namewidth(void)
+{
+ int prefixlen = 0;
+
+ if (opts.o_cols == 0 || !(opts.o_outpmode & (OPT_TERMCAP | OPT_TRUNC)))
+ return (0);
+
+ if (opts.o_outpmode & OPT_PSINFO) {
+ if (opts.o_outpmode & OPT_LGRP)
+ prefixlen = 64;
+ else
+ prefixlen = 59;
+ } else if (opts.o_outpmode & OPT_MSACCT) {
+ prefixlen = 64;
+ }
+
+ return (opts.o_cols - prefixlen);
+}
+
+void
+format_name(lwp_info_t *lwp, char *buf, size_t buflen)
+{
+ int pname_width = PRFNSZ;
+ char nr_suffix[20];
+ char pname[PRFNSZ];
+ int width;
+ int n;
+
+ stripfname(pname, sizeof (pname), lwp->li_info.pr_fname);
+
+ if (opts.o_outpmode & OPT_LWPS) {
+ n = snprintf(nr_suffix, sizeof (nr_suffix), "%d",
+ lwp->li_info.pr_lwp.pr_lwpid);
+ } else {
+ n = snprintf(nr_suffix, sizeof (nr_suffix), "%d",
+ lwp->li_info.pr_nlwp + lwp->li_info.pr_nzomb);
+ }
+
+ width = format_namewidth();
+
+ /* If we're over budget, truncate the process name not the LWP part. */
+ if (strlen(pname) > (width - n - 1)) {
+ pname_width = width - n - 1;
+ pname[pname_width - 1] = '*';
+ }
+
+ if ((opts.o_outpmode & OPT_LWPS) && lwp->li_lwpname[0] != '\0') {
+ n = snprintf(buf, buflen, "%.*s/%s [%s]", pname_width,
+ pname, nr_suffix, lwp->li_lwpname);
+ } else {
+ n = snprintf(buf, buflen, "%.*s/%s", pname_width,
+ pname, nr_suffix);
+ }
+
+ if (width > 0 && strlen(buf) > width)
+ buf[width] = '\0';
+}
diff --git a/usr/src/cmd/prstat/prutil.h b/usr/src/cmd/prstat/prutil.h
index cfa2133714..ae2dbe5a93 100644
--- a/usr/src/cmd/prstat/prutil.h
+++ b/usr/src/cmd/prstat/prutil.h
@@ -25,6 +25,7 @@
* Use is subject to license terms.
*
* Portions Copyright 2009 Chad Mynhier
+ * Copyright 2018, Joyent, Inc.
*/
#ifndef _PRUTIL_H
@@ -54,7 +55,7 @@ extern int Setrlimit();
extern void Priocntl(char *);
extern void getprojname(projid_t, char *, size_t, int, int, size_t);
extern void getzonename(projid_t, char *, size_t, int, size_t);
-extern void stripfname(char *);
+extern void format_name(lwp_info_t *, char *, size_t);
#ifdef __cplusplus
}