summaryrefslogtreecommitdiff
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
parentdee777b5a3880de62b42997fe61524f95dcc16db (diff)
downloadillumos-joyent-OS-7200.tar.gz
OS-7200 would like thread name APIOS-7200
OS-7205 bhyve makefile uses wrong linker flags
-rw-r--r--usr/src/cmd/bhyve/Makefile10
-rw-r--r--usr/src/cmd/bhyve/rfb.c7
-rw-r--r--usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c5
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/Makefile3
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c99
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d26
-rw-r--r--usr/src/cmd/ldapcachemgr/cachemgr_change.c5
-rw-r--r--usr/src/cmd/ldapcachemgr/cachemgr_discovery.c7
-rw-r--r--usr/src/cmd/ldapcachemgr/cachemgr_getldap.c8
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_proc.c23
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/findstack.c28
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/genunix.c18
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/thread.c235
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/thread.h4
-rw-r--r--usr/src/cmd/nscd/cache.c8
-rw-r--r--usr/src/cmd/nscd/nscd_frontend.c13
-rw-r--r--usr/src/cmd/nscd/nscd_getentctx.c10
-rw-r--r--usr/src/cmd/nscd/nscd_selfcred.c8
-rw-r--r--usr/src/cmd/nscd/nscd_smfmonitor.c5
-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
-rw-r--r--usr/src/cmd/ps/ps.c49
-rw-r--r--usr/src/cmd/ptools/pstack/pstack.c66
-rw-r--r--usr/src/cmd/sgs/elfdump/common/corenote.c19
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.msg3
-rw-r--r--usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c2
-rw-r--r--usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c15
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout.h13
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c11
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c11
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c12
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c11
-rw-r--r--usr/src/cmd/sgs/libconv/common/corenote.c5
-rw-r--r--usr/src/cmd/sgs/libconv/common/corenote.msg1
-rw-r--r--usr/src/cmd/svc/startd/graph.c14
-rw-r--r--usr/src/cmd/svc/startd/method.c4
-rw-r--r--usr/src/cmd/svc/startd/restarter.c16
-rw-r--r--usr/src/cmd/svc/startd/wait.c5
-rw-r--r--usr/src/compat/freebsd/pthread_np.h4
-rw-r--r--usr/src/head/pthread.h11
-rw-r--r--usr/src/head/thread.h4
-rw-r--r--usr/src/lib/brand/bhyve/zone/platform.xml1
-rw-r--r--usr/src/lib/libc/inc/thr_uberdata.h4
-rw-r--r--usr/src/lib/libc/port/mapfile-vers8
-rw-r--r--usr/src/lib/libc/port/threads/pthr_attr.c61
-rw-r--r--usr/src/lib/libc/port/threads/pthread.c4
-rw-r--r--usr/src/lib/libc/port/threads/thr.c88
-rw-r--r--usr/src/lib/libdtrace/common/dt_open.c10
-rw-r--r--usr/src/lib/libfakekernel/common/sys/thread.h2
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.h6
-rw-r--r--usr/src/lib/libproc/common/Pcore.c29
-rw-r--r--usr/src/lib/libproc/common/Pgcore.c11
-rw-r--r--usr/src/lib/libproc/common/Plwpregs.c34
-rw-r--r--usr/src/lib/libproc/common/libproc.h3
-rw-r--r--usr/src/lib/libproc/common/mapfile-vers3
-rw-r--r--usr/src/man/man1/ps.133
-rw-r--r--usr/src/man/man1m/prstat.1m9
-rw-r--r--usr/src/man/man3c/Makefile12
-rw-r--r--usr/src/man/man3c/pthread_attr_getname_np.3c105
-rw-r--r--usr/src/man/man3c/pthread_getname_np.3c124
-rw-r--r--usr/src/man/man3c/thr_getname.3c124
-rw-r--r--usr/src/man/man3lib/libproc.3lib60
-rw-r--r--usr/src/man/man3proc/Makefile15
-rw-r--r--usr/src/man/man3proc/Plwp_getname.3proc94
-rw-r--r--usr/src/man/man4/proc.420
-rw-r--r--usr/src/pkg/manifests/system-dtrace-tests.mf4
-rw-r--r--usr/src/pkg/manifests/system-library.man3c.inc9
-rw-r--r--usr/src/pkg/manifests/system-library.man3proc.inc3
-rw-r--r--usr/src/pkg/manifests/system-test-libctest.mf2
-rw-r--r--usr/src/pkg/manifests/system-test-ostest.mf4
-rw-r--r--usr/src/test/libc-tests/runfiles/default.run3
-rw-r--r--usr/src/test/libc-tests/tests/threads/Makefile4
-rw-r--r--usr/src/test/libc-tests/tests/threads/thread_name.c278
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_prctl.c6
-rw-r--r--usr/src/uts/common/disp/thread.c29
-rw-r--r--usr/src/uts/common/dtrace/dtrace.c25
-rw-r--r--usr/src/uts/common/exec/elf/elf_notes.c19
-rw-r--r--usr/src/uts/common/fs/proc/prdata.h5
-rw-r--r--usr/src/uts/common/fs/proc/prvnops.c111
-rw-r--r--usr/src/uts/common/sys/dtrace.h7
-rw-r--r--usr/src/uts/common/sys/elf.h19
-rw-r--r--usr/src/uts/common/sys/procfs.h15
-rw-r--r--usr/src/uts/common/sys/thread.h3
-rw-r--r--usr/src/uts/i86pc/io/viona/viona.c4
87 files changed, 2056 insertions, 379 deletions
diff --git a/usr/src/cmd/bhyve/Makefile b/usr/src/cmd/bhyve/Makefile
index 554603d4f8..a8c772c7f8 100644
--- a/usr/src/cmd/bhyve/Makefile
+++ b/usr/src/cmd/bhyve/Makefile
@@ -83,7 +83,7 @@ OBJS = $(SRCS:.c=.o)
CLOBBERFILES = $(ROOTUSRSBINPROG) $(ZHYVE)
ZHYVE_DIR = $(ROOT)/usr/lib/brand/bhyve
-ZHYVE_PROG = zhyve
+ZHYVE_PROG = zhyve
ZHYVE = $(ZHYVE_DIR)/$(ZHYVE_PROG)
MEVENT_TEST_PROG = mevent_test
@@ -109,9 +109,9 @@ CPPFLAGS = -I$(COMPAT)/freebsd -I$(CONTRIB)/freebsd \
# Disable the crypto code until it is wired up
CPPFLAGS += -DNO_OPENSSL
-LDLIBS += -lsocket -lnsl -ldlpi -ldladm -lmd -luuid -lvmmapi -lz
-
-zhyve := LDLIBS = -lnvpair
+$(PROG) := LDLIBS += -lsocket -lnsl -ldlpi -ldladm -lmd -luuid -lvmmapi -lz
+$(ZHYVE_PROG) := LDLIBS += -lnvpair
+$(MEVENT_TEST_PROG) := LDLIBS += -lsocket
POST_PROCESS += ; $(GENSETDEFS) $@
@@ -124,7 +124,7 @@ $(PROG): $(OBJS)
$(POST_PROCESS)
$(MEVENT_TEST_PROG): $(MEVENT_TEST_OBJS)
- $(LINK.c) -o $@ $(MEVENT_TEST_OBJS) -lsocket
+ $(LINK.c) -o $@ $(MEVENT_TEST_OBJS) $(LDFLAGS) $(LDLIBS)
install: all $(ZHYVE) $(ROOTUSRSBINPROG) $(SUBDIRS)
diff --git a/usr/src/cmd/bhyve/rfb.c b/usr/src/cmd/bhyve/rfb.c
index d96b45c5da..e8c74766fe 100644
--- a/usr/src/cmd/bhyve/rfb.c
+++ b/usr/src/cmd/bhyve/rfb.c
@@ -874,15 +874,8 @@ rfb_handle(struct rfb_softc *rc, int cfd)
rfb_send_screen(rc, cfd, 1);
perror = pthread_create(&tid, NULL, rfb_wr_thr, rc);
-#ifdef __FreeBSD__
if (perror == 0)
pthread_set_name_np(tid, "rfbout");
-#else
- /*
- * While pthread_set_name_np() remains a no-op, skip this to avoid
- * compiler warnings about an empty if-statement.
- */
-#endif
/* Now read in client requests. 1st byte identifies type */
for (;;) {
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
index 5950562fd6..a185068005 100644
--- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
+++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
* Copyright 2016 Argo Technologie SA.
* Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>.
*/
@@ -467,6 +467,7 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op)
(void) pthread_attr_init(&attr);
(void) pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_DETACHED);
+ (void) pthread_attr_setname_np(&attr, "db_restore");
err = pthread_create(&tid, &attr, ipmgmt_db_restore_thread,
NULL);
(void) pthread_attr_destroy(&attr);
@@ -1134,7 +1135,7 @@ ipmgmt_aobjmap_init(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
{
nvpair_t *nvp = NULL;
char *name, *strval = NULL;
- ipmgmt_aobjmap_t node;
+ ipmgmt_aobjmap_t node;
struct sockaddr_in6 *in6;
*errp = 0;
diff --git a/usr/src/cmd/dtrace/test/tst/common/Makefile b/usr/src/cmd/dtrace/test/tst/common/Makefile
index 32d6a1db05..b7e12866c3 100644
--- a/usr/src/cmd/dtrace/test/tst/common/Makefile
+++ b/usr/src/cmd/dtrace/test/tst/common/Makefile
@@ -26,8 +26,8 @@
#
# Copyright (c) 2012 by Delphix. All rights reserved.
-# Copyright (c) 2013, Joyent, Inc. All rights reserved.
# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2018 Joyent, Inc.
#
#
@@ -58,6 +58,7 @@ sysevent/tst.post_chan.exe := LDLIBS += -lsysevent
ustack/tst.bigstack.exe := COPTFLAG += -xO1
GCC = $(ONBLD_TOOLS)/bin/$(MACH)/cw -_gcc
+CSTD = $(CSTD_GNU99)
nfs/%.o: $(SNOOPDIR)/%.c
$(COMPILE.c) -o $@ $< -I$(SNOOPDIR)
diff --git a/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c
new file mode 100644
index 0000000000..49d9f2155c
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c
@@ -0,0 +1,99 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
+/*
+ * All we're doing is constantly modifying a thread name while DTrace is
+ * watching us, making sure we don't break.
+ */
+
+#include <sys/fcntl.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NR_THREADS (100)
+#define RUNTIME (30) /* seconds */
+
+static void
+random_ascii(char *buf, size_t bufsize)
+{
+ char table[] = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,.-#'?!";
+ size_t len = rand() % bufsize;
+
+ bzero(buf, bufsize);
+
+ for (size_t i = 0; i < len; i++) {
+ buf[i] = table[rand() % (sizeof (table) - 1)];
+ }
+}
+
+static void
+busy()
+{
+ struct timeval tv1;
+ struct timeval tv2;
+
+ if (gettimeofday(&tv1, NULL) != 0)
+ abort();
+
+ for (;;) {
+ static volatile int i;
+ for (i = 0; i < 2000000; i++)
+ ;
+
+ if (gettimeofday(&tv2, NULL) != 0)
+ abort();
+
+ /* janky, but we don't care */
+ if (tv2.tv_sec != tv1.tv_sec)
+ return;
+ }
+}
+
+static void *
+thread(void *arg)
+{
+ char name[PTHREAD_MAX_NAMELEN_NP];
+
+ for (size_t i = 0; ; i++) {
+ random_ascii(name, sizeof (name));
+
+ if ((i % 100) == 0) {
+ if (pthread_setname_np(pthread_self(), NULL) != 0)
+ abort();
+ } else {
+ (void) pthread_setname_np(pthread_self(), name);
+ }
+
+ busy();
+ }
+
+ return (NULL);
+}
+
+int
+main(int argc, char **argv)
+{
+ pthread_t tids[NR_THREADS];
+
+ for (size_t i = 0; i < NR_THREADS; i++) {
+ if (pthread_create(&tids[i], NULL, thread, NULL) != 0)
+ exit(EXIT_FAILURE);
+ }
+
+ sleep(RUNTIME);
+ exit(EXIT_SUCCESS);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d
new file mode 100644
index 0000000000..289f6c5bbc
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d
@@ -0,0 +1,26 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
+#pragma D option quiet
+
+profile-10ms /pid == $1 && threadname == "unlikely"/
+{
+ surprising++;
+}
+
+syscall::rexit:entry /pid == $1/
+{
+ exit(arg0);
+}
diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_change.c b/usr/src/cmd/ldapcachemgr/cachemgr_change.c
index 85a15a1054..727851ffbc 100644
--- a/usr/src/cmd/ldapcachemgr/cachemgr_change.c
+++ b/usr/src/cmd/ldapcachemgr/cachemgr_change.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <strings.h>
@@ -33,6 +35,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <procfs.h>
+#include <pthread.h>
#include "cachemgr.h"
extern admin_t current_admin;
@@ -535,6 +538,8 @@ chg_cleanup_waiting_threads(void *arg)
pid_t pid;
int always = 1, waiting;
+ (void) pthread_setname_np(pthread_self(), "chg_cleanup_thr");
+
if (op == NULL) {
waiting = 1;
type = CLEANUP_ALL;
diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c b/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c
index bb352ae7c4..6650c9c221 100644
--- a/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c
+++ b/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#ifdef SLP
@@ -539,9 +541,12 @@ done:
* parameter 'r' should be a pointer to an unsigned int containing
* the requested interval at which the network should be queried.
*/
-void discover(void *r) {
+void
+discover(void *r) {
unsigned short reqrefresh = *((unsigned int *)r);
+ (void) pthread_setname_np(pthread_self(), "discover");
+
for (;;) {
find_all_contexts("ldap",
__cache_get_cfghandle,
diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c b/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
index 298e61fcb0..b9bc3f77b6 100644
--- a/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
+++ b/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
@@ -20,6 +20,8 @@
*/
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <assert.h>
@@ -1631,6 +1633,8 @@ getldap_serverInfo_op(info_op_t op, char *input, char **output)
static time_t prev_refresh = 0, next_refresh = 0;
ns_server_status_t changed = 0;
+ (void) pthread_setname_np(pthread_self(), "getldap_serverinfo");
+
if (current_admin.debug_level >= DBG_ALL) {
logit("getldap_serverInfo_op()...\n");
}
@@ -2542,6 +2546,8 @@ getldap_refresh()
int sig_done = 0;
int dbg_level;
+ (void) pthread_setname_np(pthread_self(), "getldap_refresh");
+
if (current_admin.debug_level >= DBG_ALL) {
logit("getldap_refresh()...\n");
}
@@ -2892,6 +2898,8 @@ remove_server_thread(void *arg)
int up;
rm_svr_t rms;
+ (void) pthread_setname_np(pthread_self(), "remove_server");
+
up = contact_server(addr);
rms.addr = addr;
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_proc.c b/usr/src/cmd/mdb/common/mdb/mdb_proc.c
index 6c9f0aa5f4..33994c11e6 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_proc.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_proc.c
@@ -1303,6 +1303,23 @@ pt_regstatus(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (pt_regs(addr, flags, argc, argv));
}
+static void
+pt_thread_name(mdb_tgt_t *t, mdb_tgt_tid_t tid, char *buf, size_t bufsize)
+{
+ char name[THREAD_NAME_MAX];
+
+ buf[0] = '\0';
+
+ if (t->t_pshandle == NULL ||
+ Plwp_getname(t->t_pshandle, tid, name, sizeof (name)) != 0 ||
+ name[0] == '\0') {
+ (void) mdb_snprintf(buf, bufsize, "%lu", tid);
+ return;
+ }
+
+ (void) mdb_snprintf(buf, bufsize, "%lu [%s]", tid, name);
+}
+
static int
pt_findstack(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv)
{
@@ -1311,6 +1328,7 @@ pt_findstack(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv)
int showargs = 0;
int count;
uintptr_t pc, sp;
+ char name[128];
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
@@ -1334,7 +1352,10 @@ pt_findstack(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv)
#else
sp = gregs.gregs[R_SP];
#endif
- mdb_printf("stack pointer for thread %p: %p\n", tid, sp);
+
+ pt_thread_name(t, tid, name, sizeof (name));
+
+ mdb_printf("stack pointer for thread %s: %p\n", name, sp);
if (pc != 0)
mdb_printf("[ %0?lr %a() ]\n", sp, pc);
diff --git a/usr/src/cmd/mdb/common/modules/genunix/findstack.c b/usr/src/cmd/mdb/common/modules/genunix/findstack.c
index 12b90b8f7d..fc8a4f874b 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/findstack.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/findstack.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * Copyright 2018 Joyent, Inc.
*/
#include <mdb/mdb_modapi.h>
@@ -38,6 +39,12 @@
#include "thread.h"
#include "sobj.h"
+/*
+ * Parts of this file are shared between targets, but this section is only
+ * used for KVM and KMDB.
+ */
+#ifdef _KERNEL
+
int findstack_debug_on = 0;
/*
@@ -48,6 +55,7 @@ print_stack(uintptr_t sp, uintptr_t pc, uintptr_t addr,
int argc, const mdb_arg_t *argv, int free_state)
{
int showargs = 0, count, err;
+ char tdesc[128] = "";
count = mdb_getopts(argc, argv,
'v', MDB_OPT_SETBITS, TRUE, &showargs, NULL);
@@ -57,8 +65,10 @@ print_stack(uintptr_t sp, uintptr_t pc, uintptr_t addr,
if (argc > 1 || (argc == 1 && argv->a_type != MDB_TYPE_STRING))
return (DCMD_USAGE);
- mdb_printf("stack pointer for thread %p%s: %p\n",
- addr, (free_state ? " (TS_FREE)" : ""), sp);
+ (void) thread_getdesc(addr, B_TRUE, tdesc, sizeof (tdesc));
+
+ mdb_printf("stack pointer for thread %p%s (%s): %p\n",
+ addr, (free_state ? " (TS_FREE)" : ""), tdesc, sp);
if (pc != 0)
mdb_printf("[ %0?lr %a() ]\n", sp, pc);
@@ -108,6 +118,8 @@ findstack_debug(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *av)
return (DCMD_OK);
}
+#endif /* _KERNEL */
+
static void
uppercase(char *p)
{
@@ -197,7 +209,7 @@ static stacks_entry_t **stacks_hash;
static stacks_entry_t **stacks_array;
static size_t stacks_array_size;
-size_t
+static size_t
stacks_hash_entry(stacks_entry_t *sep)
{
size_t depth = sep->se_depth;
@@ -224,7 +236,7 @@ stacks_hash_entry(stacks_entry_t *sep)
* relative ordering, so we don't do the extra work of looking up symbols
* for the stack addresses.
*/
-int
+static int
stacks_entry_comp_impl(stacks_entry_t *l, stacks_entry_t *r,
uint_t forsort)
{
@@ -298,7 +310,7 @@ stacks_entry_comp_impl(stacks_entry_t *l, stacks_entry_t *r,
return (0);
}
-int
+static int
stacks_entry_comp(const void *l_arg, const void *r_arg)
{
stacks_entry_t * const *lp = l_arg;
@@ -368,7 +380,7 @@ stacks_cleanup(int force)
}
/*ARGSUSED*/
-int
+static int
stacks_thread_cb(uintptr_t addr, const void *ignored, void *cbarg)
{
stacks_info_t *sip = cbarg;
@@ -421,7 +433,7 @@ stacks_thread_cb(uintptr_t addr, const void *ignored, void *cbarg)
return (WALK_NEXT);
}
-int
+static int
stacks_run_tlist(mdb_pipe_t *tlist, stacks_info_t *si)
{
size_t idx;
@@ -445,7 +457,7 @@ stacks_run_tlist(mdb_pipe_t *tlist, stacks_info_t *si)
return (-1);
}
-int
+static int
stacks_run(int verbose, mdb_pipe_t *tlist)
{
stacks_info_t si;
diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
index 9da3c5eba0..b3b8aea9bc 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
@@ -21,7 +21,7 @@
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -161,20 +161,18 @@ ps_threadprint(uintptr_t addr, const void *data, void *private)
mdb_printf("\tT %?a <%b>\n", addr, t->t_state, t_state_bits);
if (prt_flags & PS_PRTLWPS) {
- char name[THREAD_NAME_MAX];
+ char desc[128] = "";
- mdb_printf("\tL %?a ID: %u", t->t_lwp, t->t_tid);
- if (thread_getname(addr, name, sizeof (name))) {
- mdb_printf(" NAME: %s", name);
- }
- mdb_printf("\n");
+ (void) thread_getdesc(addr, B_FALSE, desc, sizeof (desc));
+
+ mdb_printf("\tL %?a ID: %s\n", t->t_lwp, desc);
}
return (WALK_NEXT);
}
typedef struct mdb_pflags_proc {
- struct pid *p_pidp;
+ struct pid *p_pidp;
ushort_t p_pidflag;
uint_t p_proc_flag;
uint_t p_flag;
@@ -264,8 +262,8 @@ pflags(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
typedef struct mdb_ps_proc {
char p_stat;
- struct pid *p_pidp;
- struct pid *p_pgidp;
+ struct pid *p_pidp;
+ struct pid *p_pgidp;
struct cred *p_cred;
struct sess *p_sessp;
struct task *p_task;
diff --git a/usr/src/cmd/mdb/common/modules/genunix/thread.c b/usr/src/cmd/mdb/common/modules/genunix/thread.c
index 811f29ec66..410f9973d8 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/thread.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/thread.c
@@ -24,7 +24,7 @@
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
*/
@@ -564,6 +564,89 @@ thread_help(void)
}
/*
+ * Return a string description of the thread, including the ID and the thread
+ * name.
+ *
+ * If ->t_name is NULL, and we're a system thread, we'll do a little more
+ * spelunking to find a useful string to return.
+ */
+int
+thread_getdesc(uintptr_t addr, boolean_t include_comm,
+ char *buf, size_t bufsize)
+{
+ char name[THREAD_NAME_MAX] = "";
+ kthread_t t;
+ proc_t p;
+
+ bzero(buf, bufsize);
+
+ if (mdb_vread(&t, sizeof (kthread_t), addr) == -1) {
+ mdb_warn("failed to read kthread_t at %p", addr);
+ return (-1);
+ }
+
+ if (t.t_tid == 0) {
+ taskq_t tq;
+
+ if (mdb_vread(&tq, sizeof (taskq_t),
+ (uintptr_t)t.t_taskq) == -1)
+ tq.tq_name[0] = '\0';
+
+ if (t.t_name != NULL) {
+ if (mdb_readstr(buf, bufsize,
+ (uintptr_t)t.t_name) == -1) {
+ mdb_warn("error reading thread name");
+ }
+ } else if (tq.tq_name[0] != '\0') {
+ (void) mdb_snprintf(buf, bufsize, "tq:%s", tq.tq_name);
+ } else {
+ mdb_snprintf(buf, bufsize, "%a()", t.t_startpc);
+ }
+
+ return (buf[0] == '\0' ? -1 : 0);
+ }
+
+ if (include_comm && mdb_vread(&p, sizeof (proc_t),
+ (uintptr_t)t.t_procp) == -1) {
+ mdb_warn("failed to read proc at %p", t.t_procp);
+ return (-1);
+ }
+
+ if (t.t_name != NULL) {
+ if (mdb_readstr(name, sizeof (name), (uintptr_t)t.t_name) == -1)
+ mdb_warn("error reading thread name");
+
+ /*
+ * Just to be safe -- if mdb_readstr() succeeds, it always NUL
+ * terminates the output, but is unclear what it does on
+ * failure. In that case we attempt to show any partial content
+ * w/ the warning in case it's useful, but explicitly
+ * NUL-terminate to be safe.
+ */
+ buf[bufsize - 1] = '\0';
+ }
+
+ if (name[0] != '\0') {
+ if (include_comm) {
+ (void) mdb_snprintf(buf, bufsize, "%s/%u [%s]",
+ p.p_user.u_comm, t.t_tid, name);
+ } else {
+ (void) mdb_snprintf(buf, bufsize, "%u [%s]",
+ t.t_tid, name);
+ }
+ } else {
+ if (include_comm) {
+ (void) mdb_snprintf(buf, bufsize, "%s/%u",
+ p.p_user.u_comm, t.t_tid);
+ } else {
+ (void) mdb_snprintf(buf, bufsize, "%u", t.t_tid);
+ }
+ }
+
+ return (buf[0] == '\0' ? -1 : 0);
+}
+
+/*
* List a combination of kthread_t and proc_t. Add stack traces in verbose mode.
*/
int
@@ -574,8 +657,6 @@ threadlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
uint_t verbose = FALSE;
uint_t notaskq = FALSE;
kthread_t t;
- taskq_t tq;
- proc_t p;
char cmd[80];
mdb_arg_t cmdarg;
@@ -621,55 +702,32 @@ threadlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (t.t_state == TS_FREE)
return (DCMD_OK);
- if (mdb_vread(&p, sizeof (proc_t), (uintptr_t)t.t_procp) == -1) {
- mdb_warn("failed to read proc at %p", t.t_procp);
- return (DCMD_ERR);
- }
+ if (!verbose) {
+ char desc[128];
- if (mdb_vread(&tq, sizeof (taskq_t), (uintptr_t)t.t_taskq) == -1)
- tq.tq_name[0] = '\0';
+ if (thread_getdesc(addr, B_TRUE, desc, sizeof (desc)) == -1)
+ return (DCMD_ERR);
- if (verbose) {
- mdb_printf("%0?p %?p %?p %3u %3d %?p\n",
- addr, t.t_procp, t.t_lwp, t.t_cid, t.t_pri, t.t_wchan);
+ mdb_printf("%0?p %?p %?p %s\n", addr, t.t_procp, t.t_lwp, desc);
+ return (DCMD_OK);
+ }
- mdb_inc_indent(2);
+ mdb_printf("%0?p %?p %?p %3u %3d %?p\n",
+ addr, t.t_procp, t.t_lwp, t.t_cid, t.t_pri, t.t_wchan);
- mdb_printf("PC: %a", t.t_pc);
- if (t.t_tid == 0) {
- if (tq.tq_name[0] != '\0')
- mdb_printf(" TASKQ: %s\n", tq.tq_name);
- else
- mdb_printf(" THREAD: %a()\n", t.t_startpc);
- } else {
- mdb_printf(" CMD: %s\n", p.p_user.u_psargs);
- }
+ mdb_inc_indent(2);
- mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", count);
- cmdarg.a_type = MDB_TYPE_STRING;
- cmdarg.a_un.a_str = cmd;
+ mdb_printf("PC: %a\n", t.t_pc);
- (void) mdb_call_dcmd("findstack", addr, flags, 1, &cmdarg);
+ mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", count);
+ cmdarg.a_type = MDB_TYPE_STRING;
+ cmdarg.a_un.a_str = cmd;
- mdb_dec_indent(2);
+ (void) mdb_call_dcmd("findstack", addr, flags, 1, &cmdarg);
- mdb_printf("\n");
- } else {
- mdb_printf("%0?p %?p %?p", addr, t.t_procp, t.t_lwp);
- if (t.t_tid == 0) {
- if (tq.tq_name[0] != '\0')
- mdb_printf(" tq:%s\n", tq.tq_name);
- else
- mdb_printf(" %a()\n", t.t_startpc);
- } else {
- char name[THREAD_NAME_MAX];
+ mdb_dec_indent(2);
- mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid);
- if (thread_getname(addr, name, sizeof (name)))
- mdb_printf(" [%s]", name);
- mdb_printf("\n");
- }
- }
+ mdb_printf("\n");
return (DCMD_OK);
}
@@ -724,7 +782,6 @@ int
stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
kthread_t t;
- proc_t p;
uint64_t *ptr; /* pattern pointer */
caddr_t start; /* kernel stack start */
caddr_t end; /* kernel stack end */
@@ -738,6 +795,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
int i = 0;
unsigned int ukmem_stackinfo;
uintptr_t allthreads;
+ char tdesc[128] = "";
/* handle options */
if (mdb_getopts(argc, argv,
@@ -783,7 +841,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf("%<u>%?s%</u>", "THREAD");
mdb_printf(" %<u>%?s%</u>", "STACK");
- mdb_printf("%<u>%s%</u>", " SIZE MAX CMD/LWPID or STARTPC");
+ mdb_printf("%<u>%s%</u>", " SIZE MAX LWP");
mdb_printf("\n");
usize = KMEM_STKINFO_LOG_SIZE * sizeof (kmem_stkinfo_t);
log = (kmem_stkinfo_t *)mdb_alloc(usize, UM_SLEEP);
@@ -806,18 +864,15 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (log[i].kthread == NULL) {
continue;
}
- mdb_printf("%0?p %0?p %6x %3d%%",
+
+ (void) thread_getdesc((uintptr_t)log[i].kthread,
+ B_TRUE, tdesc, sizeof (tdesc));
+
+ mdb_printf("%0?p %0?p %6x %3d%% %s\n",
log[i].kthread,
log[i].start,
(uint_t)log[i].stksz,
- (int)log[i].percent);
- if (log[i].t_tid != 0) {
- mdb_printf(" %s/%u\n",
- log[i].cmd, log[i].t_tid);
- } else {
- mdb_printf(" %p (%a)\n", log[i].t_startpc,
- log[i].t_startpc);
- }
+ (int)log[i].percent, tdesc);
}
mdb_free((void *)log, usize);
return (DCMD_OK);
@@ -832,7 +887,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
mdb_printf("%<u>%?s%</u>", "THREAD");
mdb_printf(" %<u>%?s%</u>", "STACK");
- mdb_printf("%<u>%s%</u>", " SIZE CUR MAX CMD/LWPID");
+ mdb_printf("%<u>%s%</u>", " SIZE CUR MAX LWP");
mdb_printf("\n");
}
@@ -846,12 +901,6 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
- /* read proc */
- if (mdb_vread(&p, sizeof (proc_t), (uintptr_t)t.t_procp) == -1) {
- mdb_warn("failed to read proc at %p\n", t.t_procp);
- return (DCMD_ERR);
- }
-
/*
* Stack grows up or down, see thread_create(),
* compute stack memory aera start and end (start < end).
@@ -886,14 +935,10 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf(" %3d%%", percent);
percent = 0;
+ (void) thread_getdesc(addr, B_TRUE, tdesc, sizeof (tdesc));
+
if (ukmem_stackinfo == 0) {
- mdb_printf(" n/a");
- if (t.t_tid == 0) {
- mdb_printf(" %a()", t.t_startpc);
- } else {
- mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid);
- }
- mdb_printf("\n");
+ mdb_printf(" n/a %s\n", tdesc);
return (DCMD_OK);
}
@@ -966,12 +1011,9 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
} else {
mdb_printf(" n/a");
}
- if (t.t_tid == 0) {
- mdb_printf(" %a()", t.t_startpc);
- } else {
- mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid);
- }
- mdb_printf("\n");
+
+ mdb_printf(" %s\n", tdesc);
+
mdb_free((void *)ustack, usize + 8);
return (DCMD_OK);
}
@@ -986,7 +1028,7 @@ stackinfo_help(void)
"(an unsigned integer) is non zero at kthread creation time. ");
mdb_printf("For example:\n");
mdb_printf(
- " THREAD STACK SIZE CUR MAX CMD/LWPID\n");
+ " THREAD STACK SIZE CUR MAX LWP\n");
mdb_printf(
"ffffff014f5f2c20 ffffff0004153000 4f00 4%% 43%% init/1\n");
mdb_printf(
@@ -1013,46 +1055,3 @@ stackinfo_help(void)
"\nSee illumos Modular Debugger Guide for detailed usage.\n");
mdb_flush();
}
-
-/* If the field is not present in the target, return an empty (0 length) name */
-boolean_t
-thread_getname(uintptr_t addr, char *namep, size_t namelen)
-{
- mdb_ctf_id_t id;
- ulong_t offset;
- uintptr_t nameaddr;
-
- bzero(namep, namelen);
-
- if (mdb_ctf_lookup_by_name("kthread_t", &id) == -1)
- return (B_FALSE);
-
- if (mdb_ctf_offsetof(id, "t_name", &offset) == -1)
- return (B_FALSE);
-
- if (offset % 8 != 0) {
- mdb_warn("kthread_t.t_name is not on a byte boundary");
- return (B_FALSE);
- }
- offset /= 8;
-
- if (mdb_vread(&nameaddr, sizeof (nameaddr), addr + offset) !=
- sizeof (nameaddr)) {
- mdb_warn("could not read address of thread name buffer");
- return (B_FALSE);
- }
-
- if (nameaddr != 0 && mdb_readstr(namep, namelen, addr + offset) == -1) {
- mdb_warn("error reading thread name");
- /*
- * Just to be safe -- if mdb_readstr() succeeds, it always
- * NUL terminates the output, but is unclear what it does
- * on failure. In that case we attempt to show any partial
- * content w/ the warning in case it's useful, but explicity
- * NUL terminate to be safe.
- */
- namep[namelen - 1] = '\0';
- }
-
- return (strlen(namep) > 0 ? B_TRUE : B_FALSE);
-}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/thread.h b/usr/src/cmd/mdb/common/modules/genunix/thread.h
index 9763781008..901d962be8 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/thread.h
+++ b/usr/src/cmd/mdb/common/modules/genunix/thread.h
@@ -22,7 +22,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
*/
#ifndef _THREAD_H
@@ -60,7 +60,7 @@ void thread_state_to_text(uint_t, char *, size_t);
int thread_text_to_state(const char *, uint_t *);
void thread_walk_states(void (*)(uint_t, const char *, void *), void *);
-boolean_t thread_getname(uintptr_t, char *, size_t);
+int thread_getdesc(uintptr_t, boolean_t, char *, size_t);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/nscd/cache.c b/usr/src/cmd/nscd/cache.c
index 2ffb95c30d..050154122c 100644
--- a/usr/src/cmd/nscd/cache.c
+++ b/usr/src/cmd/nscd/cache.c
@@ -22,6 +22,7 @@
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -48,6 +49,7 @@
#include <string.h>
#include <umem.h>
#include <fcntl.h>
+#include <pthread.h>
#include "cache.h"
#include "nscd_door.h"
#include "nscd_log.h"
@@ -1817,6 +1819,8 @@ init_cache_ctx(int i) {
static void
revalidate(nsc_ctx_t *ctx)
{
+ (void) pthread_setname_np(pthread_self(), "revalidate");
+
for (;;) {
int i, slp, interval, count;
@@ -1961,6 +1965,8 @@ static void
do_update(nsc_lookup_args_t *in) {
nss_pheader_t *phdr = (nss_pheader_t *)in->buffer;
+ (void) pthread_setname_np(pthread_self(), "do_update");
+
/* update the length of the data buffer */
phdr->data_len = phdr->pbufsiz - phdr->data_off;
@@ -2190,6 +2196,8 @@ reaper(nsc_ctx_t *ctx)
ulong_t nsc_entries;
char *me = "reaper";
+ (void) pthread_setname_np(pthread_self(), "reaper");
+
for (;;) {
(void) mutex_lock(&ctx->stats_mutex);
nsc_entries = ctx->stats.entries;
diff --git a/usr/src/cmd/nscd/nscd_frontend.c b/usr/src/cmd/nscd/nscd_frontend.c
index 7ed5e71bca..ea86b6e742 100644
--- a/usr/src/cmd/nscd/nscd_frontend.c
+++ b/usr/src/cmd/nscd/nscd_frontend.c
@@ -22,6 +22,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#include <stdlib.h>
@@ -89,6 +90,8 @@ server_tsd_bind(void *arg)
{
static void *value = 0;
+ (void) pthread_setname_np(pthread_self(), "server_tsd_bind");
+
/* disable cancellation to avoid hangs if server threads disappear */
(void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
(void) thr_setspecific(server_key, value);
@@ -132,7 +135,8 @@ server_destroy(void *arg)
* get clearance
*/
int
-_nscd_get_clearance(sema_t *sema) {
+_nscd_get_clearance(sema_t *sema)
+{
if (sema_trywait(&common_sema) == 0) {
(void) thr_setspecific(lookup_state_key, NULL);
return (0);
@@ -151,7 +155,8 @@ _nscd_get_clearance(sema_t *sema) {
* release clearance
*/
int
-_nscd_release_clearance(sema_t *sema) {
+_nscd_release_clearance(sema_t *sema)
+{
int which;
(void) thr_getspecific(lookup_state_key, (void**)&which);
@@ -197,7 +202,7 @@ _nscd_restart_if_cfgfile_changed()
static timestruc_t last_nsswitch_modified = { 0 };
static timestruc_t last_resolv_modified = { -1, 0 };
static mutex_t restarting_lock = DEFAULTMUTEX;
- static int restarting = 0;
+ static int restarting = 0;
int restart = 0;
time_t now = time(NULL);
char *me = "_nscd_restart_if_cfgfile_changed";
@@ -1477,6 +1482,8 @@ rts_mon(void)
struct ifa_msghdr *ifam = &mbuf.ifam;
char *me = "rts_mon";
+ (void) pthread_setname_np(pthread_self(), me);
+
rt_sock = socket(PF_ROUTE, SOCK_RAW, 0);
if (rt_sock < 0) {
_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
diff --git a/usr/src/cmd/nscd/nscd_getentctx.c b/usr/src/cmd/nscd/nscd_getentctx.c
index 2fed9a5c82..bebd7be19f 100644
--- a/usr/src/cmd/nscd/nscd_getentctx.c
+++ b/usr/src/cmd/nscd/nscd_getentctx.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/ccompile.h>
@@ -30,6 +32,7 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
+#include <pthread.h>
#include "nscd_db.h"
#include "nscd_log.h"
@@ -658,6 +661,8 @@ reclaim_getent_ctx(void *arg)
nss_getent_t nssctx = { 0 };
char *me = "reclaim_getent_ctx";
+ (void) pthread_setname_np(pthread_self(), me);
+
/*CONSTCOND*/
while (1) {
@@ -744,7 +749,8 @@ reclaim_getent_ctx(void *arg)
}
static nscd_rc_t
-_nscd_init_getent_ctx_monitor() {
+_nscd_init_getent_ctx_monitor()
+{
int errnum;
char *me = "_nscd_init_getent_ctx_monitor";
@@ -763,7 +769,7 @@ _nscd_init_getent_ctx_monitor() {
* start a thread to reclaim unused getent contexts
*/
if (thr_create(NULL, NULL, reclaim_getent_ctx,
- NULL, THR_DETACHED, NULL) != 0) {
+ NULL, THR_DETACHED, NULL) != 0) {
errnum = errno;
_NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR)
(me, "thr_create: %s\n", strerror(errnum));
diff --git a/usr/src/cmd/nscd/nscd_selfcred.c b/usr/src/cmd/nscd/nscd_selfcred.c
index df4d2a2c5b..bc56fc19c7 100644
--- a/usr/src/cmd/nscd/nscd_selfcred.c
+++ b/usr/src/cmd/nscd/nscd_selfcred.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2018 Joyent Inc.
*/
#include <stdio.h>
@@ -44,6 +45,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <libscf.h>
+#include <pthread.h>
#include "nscd_door.h"
#include "nscd_config.h"
#include "nscd_log.h"
@@ -425,6 +427,8 @@ forker_monitor(
char *fmri;
char *me = "forker_monitor";
+ (void) pthread_setname_np(pthread_self(), me);
+
/* wait until forker exits */
fpid = forker_pid;
(void) selfcred_pulse(forking_door);
@@ -1416,7 +1420,7 @@ check_uid(char *pid_name)
static uid_t uid = 0;
static uid_t euid = 0;
int pfd; /* file descriptor for /proc/<pid>/psinfo */
- psinfo_t info; /* process information from /proc */
+ psinfo_t info; /* process information from /proc */
if (uid == 0) {
pid = getpid();
@@ -1466,6 +1470,8 @@ check_user_process(void *arg)
int found;
char *me = "check_user_process";
+ (void) pthread_setname_np(pthread_self(), me);
+
for (;;) {
(void) sleep(60);
diff --git a/usr/src/cmd/nscd/nscd_smfmonitor.c b/usr/src/cmd/nscd/nscd_smfmonitor.c
index bd2ff958ba..5cd179a8e2 100644
--- a/usr/src/cmd/nscd/nscd_smfmonitor.c
+++ b/usr/src/cmd/nscd/nscd_smfmonitor.c
@@ -21,11 +21,14 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <stdlib.h>
#include <libscf.h>
#include <string.h>
+#include <pthread.h>
#include "nscd_switch.h"
#include "nscd_log.h"
#include "nscd_door.h"
@@ -107,6 +110,8 @@ set_smf_state(void *arg)
int i;
int st;
+ (void) pthread_setname_np(pthread_self(), "set_smf_state");
+
/*
* the forker nscd needs not monitor the state
* of the client services
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
}
diff --git a/usr/src/cmd/ps/ps.c b/usr/src/cmd/ps/ps.c
index 2773444803..45ffc3a6cf 100644
--- a/usr/src/cmd/ps/ps.c
+++ b/usr/src/cmd/ps/ps.c
@@ -27,11 +27,11 @@
*/
/*
- * Copyright 2015 Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
+/* All Rights Reserved */
/*
* ps -- print things about processes.
@@ -108,6 +108,7 @@ enum fname { /* enumeration of field names */
F_SID, /* session id */
F_PSR, /* bound processor */
F_LWP, /* lwp-id */
+ F_LWPNAME, /* lwp name */
F_NLWP, /* number of lwps */
F_OPRI, /* old priority (obsolete) */
F_PRI, /* new priority */
@@ -177,6 +178,7 @@ static struct def_field fname[] = {
{ "sid", "SID", 5, 5 },
{ "psr", "PSR", 3, 2 },
{ "lwp", "LWP", 6, 2 },
+ { "lwpname", "LWPNAME", 32, 8 },
{ "nlwp", "NLWP", 4, 2 },
{ "opri", "PRI", 3, 2 },
{ "pri", "PRI", 3, 2 },
@@ -211,8 +213,8 @@ static struct def_field fname[] = {
{ "zone", "ZONE", 8, 8 },
{ "zoneid", "ZONEID", 5, 5 },
{ "ctid", "CTID", 5, 5 },
- { "lgrp", "LGRP", 4, 2 },
- { "dmodel", "DMODEL", 6, 6 },
+ { "lgrp", "LGRP", 4, 2 },
+ { "dmodel", "DMODEL", 6, 6 },
};
#define NFIELDS (sizeof (fname) / sizeof (fname[0]))
@@ -811,6 +813,7 @@ stdmain(int argc, char **argv)
(void) printf("%-*s",
f->width, f->header);
break;
+ case F_LWPNAME:
case F_FNAME:
case F_COMM:
case F_ARGS:
@@ -1186,7 +1189,8 @@ parse_format(char *arg)
}
for (df = &fname[0]; df < &fname[NFIELDS]; df++)
if (strcmp(name, df->fname) == 0) {
- if (strcmp(name, "lwp") == 0)
+ if (strcmp(name, "lwp") == 0 ||
+ strcmp(name, "lwpname") == 0)
Lflg++;
break;
}
@@ -1762,6 +1766,27 @@ print_field(psinfo_t *psinfo, struct field *f, const char *ttyp)
case F_LWP:
(void) printf("%*d", width, (int)psinfo->pr_lwp.pr_lwpid);
break;
+ case F_LWPNAME: {
+ char lwpname[THREAD_NAME_MAX] = "";
+ char *path = NULL;
+ int fd;
+
+ if (asprintf(&path, "/proc/%d/lwp/%d/lwpname",
+ (int)psinfo->pr_pid, (int)psinfo->pr_lwp.pr_lwpid) != -1 &&
+ (fd = open(path, O_RDONLY)) != -1) {
+ (void) read(fd, lwpname, sizeof (lwpname));
+ lwpname[THREAD_NAME_MAX - 1] = '\0';
+ (void) close(fd);
+ }
+
+ free(path);
+
+ if (f->next != NULL)
+ (void) printf("%-*s", width, lwpname);
+ else
+ (void) printf("%s", lwpname);
+ break;
+ }
case F_NLWP:
(void) printf("%*d", width, psinfo->pr_nlwp + psinfo->pr_nzomb);
break;
@@ -2375,7 +2400,7 @@ przom(psinfo_t *psinfo)
}
if (fflg) {
int width = fname[F_STIME].width;
- (void) printf(" %*.*s", width, width, "-"); /* STIME */
+ (void) printf(" %*.*s", width, width, "-"); /* STIME */
}
(void) printf(" %-8.14s", "?"); /* TTY */
@@ -2455,9 +2480,9 @@ delta_secs(const timestruc_t *start)
/*
* Returns the following:
*
- * 0 No error
- * EINVAL Invalid number
- * ERANGE Value exceeds (min, max) range
+ * 0 No error
+ * EINVAL Invalid number
+ * ERANGE Value exceeds (min, max) range
*/
static int
str2id(const char *p, pid_t *val, long min, long max)
@@ -2492,9 +2517,9 @@ str2id(const char *p, pid_t *val, long min, long max)
/*
* Returns the following:
*
- * 0 No error
- * EINVAL Invalid number
- * ERANGE Value exceeds (min, max) range
+ * 0 No error
+ * EINVAL Invalid number
+ * ERANGE Value exceeds (min, max) range
*/
static int
str2uid(const char *p, uid_t *val, unsigned long min, unsigned long max)
diff --git a/usr/src/cmd/ptools/pstack/pstack.c b/usr/src/cmd/ptools/pstack/pstack.c
index 0515ff62d0..d1d55d2280 100644
--- a/usr/src/cmd/ptools/pstack/pstack.c
+++ b/usr/src/cmd/ptools/pstack/pstack.c
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/isa_defs.h>
@@ -137,7 +139,7 @@ static int thr_stack(const td_thrhandle_t *, void *);
static void free_threadinfo(void);
static struct threadinfo *find_thread(id_t);
static int all_call_stacks(pstack_handle_t *, int);
-static void tlhead(id_t, id_t);
+static void tlhead(id_t, id_t, const char *);
static int print_frame(void *, prgregset_t, uint_t, const long *);
static void print_zombie(struct ps_prochandle *, struct threadinfo *);
static void print_syscall(const lwpstatus_t *, prgregset_t);
@@ -380,6 +382,7 @@ static int
thread_call_stack(void *data, const lwpstatus_t *psp,
const lwpsinfo_t *pip)
{
+ char lwpname[THREAD_NAME_MAX] = "";
pstack_handle_t *h = data;
lwpstatus_t lwpstatus;
struct threadinfo *tip;
@@ -391,7 +394,10 @@ thread_call_stack(void *data, const lwpstatus_t *psp,
if ((tip = find_thread(pip->pr_lwpid)) == NULL)
return (0);
- tlhead(tip->threadid, pip->pr_lwpid);
+ (void) Plwp_getname(h->proc, pip->pr_lwpid,
+ lwpname, sizeof (lwpname));
+
+ tlhead(tip->threadid, pip->pr_lwpid, lwpname);
tip->threadid = 0; /* finish eliminating tid */
if (psp)
call_stack(h, psp);
@@ -410,15 +416,19 @@ thread_call_stack(void *data, const lwpstatus_t *psp,
static int
lwp_call_stack(void *data,
- const lwpstatus_t *psp, const lwpsinfo_t *pip)
+ const lwpstatus_t *psp, const lwpsinfo_t *pip)
{
+ char lwpname[THREAD_NAME_MAX] = "";
pstack_handle_t *h = data;
if (!proc_lwp_in_set(h->lwps, pip->pr_lwpid))
return (0);
h->count++;
- tlhead(0, pip->pr_lwpid);
+ (void) Plwp_getname(h->proc, pip->pr_lwpid,
+ lwpname, sizeof (lwpname));
+
+ tlhead(0, pip->pr_lwpid, lwpname);
if (psp)
call_stack(h, psp);
else
@@ -462,7 +472,7 @@ all_call_stacks(pstack_handle_t *h, int dothreads)
if ((tid = tip->threadid) != 0) {
(void) memcpy(lwpstatus.pr_reg, tip->regs,
sizeof (prgregset_t));
- tlhead(tid, tip->lwpid);
+ tlhead(tid, tip->lwpid, NULL);
if (tip->state == TD_THR_ZOMBIE)
print_zombie(Pr, tip);
else
@@ -475,23 +485,49 @@ all_call_stacks(pstack_handle_t *h, int dothreads)
return (0);
}
+/* The width of the header */
+#define HEAD_WIDTH (62)
static void
-tlhead(id_t threadid, id_t lwpid)
+tlhead(id_t threadid, id_t lwpid, const char *name)
{
+ char buf[128] = { 0 };
+ char num[16];
+ ssize_t amt = 0;
+ int i;
+
if (threadid == 0 && lwpid == 0)
return;
- (void) printf("-----------------");
+ if (lwpid > 0) {
+ (void) snprintf(num, sizeof (num), "%d", (int)lwpid);
+ (void) strlcat(buf, "thread# ", sizeof (buf));
+ (void) strlcat(buf, num, sizeof (buf));
+ }
+
+ if (threadid > 0) {
+ (void) snprintf(num, sizeof (num), "%d", (int)threadid);
+ if (lwpid > 0)
+ (void) strlcat(buf, " / ", sizeof (buf));
+ (void) strlcat(buf, "lwp# ", sizeof (buf));
+ (void) strlcat(buf, num, sizeof (buf));
+ }
+
+ if (name != NULL && strlen(name) > 0) {
+ (void) strlcat(buf, " [", sizeof (buf));
+ (void) strlcat(buf, name, sizeof (buf));
+ (void) strlcat(buf, "]", sizeof (buf));
+ }
- if (threadid && lwpid)
- (void) printf(" lwp# %d / thread# %d ",
- (int)lwpid, (int)threadid);
- else if (threadid)
- (void) printf("--------- thread# %d ", (int)threadid);
- else if (lwpid)
- (void) printf(" lwp# %d ------------", (int)lwpid);
+ amt = (HEAD_WIDTH - strlen(buf) - 2);
+ if (amt < 4)
+ amt = 4;
- (void) printf("--------------------\n");
+ for (i = 0; i < amt / 2; i++)
+ (void) putc('-', stdout);
+ (void) printf(" %s ", buf);
+ for (i = 0; i < (amt / 2) + (amt % 2); i++)
+ (void) putc('-', stdout);
+ (void) putc('\n', stdout);
}
/*ARGSUSED*/
diff --git a/usr/src/cmd/sgs/elfdump/common/corenote.c b/usr/src/cmd/sgs/elfdump/common/corenote.c
index 0777025523..a5ba4e31b8 100644
--- a/usr/src/cmd/sgs/elfdump/common/corenote.c
+++ b/usr/src/cmd/sgs/elfdump/common/corenote.c
@@ -1256,6 +1256,20 @@ dump_prstatus(note_state_t *state, const char *title)
}
+static void
+dump_lwpname(note_state_t *state, const char *title)
+{
+ const sl_prlwpname_layout_t *layout = state->ns_arch->prlwpname;
+
+ indent_enter(state, title, &layout->pr_lwpid);
+
+ PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_LWPID), pr_lwpid);
+ PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_LWPNAME), pr_lwpname);
+
+ indent_exit(state);
+}
+
+
/*
* Print percent from 16-bit binary fraction [0 .. 1]
* Round up .01 to .1 to indicate some small percentage (the 0x7000 below).
@@ -1909,6 +1923,11 @@ corenote(Half mach, int do_swap, Word type,
state.ns_v2col = 54;
dump_secflags(&state, MSG_ORIG(MSG_CNOTE_DESC_PRSECFLAGS_T));
return (CORENOTE_R_OK);
+
+ case NT_LWPNAME:
+ state.ns_vcol = 20;
+ dump_lwpname(&state, MSG_ORIG(MSG_CNOTE_DESC_PRLWPNAME_T));
+ return (CORENOTE_R_OK);
}
return (CORENOTE_R_BADTYPE);
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
index e7488d5373..253ea4a788 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
@@ -22,6 +22,7 @@
#
# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+# Copyright 2018 Joyent, Inc.
#
@ _START_
@@ -469,6 +470,7 @@
@ MSG_CNOTE_DESC_STRUCT_UTSNAME "desc: (struct utsname)"
@ MSG_CNOTE_DESC_PRFDINFO_T "desc: (prfdinfo_t)"
@ MSG_CNOTE_DESC_PRSECFLAGS_T "desc: (prsecflags_t)"
+@ MSG_CNOTE_DESC_PRLWPNAME_T "desc: (prlwpname_t)"
@ MSG_CNOTE_FMT_LINE "%*s%-*s%s"
@ MSG_CNOTE_FMT_LINE_2UP "%*s%-*s%-*s%-*s%s"
@@ -535,6 +537,7 @@
@ MSG_CNOTE_T_PR_LWP "pr_lwp:"
@ MSG_CNOTE_T_PR_LWPHOLD "pr_lwphold:"
@ MSG_CNOTE_T_PR_LWPID "pr_lwpid:"
+@ MSG_CNOTE_T_PR_LWPNAME "pr_lwpname:"
@ MSG_CNOTE_T_PR_LWPPEND "pr_lwppend:"
@ MSG_CNOTE_T_PR_NAME "pr_name:"
@ MSG_CNOTE_T_PR_NGROUPS "pr_ngroups:"
diff --git a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
index f7af1c1543..674972dc22 100644
--- a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
+++ b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
@@ -11,6 +11,7 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -58,3 +59,4 @@ timestruc_t ts;
struct utsname uts;
prfdinfo_t ptfd;
prsecflags_t psf;
+prlwpname_t psn;
diff --git a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
index d90363c5de..10d6a00af7 100644
--- a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
+++ b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
@@ -24,11 +24,13 @@
* Use is subject to license terms.
*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
/*
* This program is used to generate the contents of the
- * struct_layout_XXX.c files that contain per-archtecture
+ * struct_layout_XXX.c files that contain per-architecture
* structure layout information.
*
* Although not part of elfdump, it is built by the makefile
@@ -599,6 +601,15 @@ gen_prsecflags(void)
END;
}
+static void
+gen_prlwpname(void)
+{
+ START(prlwpname, prlwpname_t);
+ SCALAR_FIELD(prlwpname_t, pr_lwpid, 0);
+ ARRAY_FIELD(prlwpname_t, pr_lwpname, 0);
+ END;
+}
+
/*ARGSUSED*/
int
main(int argc, char *argv[])
@@ -640,6 +651,7 @@ main(int argc, char *argv[])
gen_utsname();
gen_prfdinfo();
gen_prsecflags();
+ gen_prlwpname();
/*
* Generate the full arch_layout description
@@ -668,6 +680,7 @@ main(int argc, char *argv[])
(void) printf(fmt, "utsname");
(void) printf(fmt, "prfdinfo");
(void) printf(fmt, "prsecflags");
+ (void) printf(fmt, "prlwpname");
(void) printf("};\n");
/*
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout.h b/usr/src/cmd/sgs/elfdump/common/struct_layout.h
index b0592d6909..e452de47ca 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout.h
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout.h
@@ -28,6 +28,10 @@
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
*/
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
#ifndef _STRUCT_LAYOUT_H
#define _STRUCT_LAYOUT_H
@@ -98,7 +102,7 @@ typedef struct {
*/
typedef union {
char sld_i8;
- uchar_t sld_ui8;
+ uchar_t sld_ui8;
short sld_i16;
ushort_t sld_ui16;
int32_t sld_i32;
@@ -535,6 +539,12 @@ typedef struct {
sl_field_t pr_upper;
} sl_prsecflags_layout_t;
+typedef struct {
+ sl_field_t sizeof_struct;
+ sl_field_t pr_lwpid;
+ sl_field_t pr_lwpname;
+} sl_prlwpname_layout_t;
+
/*
* This type collects all of the layout definitions for
* a given architecture.
@@ -561,6 +571,7 @@ typedef struct {
const sl_utsname_layout_t *utsname; /* struct utsname */
const sl_prfdinfo_layout_t *prfdinfo; /* prdinfo_t */
const sl_prsecflags_layout_t *prsecflags; /* prsecflags_t */
+ const sl_prlwpname_layout_t *prlwpname; /* prlwpname_t */
} sl_arch_layout_t;
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
index 2b9469a022..11488009ea 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
@@ -26,6 +26,9 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
*/
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
#include <struct_layout.h>
@@ -387,6 +390,13 @@ static const sl_prsecflags_layout_t prsecflags_layout = {
};
+static const sl_prlwpname_layout_t prlwpname_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
+ { 0, 8, 0, 0 }, /* pr_lwpid */
+ { 8, 1, 32, 0 }, /* pr_lwpname[] */
+};
+
+
static const sl_arch_layout_t layout_amd64 = {
@@ -411,6 +421,7 @@ static const sl_arch_layout_t layout_amd64 = {
&utsname_layout,
&prfdinfo_layout,
&prsecflags_layout,
+ &prlwpname_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
index 6a516bc225..08d5e5f3ce 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
@@ -26,6 +26,9 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
*/
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
#include <struct_layout.h>
@@ -387,6 +390,13 @@ static const sl_prsecflags_layout_t prsecflags_layout = {
};
+static const sl_prlwpname_layout_t prlwpname_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
+ { 0, 8, 0, 0 }, /* pr_lwpid */
+ { 8, 1, 32, 0 }, /* pr_lwpname[] */
+};
+
+
static const sl_arch_layout_t layout_i386 = {
@@ -411,6 +421,7 @@ static const sl_arch_layout_t layout_i386 = {
&utsname_layout,
&prfdinfo_layout,
&prsecflags_layout,
+ &prlwpname_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
index 94760c3d82..d0306d60fe 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
@@ -26,6 +26,10 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
*/
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
#include <struct_layout.h>
@@ -386,6 +390,13 @@ static const sl_prsecflags_layout_t prsecflags_layout = {
};
+static const sl_prlwpname_layout_t prlwpname_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
+ { 0, 8, 0, 0 }, /* pr_lwpid */
+ { 8, 1, 32, 0 }, /* pr_lwpname[] */
+};
+
+
static const sl_arch_layout_t layout_sparc = {
@@ -410,6 +421,7 @@ static const sl_arch_layout_t layout_sparc = {
&utsname_layout,
&prfdinfo_layout,
&prsecflags_layout,
+ &prlwpname_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
index a194d8136a..a90db686ba 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
@@ -26,6 +26,9 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
*/
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
#include <struct_layout.h>
@@ -387,6 +390,13 @@ static const sl_prsecflags_layout_t prsecflags_layout = {
};
+static const sl_prlwpname_layout_t prlwpname_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
+ { 0, 8, 0, 0 }, /* pr_lwpid */
+ { 8, 1, 32, 0 }, /* pr_lwpname[] */
+};
+
+
static const sl_arch_layout_t layout_sparcv9 = {
@@ -411,6 +421,7 @@ static const sl_arch_layout_t layout_sparcv9 = {
&utsname_layout,
&prfdinfo_layout,
&prsecflags_layout,
+ &prlwpname_layout,
};
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.c b/usr/src/cmd/sgs/libconv/common/corenote.c
index 3515e9b59c..ce923bb039 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.c
+++ b/usr/src/cmd/sgs/libconv/common/corenote.c
@@ -58,9 +58,10 @@ conv_cnote_type(Word type, Conv_fmt_flags_t fmt_flags,
MSG_NT_LWPSINFO, MSG_NT_PRPRIV,
MSG_NT_PRPRIVINFO, MSG_NT_CONTENT,
MSG_NT_ZONENAME, MSG_NT_FDINFO,
- MSG_NT_SPYMASTER, MSG_NT_SECFLAGS
+ MSG_NT_SPYMASTER, MSG_NT_SECFLAGS,
+ MSG_NT_LWPNAME,
};
-#if NT_NUM != NT_SECFLAGS
+#if NT_NUM != NT_LWPNAME
#error "NT_NUM has grown. Update core note types[]"
#endif
static const conv_ds_msg_t ds_types = {
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.msg b/usr/src/cmd/sgs/libconv/common/corenote.msg
index 1613f4947a..78951cfb1d 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.msg
+++ b/usr/src/cmd/sgs/libconv/common/corenote.msg
@@ -49,6 +49,7 @@
@ MSG_NT_FDINFO "[ NT_FDINFO ]"
@ MSG_NT_SPYMASTER "[ NT_SPYMASTER ]"
@ MSG_NT_SECFLAGS "[ NT_SECFLAGS ]"
+@ MSG_NT_LWPNAME "[ NT_LWPNAME ]"
@ MSG_AUXV_AF_SUN_SETUGID "AF_SUN_SETUGID"
diff --git a/usr/src/cmd/svc/startd/graph.c b/usr/src/cmd/svc/startd/graph.c
index 30881ea34a..6b617690c1 100644
--- a/usr/src/cmd/svc/startd/graph.c
+++ b/usr/src/cmd/svc/startd/graph.c
@@ -21,10 +21,10 @@
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2015, Syneto S.R.L. All rights reserved.
* Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright 2016 RackTop Systems.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -579,7 +579,7 @@ typedef enum {
typedef int (*graph_walk_cb_t)(graph_vertex_t *, void *);
typedef struct graph_walk_info {
- graph_walk_dir_t gi_dir;
+ graph_walk_dir_t gi_dir;
uchar_t *gi_visited; /* vertex bitmap */
int (*gi_pre)(graph_vertex_t *, void *);
void (*gi_post)(graph_vertex_t *, void *);
@@ -3852,6 +3852,8 @@ run_sulogin(const char *msg)
static void *
sulogin_thread(void *unused)
{
+ (void) pthread_setname_np(pthread_self(), "sulogin");
+
MUTEX_LOCK(&dgraph_lock);
assert(sulogin_thread_running);
@@ -3879,6 +3881,8 @@ single_user_thread(void *unused)
char *buf;
int r;
+ (void) pthread_setname_np(pthread_self(), "single_user");
+
MUTEX_LOCK(&single_user_thread_lock);
single_user_thread_count++;
@@ -5796,6 +5800,8 @@ graph_event_thread(void *unused)
scf_handle_t *h;
int err;
+ (void) pthread_setname_np(pthread_self(), "graph_event");
+
h = libscf_handle_create_bound_loop();
/*CONSTCOND*/
@@ -6155,6 +6161,8 @@ graph_thread(void *arg)
scf_handle_t *h;
int err;
+ (void) pthread_setname_np(pthread_self(), "graph");
+
h = libscf_handle_create_bound_loop();
if (st->st_initial)
@@ -6812,6 +6820,8 @@ repository_event_thread(void *unused)
int r;
int fd;
+ (void) pthread_setname_np(pthread_self(), "repository_event");
+
h = libscf_handle_create_bound_loop();
pg = safe_scf_pg_create(h);
diff --git a/usr/src/cmd/svc/startd/method.c b/usr/src/cmd/svc/startd/method.c
index c3cd0144c1..1d8ffaa2b6 100644
--- a/usr/src/cmd/svc/startd/method.c
+++ b/usr/src/cmd/svc/startd/method.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -1135,6 +1135,8 @@ method_thread(void *arg)
boolean_t retryable;
restarter_str_t reason;
+ (void) pthread_setname_np(pthread_self(), "method");
+
assert(0 <= info->sf_method_type && info->sf_method_type <= 2);
/* Get (and lock) the restarter_inst_t. */
diff --git a/usr/src/cmd/svc/startd/restarter.c b/usr/src/cmd/svc/startd/restarter.c
index 676cded1c8..a98c863fb5 100644
--- a/usr/src/cmd/svc/startd/restarter.c
+++ b/usr/src/cmd/svc/startd/restarter.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -994,6 +994,8 @@ restarter_post_fsminimal_thread(void *unused)
scf_handle_t *h;
int r;
+ (void) pthread_setname_np(pthread_self(), "restarter_post_fsmin");
+
h = libscf_handle_create_bound_loop();
for (;;) {
@@ -1771,6 +1773,8 @@ restarter_process_events(void *arg)
char *fmri = (char *)arg;
struct timespec to;
+ (void) pthread_setname_np(pthread_self(), "restarter_process_events");
+
assert(fmri != NULL);
h = libscf_handle_create_bound_loop();
@@ -1939,8 +1943,8 @@ out:
}
static int
-is_admin_event(restarter_event_type_t t) {
-
+is_admin_event(restarter_event_type_t t)
+{
switch (t) {
case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE:
@@ -1985,6 +1989,8 @@ restarter_event_thread(void *unused)
{
scf_handle_t *h;
+ (void) pthread_setname_np(pthread_self(), "restarter_event");
+
/*
* This is a new thread, and thus, gets its own handle
* to the repository.
@@ -2196,6 +2202,8 @@ restarter_contracts_event_thread(void *unused)
int fd, err;
scf_handle_t *local_handle;
+ (void) pthread_setname_np(pthread_self(), "restarter_contracts_event");
+
/*
* Await graph load completion. That is, stop here, until we've scanned
* the repository for contract - instance associations.
@@ -2545,6 +2553,8 @@ restarter_timeouts_event_thread(void *unused)
* is not empty.
*/
+ (void) pthread_setname_np(pthread_self(), "restarter_timeouts_event");
+
/*CONSTCOND*/
while (1) {
/*
diff --git a/usr/src/cmd/svc/startd/wait.c b/usr/src/cmd/svc/startd/wait.c
index ebd83be10e..12856ff639 100644
--- a/usr/src/cmd/svc/startd/wait.c
+++ b/usr/src/cmd/svc/startd/wait.c
@@ -21,7 +21,8 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2012, Joyent, Inc. All rights reserved.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -252,6 +253,8 @@ wait_register(pid_t pid, const char *inst_fmri, int am_parent, int direct)
void *
wait_thread(void *args)
{
+ (void) pthread_setname_np(pthread_self(), "wait");
+
for (;;) {
port_event_t pe;
int fd;
diff --git a/usr/src/compat/freebsd/pthread_np.h b/usr/src/compat/freebsd/pthread_np.h
index 641c58f406..c4f76b259c 100644
--- a/usr/src/compat/freebsd/pthread_np.h
+++ b/usr/src/compat/freebsd/pthread_np.h
@@ -11,6 +11,7 @@
/*
* Copyright 2014 Pluribus Networks Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _COMPAT_FREEBSD_PTHREAD_NP_H_
@@ -20,8 +21,9 @@
#include <sys/cpuset.h>
#include <synch.h>
+#include <pthread.h>
-#define pthread_set_name_np(thread, name)
+#define pthread_set_name_np pthread_setname_np
#define pthread_mutex_isowned_np(x) _mutex_held(x)
diff --git a/usr/src/head/pthread.h b/usr/src/head/pthread.h
index 91d268a30d..490a93f1b2 100644
--- a/usr/src/head/pthread.h
+++ b/usr/src/head/pthread.h
@@ -21,7 +21,7 @@
/*
* Copyright 2014 Garrett D'Amore <garrett@damore.org>
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -139,6 +139,9 @@ extern "C" {
/* barriers */
#define PTHREAD_BARRIER_SERIAL_THREAD -2
+/* For pthread_{get,set}name_np(). */
+#define PTHREAD_MAX_NAMELEN_NP (32)
+
#ifndef _ASM
/*
@@ -209,6 +212,10 @@ extern int pthread_attr_setschedparam(pthread_attr_t *_RESTRICT_KYWD,
const struct sched_param *_RESTRICT_KYWD);
extern int pthread_attr_getschedparam(const pthread_attr_t *_RESTRICT_KYWD,
struct sched_param *_RESTRICT_KYWD);
+extern int pthread_attr_setname_np(pthread_attr_t *_RESTRICT_KYWD,
+ const char *_RESTRICT_KYWD);
+extern int pthread_attr_getname_np(pthread_attr_t *_RESTRICT_KYWD,
+ char *_RESTRICT_KYWD, size_t);
extern int pthread_create(pthread_t *_RESTRICT_KYWD,
const pthread_attr_t *_RESTRICT_KYWD, void * (*)(void *),
void *_RESTRICT_KYWD);
@@ -231,6 +238,8 @@ extern int pthread_key_delete(pthread_key_t);
extern int pthread_setspecific(pthread_key_t, const void *);
extern void *pthread_getspecific(pthread_key_t);
extern pthread_t pthread_self(void);
+extern int pthread_setname_np(pthread_t, const char *);
+extern int pthread_getname_np(pthread_t, char *, size_t);
/*
* function prototypes - synchronization related calls
diff --git a/usr/src/head/thread.h b/usr/src/head/thread.h
index d0b0b3ddeb..704174d411 100644
--- a/usr/src/head/thread.h
+++ b/usr/src/head/thread.h
@@ -24,6 +24,8 @@
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _THREAD_H
@@ -87,6 +89,8 @@ extern int thr_keycreate_once(thread_key_t *, void(*)(void *));
extern int thr_setspecific(thread_key_t, void *);
extern int thr_getspecific(thread_key_t, void **);
extern size_t thr_min_stack(void);
+extern int thr_getname(thread_t, char *, size_t);
+extern int thr_setname(thread_t, const char *);
#endif /* _ASM */
diff --git a/usr/src/lib/brand/bhyve/zone/platform.xml b/usr/src/lib/brand/bhyve/zone/platform.xml
index 0aa8d875c3..4f4446b345 100644
--- a/usr/src/lib/brand/bhyve/zone/platform.xml
+++ b/usr/src/lib/brand/bhyve/zone/platform.xml
@@ -29,6 +29,7 @@
opt="ro,nodevices,nosub" type="lofs" />
<!-- Local filesystems to mount when booting the zone -->
+ <mount special="/proc" directory="/proc" type="proc" />
<mount special="swap" directory="/var/run" type="tmpfs"
opt="size=50m"/>
diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h
index 2c56e76f17..7f08a0b8c4 100644
--- a/usr/src/lib/libc/inc/thr_uberdata.h
+++ b/usr/src/lib/libc/inc/thr_uberdata.h
@@ -57,6 +57,7 @@
#include <sys/priocntl.h>
#include <thread_db.h>
#include <setjmp.h>
+#include <sys/thread.h>
#include "libc_int.h"
#include "tdb_agent.h"
#include "thr_debug.h"
@@ -1237,6 +1238,7 @@ typedef struct _thrattr {
int policy;
int inherit;
size_t guardsize;
+ char name[THREAD_NAME_MAX];
} thrattr_t;
typedef struct _rwlattr {
@@ -1497,7 +1499,7 @@ extern int rw_read_held(rwlock_t *);
extern int rw_write_held(rwlock_t *);
extern int _thrp_create(void *, size_t, void *(*)(void *), void *, long,
- thread_t *, size_t);
+ thread_t *, size_t, const char *);
extern int _thrp_suspend(thread_t, uchar_t);
extern int _thrp_continue(thread_t, uchar_t);
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index 9992247d90..f51996c646 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -23,7 +23,7 @@
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2018 Nexenta Systems, Inc.
# Copyright (c) 2012 by Delphix. All rights reserved.
-# Copyright 2016 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
# Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright (c) 2013 Gary Mills
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
@@ -3097,7 +3097,11 @@ $endif
pset_bind_lwp;
_psignal;
pthread_attr_getdaemonstate_np;
+ pthread_attr_getname_np;
pthread_attr_setdaemonstate_np;
+ pthread_attr_setname_np;
+ pthread_getname_np;
+ pthread_setname_np;
_pthread_setcleanupinit;
__putwchar_xpg5;
__putwc_xpg5;
@@ -3176,6 +3180,7 @@ $endif
_thr_continue_allmutators;
thr_continue_mutator;
_thr_continue_mutator;
+ thr_getname;
thr_getstate;
_thr_getstate;
thr_mutators_barrier;
@@ -3184,6 +3189,7 @@ $endif
_thr_schedctl;
thr_setmutator;
_thr_setmutator;
+ thr_setname;
thr_setstate;
_thr_setstate;
thr_sighndlrinfo;
diff --git a/usr/src/lib/libc/port/threads/pthr_attr.c b/usr/src/lib/libc/port/threads/pthr_attr.c
index b04bcdba7c..7cfc970120 100644
--- a/usr/src/lib/libc/port/threads/pthr_attr.c
+++ b/usr/src/lib/libc/port/threads/pthr_attr.c
@@ -25,11 +25,13 @@
*/
/*
- * Copyright 2015, Joyent, Inc.
+ * Copyright 2018, Joyent, Inc.
*/
#include "lint.h"
#include "thr_uberdata.h"
+#include <sys/ctype.h>
+#include <strings.h>
#include <sched.h>
/*
@@ -48,7 +50,8 @@ def_thrattr(void)
0, /* prio */
SCHED_OTHER, /* policy */
PTHREAD_INHERIT_SCHED, /* inherit */
- 0 /* guardsize */
+ 0, /* guardsize */
+ { 0 } /* name */
};
if (thrattr.guardsize == 0)
thrattr.guardsize = _sysconf(_SC_PAGESIZE);
@@ -95,7 +98,7 @@ pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr)
{
thrattr_t *ap;
const thrattr_t *old_ap =
- old_attr? old_attr->__pthread_attrp : def_thrattr();
+ old_attr ? old_attr->__pthread_attrp : def_thrattr();
if (old_ap == NULL)
return (EINVAL);
@@ -114,8 +117,8 @@ pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr)
int
pthread_attr_equal(const pthread_attr_t *attr1, const pthread_attr_t *attr2)
{
- const thrattr_t *ap1 = attr1? attr1->__pthread_attrp : def_thrattr();
- const thrattr_t *ap2 = attr2? attr2->__pthread_attrp : def_thrattr();
+ const thrattr_t *ap1 = attr1 ? attr1->__pthread_attrp : def_thrattr();
+ const thrattr_t *ap2 = attr2 ? attr2->__pthread_attrp : def_thrattr();
if (ap1 == NULL || ap2 == NULL)
return (0);
@@ -476,6 +479,53 @@ pthread_attr_getstack(const pthread_attr_t *attr,
return (EINVAL);
}
+int
+pthread_attr_setname_np(pthread_attr_t *attr, const char *name)
+{
+ thrattr_t *ap;
+
+ if (attr == NULL || (ap = attr->__pthread_attrp) == NULL)
+ return (EINVAL);
+
+ if (name == NULL) {
+ bzero(ap->name, sizeof (ap->name));
+ return (0);
+ }
+
+ if (strlen(name) >= sizeof (ap->name))
+ return (ERANGE);
+
+ /*
+ * We really want the ASCII version of isprint() here...
+ */
+ for (size_t i = 0; name[i] != '\0'; i++) {
+ if (!ISPRINT(name[i]))
+ return (EINVAL);
+ }
+
+ /*
+ * not having garbage after the end of the string simplifies attr
+ * comparison
+ */
+ bzero(ap->name, sizeof (ap->name));
+ (void) strlcpy(ap->name, name, sizeof (ap->name));
+ return (0);
+}
+
+int
+pthread_attr_getname_np(pthread_attr_t *attr, char *buf, size_t len)
+{
+ thrattr_t *ap;
+
+ if (buf == NULL || attr == NULL ||
+ (ap = attr->__pthread_attrp) == NULL)
+ return (EINVAL);
+
+ if (strlcpy(buf, ap->name, len) > len)
+ return (ERANGE);
+ return (0);
+}
+
/*
* This function is a common BSD extension to pthread which is used to obtain
* the attributes of a thread that might have changed after its creation, for
@@ -551,6 +601,7 @@ pthread_attr_get_np(pthread_t tid, pthread_attr_t *attr)
ap->policy = target->ul_policy;
ap->inherit = target->ul_ptinherit;
ap->guardsize = target->ul_guardsize;
+ (void) pthread_getname_np(tid, ap->name, sizeof (ap->name));
ret = 0;
out:
diff --git a/usr/src/lib/libc/port/threads/pthread.c b/usr/src/lib/libc/port/threads/pthread.c
index 6a22995639..34b4b4c73c 100644
--- a/usr/src/lib/libc/port/threads/pthread.c
+++ b/usr/src/lib/libc/port/threads/pthread.c
@@ -24,7 +24,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#include "lint.h"
@@ -128,7 +128,7 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
flag = ap->scope | ap->detachstate | ap->daemonstate | THR_SUSPENDED;
error = _thrp_create(ap->stkaddr, ap->stksize, start_routine, arg,
- flag, &tid, ap->guardsize);
+ flag, &tid, ap->guardsize, ap->name);
if (error == 0) {
/*
* Record the original inheritence value for
diff --git a/usr/src/lib/libc/port/threads/thr.c b/usr/src/lib/libc/port/threads/thr.c
index b6580b3e3a..69c5f24981 100644
--- a/usr/src/lib/libc/port/threads/thr.c
+++ b/usr/src/lib/libc/port/threads/thr.c
@@ -25,7 +25,7 @@
* Copyright (c) 2017 by The MathWorks, Inc. All rights reserved.
*/
/*
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#include "lint.h"
@@ -562,7 +562,7 @@ find_lwp(thread_t tid)
int
_thrp_create(void *stk, size_t stksize, void *(*func)(void *), void *arg,
- long flags, thread_t *new_thread, size_t guardsize)
+ long flags, thread_t *new_thread, size_t guardsize, const char *name)
{
ulwp_t *self = curthread;
uberdata_t *udp = self->ul_uberdata;
@@ -717,6 +717,9 @@ _thrp_create(void *stk, size_t stksize, void *(*func)(void *), void *arg,
exit_critical(self);
+ if (name != NULL)
+ (void) pthread_setname_np(tid, name);
+
if (!(flags & THR_SUSPENDED))
(void) _thrp_continue(tid, TSTP_REGULAR);
@@ -727,7 +730,8 @@ int
thr_create(void *stk, size_t stksize, void *(*func)(void *), void *arg,
long flags, thread_t *new_thread)
{
- return (_thrp_create(stk, stksize, func, arg, flags, new_thread, 0));
+ return (_thrp_create(stk, stksize, func, arg, flags, new_thread, 0,
+ NULL));
}
/*
@@ -2407,6 +2411,84 @@ __nthreads(void)
return (curthread->ul_uberdata->nthreads);
}
+#pragma weak pthread_setname_np = thr_setname
+int
+thr_setname(pthread_t tid, const char *name)
+{
+ extern ssize_t __write(int, const void *, size_t);
+ char path[PATH_MAX];
+ int saved_errno;
+ size_t len;
+ ssize_t n;
+ int fd;
+
+ if (name == NULL)
+ name = "";
+
+ len = strlen(name) + 1;
+ if (len > THREAD_NAME_MAX)
+ return (ERANGE);
+
+ /* "/proc/self/lwp/%u/lwpname" w/o stdio */
+ (void) strlcpy(path, "/proc/self/lwp/", sizeof (path));
+ ultos((uint64_t)tid, 10, path + strlen(path));
+ (void) strlcat(path, "/lwpname", sizeof (path));
+
+ if ((fd = __open(path, O_WRONLY, 0)) < 0) {
+ if (errno == ENOENT)
+ errno = ESRCH;
+ return (errno);
+ }
+
+ n = __write(fd, name, len);
+ saved_errno = errno;
+ (void) __close(fd);
+
+ if (n < 0)
+ return (saved_errno);
+ if (n != len)
+ return (EFAULT);
+ return (0);
+}
+
+#pragma weak pthread_getname_np = thr_getname
+int
+thr_getname(pthread_t tid, char *buf, size_t bufsize)
+{
+ extern ssize_t __read(int, void *, size_t);
+ char name[THREAD_NAME_MAX];
+ char path[PATH_MAX];
+ int saved_errno;
+ ssize_t n;
+ int fd;
+
+ if (buf == NULL)
+ return (EINVAL);
+
+ /* "/proc/self/lwp/%u/name" w/o stdio */
+ (void) strlcpy(path, "/proc/self/lwp/", sizeof (path));
+ ultos((uint64_t)tid, 10, path + strlen(path));
+ (void) strlcat(path, "/lwpname", sizeof (path));
+
+ if ((fd = __open(path, O_RDONLY, 0)) < 0) {
+ if (errno == ENOENT)
+ errno = ESRCH;
+ return (errno);
+ }
+
+ n = __read(fd, name, sizeof (name));
+ saved_errno = errno;
+ (void) __close(fd);
+
+ if (n < 0)
+ return (saved_errno);
+ if (n != sizeof (name))
+ return (EFAULT);
+ if (strlcpy(buf, name, bufsize) >= bufsize)
+ return (ERANGE);
+ return (0);
+}
+
/*
* XXX
* The remainder of this file implements the private interfaces to java for
diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c
index 3325f333ab..d515669e0c 100644
--- a/usr/src/lib/libdtrace/common/dt_open.c
+++ b/usr/src/lib/libdtrace/common/dt_open.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
*/
@@ -117,8 +117,9 @@
#define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0)
#define DT_VERS_1_12_1 DT_VERSION_NUMBER(1, 12, 1)
#define DT_VERS_1_13 DT_VERSION_NUMBER(1, 13, 0)
-#define DT_VERS_LATEST DT_VERS_1_13
-#define DT_VERS_STRING "Sun D 1.13"
+#define DT_VERS_1_14 DT_VERSION_NUMBER(1, 14, 0)
+#define DT_VERS_LATEST DT_VERS_1_14
+#define DT_VERS_STRING "Sun D 1.14"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -145,6 +146,7 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_12, /* D API 1.12 */
DT_VERS_1_12_1, /* D API 1.12.1 */
DT_VERS_1_13, /* D API 1.13 */
+ DT_VERS_1_14, /* D API 1.14 */
0
};
@@ -402,6 +404,8 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_func, "void(@, ...)" },
{ "this", DT_IDENT_PTR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "void" },
+{ "threadname", DT_IDENT_SCALAR, 0, DIF_VAR_THREADNAME,
+ DT_ATTR_STABCMN, DT_VERS_1_14, &dt_idops_type, "string" },
{ "tid", DT_IDENT_SCALAR, 0, DIF_VAR_TID, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "id_t" },
{ "timestamp", DT_IDENT_SCALAR, 0, DIF_VAR_TIMESTAMP,
diff --git a/usr/src/lib/libfakekernel/common/sys/thread.h b/usr/src/lib/libfakekernel/common/sys/thread.h
index 6213be2807..d6e05c691c 100644
--- a/usr/src/lib/libfakekernel/common/sys/thread.h
+++ b/usr/src/lib/libfakekernel/common/sys/thread.h
@@ -24,6 +24,7 @@
* Use is subject to license terms.
*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _SYS_THREAD_H
@@ -82,6 +83,7 @@ extern kthread_t *_curthread(void); /* returns thread pointer */
#define _KTHREAD_INVALID ((void *)(uintptr_t)-1)
+#define THREAD_NAME_MAX (32)
struct proc;
extern struct proc *_curproc(void);
diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h
index 7e19e8777c..3122207902 100644
--- a/usr/src/lib/libproc/common/Pcontrol.h
+++ b/usr/src/lib/libproc/common/Pcontrol.h
@@ -24,8 +24,8 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright (c) 2015, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _PCONTROL_H
@@ -45,6 +45,7 @@
#include <libctf.h>
#include <limits.h>
#include <libproc.h>
+#include <thread.h>
#include <sys/secflags.h>
#ifdef __cplusplus
@@ -139,6 +140,7 @@ typedef struct lwp_info { /* per-lwp information from core file */
lwpid_t lwp_id; /* lwp identifier */
lwpsinfo_t lwp_psinfo; /* /proc/<pid>/lwp/<lwpid>/lwpsinfo data */
lwpstatus_t lwp_status; /* /proc/<pid>/lwp/<lwpid>/lwpstatus data */
+ char lwp_name[THREAD_NAME_MAX];
#if defined(sparc) || defined(__sparc)
gwindows_t *lwp_gwins; /* /proc/<pid>/lwp/<lwpid>/gwindows data */
prxregset_t *lwp_xregs; /* /proc/<pid>/lwp/<lwpid>/xregs data */
@@ -276,7 +278,7 @@ extern void optimize_symtab(sym_tbl_t *);
extern void Pbuild_file_symtab(struct ps_prochandle *, file_info_t *);
extern ctf_file_t *Pbuild_file_ctf(struct ps_prochandle *, file_info_t *);
extern map_info_t *Paddr2mptr(struct ps_prochandle *, uintptr_t);
-extern char *Pfindexec(struct ps_prochandle *, const char *,
+extern char *Pfindexec(struct ps_prochandle *, const char *,
int (*)(const char *, void *), void *);
extern int getlwpstatus(struct ps_prochandle *, lwpid_t, lwpstatus_t *);
int Pstopstatus(struct ps_prochandle *, long, uint32_t);
diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c
index 89c5ce47fa..cfeb0ebb87 100644
--- a/usr/src/lib/libproc/common/Pcore.c
+++ b/usr/src/lib/libproc/common/Pcore.c
@@ -24,7 +24,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright (c) 2014, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright 2015 Gary Mills
*/
@@ -726,6 +726,32 @@ err:
}
static int
+note_lwpname(struct ps_prochandle *P, size_t nbytes)
+{
+ prlwpname_t name;
+ lwp_info_t *lwp;
+
+ if (nbytes != sizeof (name) ||
+ read(P->asfd, &name, sizeof (name)) != sizeof (name))
+ goto err;
+
+ if ((lwp = lwpid2info(P, name.pr_lwpid)) == NULL)
+ goto err;
+
+ if (strlcpy(lwp->lwp_name, name.pr_lwpname,
+ sizeof (lwp->lwp_name)) >= sizeof (lwp->lwp_name)) {
+ errno = ENAMETOOLONG;
+ goto err;
+ }
+
+ return (0);
+
+err:
+ dprintf("Pgrab_core: failed to read NT_LWPNAME\n");
+ return (-1);
+}
+
+static int
note_fdinfo(struct ps_prochandle *P, size_t nbytes)
{
prfdinfo_t prfd;
@@ -1231,6 +1257,7 @@ static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
note_fdinfo, /* 22 NT_FDINFO */
note_spymaster, /* 23 NT_SPYMASTER */
note_secflags, /* 24 NT_SECFLAGS */
+ note_lwpname, /* 25 NT_LWPNAME */
};
static void
diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c
index 6ddf92ad2f..64ef98065b 100644
--- a/usr/src/lib/libproc/common/Pgcore.c
+++ b/usr/src/lib/libproc/common/Pgcore.c
@@ -25,7 +25,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright 2015 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -509,6 +509,7 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip)
{
pgcore_t *pgc = data;
struct ps_prochandle *P = pgc->P;
+ prlwpname_t name = { 0, "" };
psinfo_t ps;
/*
@@ -577,6 +578,14 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip)
#endif /* __sparcv9 */
#endif /* sparc */
+ if (Plwp_getname(P, lsp->pr_lwpid, name.pr_lwpname,
+ sizeof (name.pr_lwpname)) == 0) {
+ name.pr_lwpid = lsp->pr_lwpid;
+ if (write_note(pgc->pgc_fd, NT_LWPNAME, &name,
+ sizeof (name), pgc->pgc_doff) != 0)
+ return (1);
+ }
+
if (!(lsp->pr_flags & PR_AGENT))
return (0);
diff --git a/usr/src/lib/libproc/common/Plwpregs.c b/usr/src/lib/libproc/common/Plwpregs.c
index c2b150000f..d400eb185c 100644
--- a/usr/src/lib/libproc/common/Plwpregs.c
+++ b/usr/src/lib/libproc/common/Plwpregs.c
@@ -24,8 +24,8 @@
*/
/*
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/types.h>
@@ -353,6 +353,38 @@ Plwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps)
}
int
+Plwp_getname(struct ps_prochandle *P, lwpid_t lwpid,
+ char *buf, size_t bufsize)
+{
+ char lwpname[THREAD_NAME_MAX];
+ char *from = NULL;
+ lwp_info_t *lwp;
+
+ if (P->state == PS_IDLE) {
+ errno = ENODATA;
+ return (-1);
+ }
+
+ if (P->state != PS_DEAD) {
+ if (getlwpfile(P, lwpid, "lwpname",
+ lwpname, sizeof (lwpname)) != 0)
+ return (-1);
+ from = lwpname;
+ } else {
+ if ((lwp = getlwpcore(P, lwpid)) == NULL)
+ return (-1);
+ from = lwp->lwp_name;
+ }
+
+ if (strlcpy(buf, from, bufsize) >= bufsize) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
Plwp_getspymaster(struct ps_prochandle *P, lwpid_t lwpid, psinfo_t *ps)
{
lwpstatus_t lps;
diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h
index d74c08e828..eb73039a21 100644
--- a/usr/src/lib/libproc/common/libproc.h
+++ b/usr/src/lib/libproc/common/libproc.h
@@ -25,7 +25,7 @@
*
* Portions Copyright 2007 Chad Mynhier
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright 2015, Joyent, Inc.
+ * Copyright 2018, Joyent, Inc.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -436,6 +436,7 @@ extern int Pldt(struct ps_prochandle *, struct ssd *, int);
extern int proc_get_ldt(pid_t, struct ssd *, int);
#endif /* __i386 || __amd64 */
+extern int Plwp_getname(struct ps_prochandle *, lwpid_t, char *, size_t);
extern int Plwp_getpsinfo(struct ps_prochandle *, lwpid_t, lwpsinfo_t *);
extern int Plwp_getspymaster(struct ps_prochandle *, lwpid_t, psinfo_t *);
diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers
index b3f9df9d97..6b31f79e98 100644
--- a/usr/src/lib/libproc/common/mapfile-vers
+++ b/usr/src/lib/libproc/common/mapfile-vers
@@ -21,8 +21,8 @@
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
-# Copyright (c) 2013, Joyent, Inc. All rights reserved.
# Copyright (c) 2013 by Delphix. All rights reserved.
+# Copyright 2018 Joyent, Inc.
#
#
@@ -136,6 +136,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
Plookup_by_name;
Plwp_alt_stack;
Plwp_getfpregs;
+ Plwp_getname;
Plwp_getpsinfo;
Plwp_getregs;
Plwp_getspymaster;
diff --git a/usr/src/man/man1/ps.1 b/usr/src/man/man1/ps.1
index afdda2f8ef..9f2fb063ca 100644
--- a/usr/src/man/man1/ps.1
+++ b/usr/src/man/man1/ps.1
@@ -44,9 +44,9 @@
.\" Portions Copyright (c) 1992, X/Open Company Limited All Rights Reserved
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved
.\" Copyright (c) 2013 Gary Mills
-.\" Copyright (c) 2017, Joyent, Inc.
+.\" Copyright (c) 2018, Joyent, Inc.
.\"
-.TH PS 1 "Jun 13, 2017"
+.TH PS 1 "August 22, 2018"
.SH NAME
ps \- report process status
.SH SYNOPSIS
@@ -1052,6 +1052,16 @@ one line to be printed for each lwp in the process.
.sp
.ne 2
.na
+\fB\fBlwpname\fR\fR
+.ad
+.RS 11n
+The name of the lwp, if set. Requesting this formatting option causes
+one line to be printed for each lwp in the process.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fBnlwp\fR\fR
.ad
.RS 11n
@@ -1176,8 +1186,8 @@ The data model of the process, printed in the same manner as via
.sp
.LP
-Only \fBcomm\fR and \fBargs\fR are allowed to contain blank characters; all
-others, including the Solaris implementation variables, are not.
+Only \fBcomm\fR, \fBlwpname\fR, and \fBargs\fR are allowed to contain blank
+characters; all others, including the Solaris implementation variables, are not.
.sp
.LP
The following table specifies the default header to be used in the POSIX locale
@@ -1199,7 +1209,7 @@ group GROUP time TIME
nice NI tty TT
pcpu %CPU user USER
pgid PGID vsz VSZ
-pid PID
+pid PID
.TE
.sp
@@ -1224,12 +1234,13 @@ fname COMMAND rss RSS
gid GID ruid RUID
lgrp LGRP s S
lwp LWP sid SID
-nlwp NLWP stime STIME
-opri PRI taskid TASKID
-osz SZ uid UID
-pmem %MEM wchan WCHAN
-pri PRI zone ZONE
-ctid CTID zoneid ZONEID
+lwpname LWPNAME stime STIME
+nlwp NLWP taskid TASKID
+opri PRI uid UID
+osz SZ wchan WCHAN
+pmem %MEM zone ZONE
+pri PRI zoneid ZONEID
+ctid CTID
.TE
.SH EXAMPLES
diff --git a/usr/src/man/man1m/prstat.1m b/usr/src/man/man1m/prstat.1m
index 35cb6fbf24..8ca1ffa70b 100644
--- a/usr/src/man/man1m/prstat.1m
+++ b/usr/src/man/man1m/prstat.1m
@@ -1,11 +1,11 @@
'\" te
.\" Copyright (c) 2013 Gary Mills
.\" Copyright (c) 2006, 2009 Sun Microsystems, Inc. All Rights Reserved.
-.\" Copyright (c) 2017, Joyent, Inc. All Rights Reserved.
+.\" Copyright (c) 2018, Joyent, Inc. All Rights Reserved.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with
.\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH PRSTAT 1M "Oct 13, 2017"
+.TH PRSTAT 1M "September 1, 2018"
.SH NAME
prstat \- report active process statistics
.SH SYNOPSIS
@@ -583,11 +583,12 @@ The name of the process (name of executed file).
.sp
.ne 2
.na
-\fBLWPID\fR
+\fBLWP\fR
.ad
.sp .6
.RS 4n
-The \fBlwp\fR \fBID\fR of the \fBlwp\fR being reported.
+The \fBlwp\fR \fBID\fR of the \fBlwp\fR being reported, as well as the LWP
+name if any is set.
.RE
.sp
diff --git a/usr/src/man/man3c/Makefile b/usr/src/man/man3c/Makefile
index 98102cdfa1..540a58948e 100644
--- a/usr/src/man/man3c/Makefile
+++ b/usr/src/man/man3c/Makefile
@@ -310,6 +310,7 @@ MANFILES= __fbufsize.3c \
pthread_attr_getdetachstate.3c \
pthread_attr_getguardsize.3c \
pthread_attr_getinheritsched.3c \
+ pthread_attr_getname_np.3c \
pthread_attr_getschedparam.3c \
pthread_attr_getschedpolicy.3c \
pthread_attr_getscope.3c \
@@ -335,6 +336,7 @@ MANFILES= __fbufsize.3c \
pthread_equal.3c \
pthread_exit.3c \
pthread_getconcurrency.3c \
+ pthread_getname_np.3c \
pthread_getschedparam.3c \
pthread_getspecific.3c \
pthread_join.3c \
@@ -478,6 +480,7 @@ MANFILES= __fbufsize.3c \
termios.3c \
thr_create.3c \
thr_exit.3c \
+ thr_getname.3c \
thr_getconcurrency.3c \
thr_getprio.3c \
thr_join.3c \
@@ -1095,6 +1098,7 @@ MANLINKS= FD_CLR.3c \
pthread_attr_setdetachstate.3c \
pthread_attr_setguardsize.3c \
pthread_attr_setinheritsched.3c \
+ pthread_attr_setname_np.3c \
pthread_attr_setschedparam.3c \
pthread_attr_setschedpolicy.3c \
pthread_attr_setscope.3c \
@@ -1131,6 +1135,7 @@ MANLINKS= FD_CLR.3c \
pthread_rwlockattr_destroy.3c \
pthread_rwlockattr_setpshared.3c \
pthread_setconcurrency.3c \
+ pthread_setname_np.3c \
pthread_setschedparam.3c \
pthread_setspecific.3c \
pthread_spin_init.3c \
@@ -1294,6 +1299,7 @@ MANLINKS= FD_CLR.3c \
thr_continue.3c \
thr_getspecific.3c \
thr_keycreate_once.3c \
+ thr_setname.3c \
thr_setconcurrency.3c \
thr_setprio.3c \
thr_setspecific.3c \
@@ -2143,6 +2149,8 @@ pthread_attr_setguardsize.3c := LINKSRC = pthread_attr_getguardsize.3c
pthread_attr_setinheritsched.3c := LINKSRC = pthread_attr_getinheritsched.3c
+pthread_attr_setname_np.3c := LINKSRC = pthread_attr_getname_np.3c
+
pthread_attr_setschedparam.3c := LINKSRC = pthread_attr_getschedparam.3c
pthread_attr_setschedpolicy.3c := LINKSRC = pthread_attr_getschedpolicy.3c
@@ -2177,6 +2185,8 @@ pthread_condattr_destroy.3c := LINKSRC = pthread_condattr_init.3c
pthread_setconcurrency.3c := LINKSRC = pthread_getconcurrency.3c
+pthread_setname_np.3c := LINKSRC = pthread_getname_np.3c
+
pthread_setschedparam.3c := LINKSRC = pthread_getschedparam.3c
pthread_setspecific.3c := LINKSRC = pthread_getspecific.3c
@@ -2411,6 +2421,8 @@ thr_setspecific.3c := LINKSRC = thr_keycreate.3c
thr_continue.3c := LINKSRC = thr_suspend.3c
+thr_setname.3c := LINKSRC = thr_getname.3c
+
timegm.3c := LINKSRC = mktime.3c
timer_getoverrun.3c := LINKSRC = timer_settime.3c
diff --git a/usr/src/man/man3c/pthread_attr_getname_np.3c b/usr/src/man/man3c/pthread_attr_getname_np.3c
new file mode 100644
index 0000000000..fbac370410
--- /dev/null
+++ b/usr/src/man/man3c/pthread_attr_getname_np.3c
@@ -0,0 +1,105 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Joyent, Inc.
+.\"
+.Dd "August 22, 2018"
+.Dt PTHREAD_ATTR_GETNAME_NP 3C
+.Os
+.Sh NAME
+.Nm pthread_attr_getname_np ,
+.Nm pthread_attr_setname_np
+.Nd get or set thread name attribute
+.Sh SYNOPSIS
+.In pthread.h
+.
+.Ft int
+.Fo pthread_attr_getname_np
+.Fa "pthread_attr_t *restrict attr"
+.Fa "char *name"
+.Fa "size_t len"
+.Fc
+.
+.Ft int
+.Fo pthread_attr_setname_np
+.Fa "pthread_attr_t *restrict attr"
+.Fa "const char *name"
+.Fc
+.
+.Sh DESCRIPTION
+The
+.Fn pthread_attr_setname_np
+and
+.Fn pthread_attr_getname_np
+functions, respectively, set and get the thread name attribute in
+.Fa attr
+to
+.Fa name .
+For
+.Fn pthread_attr_getname_np ,
+.Fa len
+is the size of
+.Fa name .
+Any threads created with
+.Xr pthread_create 3c
+using
+.Fa attr
+will have their name set to
+.Fa name
+upon creation.
+.Pp
+Thread names are limited to
+.Dv PTHREAD_MAX_NAMELEN_NP
+including the terminating NUL.
+They may only contain printable ASCII characters.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn pthread_attr_getname_np
+and
+.Fn pthread_attr_setname_np
+functions return
+.Sy 0 .
+Otherwise, an error number is returned to indicate the error.
+.Sh ERRORS
+The
+.Fn pthread_attr_getname_np
+function may fail with:
+.Bl -tag -width Er
+.It Er EINVAL
+The
+.Fa name
+argument is
+.Sy NULL .
+.It Er ERANGE
+The size of
+.Fa name
+as indicated by
+.Fa len
+is too small to contain the thread name.
+The buffer may be over-written with partial contents of the thread name.
+.El
+.Pp
+The
+.Fn pthread_attr_setname_np
+function may fail with:
+.Bl -tag -width Er
+.It Er ERANGE
+The length of name given in
+.Fa name
+exceeds the maximum size allowed.
+.El
+.Sh INTERFACE STABILITY
+.Sy Uncommitted
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr pthread_create 3c ,
+.Xr pthread_getname_np 3c
diff --git a/usr/src/man/man3c/pthread_getname_np.3c b/usr/src/man/man3c/pthread_getname_np.3c
new file mode 100644
index 0000000000..7404a4abfe
--- /dev/null
+++ b/usr/src/man/man3c/pthread_getname_np.3c
@@ -0,0 +1,124 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Joyent, Inc.
+.\"
+.Dd "August 22, 2018"
+.Dt PTHREAD_GETNAME_NP 3C
+.Os
+.Sh NAME
+.Nm pthread_getname_np ,
+.Nm pthread_setname_np
+.Nd get or set the name of a thread
+.Sh SYNOPSIS
+.In pthread.h
+.
+.Ft int
+.Fo pthread_getname_np
+.Fa "pthread_t tid"
+.Fa "char *name"
+.Fa "size_t len"
+.Fc
+.
+.Ft int
+.Fo pthread_setname_np
+.Fa "pthread_t tid"
+.Fa "const char *name"
+.Fc
+.
+.Sh DESCRIPTION
+The
+.Fn pthread_getname_np
+and
+.Fn pthread_setname_np
+functions, respectively, get and set the names of the thread whose id is given
+by the
+.Fa tid
+parameter.
+For
+.Fn pthread_getname_np ,
+.Fa len
+indicates the size of
+.Fa name .
+.Pp
+Thread names are limited to
+.Dv PTHREAD_MAX_NAMELEN_NP
+including the terminating NUL.
+They may only contain printable ASCII characters.
+.Pp
+To clear a thread name, call
+.Fn pthread_setname_np
+with
+.Sy NULL .
+.Pp
+Unlike some other systems, threads do not inherit the process name by default.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn pthread_getname_np
+and
+.Fn pthread_setname_np
+functions return
+.Sy 0 .
+Otherwise, an error number is returned to indicate the error.
+If the thread identified by
+.Fa tid
+does not have a name set,
+.Fa pthread_getname_np
+will be set to an empty string (length = 0).
+.Sh ERRORS
+On failure, the contents of the buffer are undefined.
+Errors from
+.Xr open 2 ,
+.Xr read 2 ,
+or
+.Xr write 2
+are possible.
+In addition, the
+.Fn pthread_getname_np
+function will fail with:
+.Bl -tag -width Er
+.It Er EINVAL
+The
+.Fa name
+argument is
+.Sy NULL .
+.It Er ERANGE
+The size of
+.Fa name
+as given by
+.Fa len
+was not large enough to contain the name of the thread.
+.It Er ESRCH
+The thread
+.Fa tid
+was not found.
+.El
+.Pp
+The
+.Fn pthread_setname_np
+function will fail with:
+.Bl -tag -width Er
+.It Er ERANGE
+The length of
+.Fa name
+exceeds the maximum allowed size.
+.It Er ESRCH
+The thread
+.Fa tid
+was not found.
+.El
+.Sh INTERFACE STABILITY
+.Sy Uncommitted
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr pthread_attr_getname_np 3c ,
+.Xr pthread_create 3c
diff --git a/usr/src/man/man3c/thr_getname.3c b/usr/src/man/man3c/thr_getname.3c
new file mode 100644
index 0000000000..551e620d46
--- /dev/null
+++ b/usr/src/man/man3c/thr_getname.3c
@@ -0,0 +1,124 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Joyent, Inc.
+.\"
+.Dd "August 22, 2018"
+.Dt THR_GETNAME 3C
+.Os
+.Sh NAME
+.Nm thr_getname ,
+.Nm thr_setname
+.Nd get or set the name of a thread
+.Sh SYNOPSIS
+.In thread.h
+.
+.Ft int
+.Fo thr_getname
+.Fa "thread_t tid"
+.Fa "char *name"
+.Fa "size_t len"
+.Fc
+.
+.Ft int
+.Fo thr_setname
+.Fa "thread_t tid"
+.Fa "const char *name"
+.Fc
+.
+.Sh DESCRIPTION
+The
+.Fn thr_getname
+and
+.Fn thr_setname
+functions, respectively, get and set the names of the thread whose id is given
+by the
+.Fa tid
+parameter.
+For
+.Fn thr_getname ,
+.Fa len
+indicates the size of
+.Fa name .
+.Pp
+Thread names are limited to
+.Dv THREAD_NAME_MAX
+including the terminating NUL.
+They may only contain printable ASCII characters.
+.Pp
+To clear a thread name, call
+.Fn thr_setname
+with
+.Sy NULL .
+.Pp
+Unlike some other systems, threads do not inherit the process name by default.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn thr_getname
+and
+.Fn thr_setname
+functions return
+.Sy 0 .
+Otherwise, an error number is returned to indicate the error.
+If the thread identified by
+.Fa tid
+does not have a name set,
+.Fa thr_getname
+will be set to an empty string (length = 0).
+.Sh ERRORS
+On failure, the contents of the buffer are undefined.
+Errors from
+.Xr open 2 ,
+.Xr read 2 ,
+or
+.Xr write 2
+are possible.
+In addition, the
+.Fn thr_getname
+function will fail with:
+.Bl -tag -width Er
+.It Er EINVAL
+The
+.Fa name
+argument is
+.Sy NULL .
+.It Er ERANGE
+The size of
+.Fa name
+as given by
+.Fa len
+was not large enough to contain the name of the thread.
+.It Er ESRCH
+The thread
+.Fa tid
+was not found.
+.El
+.Pp
+The
+.Fn thr_setname
+function will fail with:
+.Bl -tag -width Er
+.It Er ERANGE
+The length of
+.Fa name
+exceeds the maximum allowed size.
+.It Er ESRCH
+The thread
+.Fa tid
+was not found.
+.El
+.Sh INTERFACE STABILITY
+.Sy Uncommitted
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr pthread_setname_np 3c ,
+.Xr thr_create 3c
diff --git a/usr/src/man/man3lib/libproc.3lib b/usr/src/man/man3lib/libproc.3lib
index 915febee0b..6b1e26eaf8 100644
--- a/usr/src/man/man3lib/libproc.3lib
+++ b/usr/src/man/man3lib/libproc.3lib
@@ -9,9 +9,9 @@
.\" http://www.illumos.org/license/CDDL.
.\"
.\"
-.\" Copyright 2015 Joyent, Inc.
+.\" Copyright 2018 Joyent, Inc.
.\"
-.Dd June 06, 2016
+.Dd August 31, 2018
.Dt LIBPROC 3LIB
.Os
.Sh NAME
@@ -217,34 +217,34 @@ manipulation of the process itself.
.It Sy Plmid_to_loadobj Ta Sy Plmid_to_map
.It Sy Plookup_by_addr Ta Sy Plookup_by_name
.It Sy Plwp_alt_stack Ta Sy Plwp_getfpregs
-.It Sy Plwp_getpsinfo Ta Sy Plwp_getregs
-.It Sy Plwp_getspymaster Ta Sy Plwp_main_stack
-.It Sy Plwp_setfpregs Ta Sy Plwp_setregs
-.It Sy Plwp_stack Ta Sy Pname_to_ctf
-.It Sy Pname_to_loadobj Ta Sy Pname_to_map
-.It Sy Pobjname Ta Sy Pobjname_resolved
-.It Sy Pplatform Ta Sy Ppltdest
-.It Sy Ppriv Ta Sy Ppsinfo
-.It Sy Pputareg Ta Sy Prd_agent
-.It Sy Pread Ta Sy Pread_string
-.It Sy Preset_maps Ta Sy Psetbkpt
-.It Sy Psecflags Ta Sy Psetcred
-.It Sy Psetfault Ta Sy Psetflags
-.It Sy Psetpriv Ta Sy Psetrun
-.It Sy Psetsignal Ta Sy Psetsysentry
-.It Sy Psetsysexit Ta Sy Psetwapt
-.It Sy Psetzoneid Ta Sy Psignal
-.It Sy Pstate Ta Sy Pstatus
-.It Sy Pstop Ta Sy Pstopstatus
-.It Sy Psync Ta Sy Psysentry
-.It Sy Psysexit Ta Sy Puname
-.It Sy Punsetflags Ta Sy Pupdate_maps
-.It Sy Pupdate_syms Ta Sy Pwait
-.It Sy Pwrite Ta Sy Pxecbkpt
-.It Sy Pxecwapt Ta Sy Pxlookup_by_addr
-.It Sy Pxlookup_by_addr_resolved Ta Sy Pxlookup_by_name
-.It Sy Pzonename Ta Sy Pzonepath
-.It Sy Pzoneroot Ta
+.It Sy Plwp_getname Ta Sy Plwp_getpsinfo
+.It Sy Plwp_getregs Ta Sy Plwp_getspymaster
+.It Sy Plwp_main_stack Ta Sy Plwp_setfpregs
+.It Sy Plwp_setregs Ta Sy Plwp_stack
+.It Sy Pname_to_ctf Ta Sy Pname_to_loadobj
+.It Sy Pname_to_map Ta Sy Pobjname
+.It Sy Pobjname_resolved Ta Sy Pplatform
+.It Sy Ppltdest Ta Sy Ppriv
+.It Sy Ppsinfo Ta Sy Pputareg
+.It Sy Prd_agent Ta Sy Pread
+.It Sy Pread_string Ta Sy Preset_maps
+.It Sy Psetbkpt Ta Sy Psecflags
+.It Sy Psetcred Ta Sy Psetfault
+.It Sy Psetflags Ta Sy Psetpriv
+.It Sy Psetrun Ta Sy Psetsignal
+.It Sy Psetsysentry Ta Sy Psetsysexit
+.It Sy Psetwapt Ta Sy Psetzoneid
+.It Sy Psignal Ta Sy Pstate
+.It Sy Pstatus Ta Sy Pstop
+.It Sy Pstopstatus Ta Sy Psync
+.It Sy Psysentry Ta Sy Psysexit
+.It Sy Puname Ta Sy Punsetflags
+.It Sy Pupdate_maps Ta Sy Pupdate_syms
+.It Sy Pwait Ta Sy Pwrite
+.It Sy Pxecbkpt Ta Sy Pxecwapt
+.It Sy Pxlookup_by_addr Ta Sy Pxlookup_by_addr_resolved
+.It Sy Pxlookup_by_name Ta Sy Pzonename
+.It Sy Pzonepath Ta Sy Pzoneroot Ta
.El
.Ss Thread interrogation and manipulation
The following routines obtain information about a thread and allow
diff --git a/usr/src/man/man3proc/Makefile b/usr/src/man/man3proc/Makefile
index 0984b6871f..e59e81fbf3 100644
--- a/usr/src/man/man3proc/Makefile
+++ b/usr/src/man/man3proc/Makefile
@@ -12,12 +12,12 @@
#
# Copyright 2011, Richard Lowe
# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
-# Copyright 2015 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
include $(SRC)/Makefile.master
-MANSECT= 3proc
+MANSECT= 3proc
MANFILES= \
Lctlfd.3proc \
@@ -64,6 +64,7 @@ MANFILES= \
Plookup_by_addr.3proc \
Plwp_getasrs.3proc \
Plwp_getgwindows.3proc \
+ Plwp_getname.3proc \
Plwp_getpsinfo.3proc \
Plwp_getregs.3proc \
Plwp_getspymaster.3proc \
@@ -160,10 +161,10 @@ MANFILES= \
Pwrite.3proc \
Pxecbkpt.3proc \
Pzonename.3proc \
- ps_lgetregs.3proc \
- ps_pglobal_lookup.3proc \
- ps_pread.3proc \
- ps_pstop.3proc
+ ps_lgetregs.3proc \
+ ps_pglobal_lookup.3proc \
+ ps_pread.3proc \
+ ps_pstop.3proc
MANLINKS= \
@@ -265,7 +266,7 @@ MANLINKS= \
Pxlookup_by_name.3proc \
Pxsymbol_iter.3proc \
Pzonepath.3proc \
- Pzoneroot.3proc
+ Pzoneroot.3proc
ps_lgetfpregs.3proc := LINKSRC = ps_lgetregs.3proc
diff --git a/usr/src/man/man3proc/Plwp_getname.3proc b/usr/src/man/man3proc/Plwp_getname.3proc
new file mode 100644
index 0000000000..57326f9333
--- /dev/null
+++ b/usr/src/man/man3proc/Plwp_getname.3proc
@@ -0,0 +1,94 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Joyent, Inc.
+.\"
+.Dd August 31, 2018
+.Dt PLWP_GETNAME 3PROC
+.Os
+.Sh NAME
+.Nm Plwp_getname
+.Nd get thread name
+.Sh SYNOPSIS
+.Lb libproc
+.In libproc.h
+.Ft int
+.Fo Plwp_getname
+.Fa "struct ps_prochandle *P"
+.Fa "lwpid_t lwpid"
+.Fa "char *buf"
+.Fa "size_t bufsize"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn Plwp_getname
+function returns the thread name in the supplied buffer, from the
+thread
+.Fa lwpid
+in the process handle
+.Fa P .
+.Pp
+If no thread name is set, the buffer is set to the empty string.
+The buffer should be at least
+.Dv THREAD_NAME_MAX
+in size.
+.Pp
+The
+.Fn Plwp_getname
+function only works on process handles that refer to active processes
+and core files, it does not work on process handles that refer to
+individual files.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn Plwp_getname
+function returns 0.
+Otherwise,
+.Sy -1
+is returned,
+.Sy errno
+is set to indicate the error.
+The buffer may be modified even if an error is returned.
+.Sh ERRORS
+For a full list of possible errors also see the
+.Sy DIAGNOSTICS
+section in
+.Xr proc 4 .
+.Pp
+The
+.Fn Plwp_getname
+function will fail if:
+.Bl -tag -width Er
+.It Er ENODATA
+.Fa P
+refers to a file handle obtained through
+.Xr Pgrab_file 3PROC .
+.It Er EINVAL
+The process handle
+.Fa P
+refers to a core file and the specified thread does not exist.
+.It Er ENOENT
+The process handle
+.Fa P
+refers to an active process and the specified thread does not exist.
+.Fa P
+.It Er ENAMETOOLONG
+The buffer is not sufficient to hold the thread name.
+.El
+.Sh INTERFACE STABILITY
+.Sy Uncommitted
+.Sh MT-LEVEL
+See
+.Sy LOCKING
+in
+.Xr libproc 3LIB .
+.Sh SEE ALSO
+.Xr libproc 3LIB ,
+.Xr proc 4
diff --git a/usr/src/man/man4/proc.4 b/usr/src/man/man4/proc.4
index 3e5a9bb95f..b60c0085c7 100644
--- a/usr/src/man/man4/proc.4
+++ b/usr/src/man/man4/proc.4
@@ -1,11 +1,11 @@
'\" te
.\" Copyright 1989 AT&T
.\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved.
-.\" Copyright 2017, Joyent, Inc.
+.\" Copyright 2018, Joyent, Inc.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.Dd Jun 24, 2016
+.Dd "August 22, 2018"
.Dt PROC 4
.Os
.Sh NAME
@@ -982,12 +982,12 @@ typedef struct psinfo {
uintptr_t pr_argv; /* address of initial argument vector */
uintptr_t pr_envp; /* address of initial environment vector */
char pr_dmodel; /* data model of the process */
- lwpsinfo_t pr_lwp; /* information for representative lwp */
taskid_t pr_taskid; /* task id */
projid_t pr_projid; /* project id */
poolid_t pr_poolid; /* pool id */
zoneid_t pr_zoneid; /* zone id */
ctid_t pr_contract; /* process contract id */
+ lwpsinfo_t pr_lwp; /* information for representative lwp */
} psinfo_t;
.Ed
.Pp
@@ -1647,6 +1647,20 @@ The messages written to this file affect the specific
lwp rather than the representative lwp, as is the case for the process's
.Pa ctl
file.
+.Ss lwpname
+A buffer of
+.Dv THREAD_NAME_MAX
+bytes representing the LWP name; the buffer is
+zero-filled if the thread name is shorter than the buffer.
+If no thread name is set, the buffer contains the empty string.
+A read with a buffer shorter than
+.Dv THREAD_NAME_MAX
+bytes is not guaranteed
+to be NUL-terminated.
+Writing to this file will set the LWP name for the specific lwp.
+This file may not be present in older operating system versions.
+.Dv THREAD_NAME_MAX
+may increase in the future; clients should be prepared for this.
.Ss lwpstatus
lwp-specific state information.
This file contains the
diff --git a/usr/src/pkg/manifests/system-dtrace-tests.mf b/usr/src/pkg/manifests/system-dtrace-tests.mf
index 72099167b7..f39776b305 100644
--- a/usr/src/pkg/manifests/system-dtrace-tests.mf
+++ b/usr/src/pkg/manifests/system-dtrace-tests.mf
@@ -22,6 +22,7 @@
#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2018 Joyent, Inc.
#
set name=pkg.fmri value=pkg:/system/dtrace/tests@$(PKGVERS)
@@ -115,6 +116,7 @@ dir path=opt/SUNWdtrt/tst/common/struct
dir path=opt/SUNWdtrt/tst/common/sugar
dir path=opt/SUNWdtrt/tst/common/syscall
dir path=opt/SUNWdtrt/tst/common/sysevent
+dir path=opt/SUNWdtrt/tst/common/threadname
dir path=opt/SUNWdtrt/tst/common/tick-n
dir path=opt/SUNWdtrt/tst/common/trace
dir path=opt/SUNWdtrt/tst/common/tracemem
@@ -1850,6 +1852,8 @@ file path=opt/SUNWdtrt/tst/common/sysevent/tst.post.d mode=0444
file path=opt/SUNWdtrt/tst/common/sysevent/tst.post.exe mode=0555
file path=opt/SUNWdtrt/tst/common/sysevent/tst.post_chan.d mode=0444
file path=opt/SUNWdtrt/tst/common/sysevent/tst.post_chan.exe mode=0555
+file path=opt/SUNWdtrt/tst/common/tick-n/tst.threadname.d mode=0444
+file path=opt/SUNWdtrt/tst/common/tick-n/tst.threadname.exe mode=0555
file path=opt/SUNWdtrt/tst/common/tick-n/err.D_PDESC_ZERO.tick.d mode=0444
file path=opt/SUNWdtrt/tst/common/tick-n/err.D_PDESC_ZEROonens.d mode=0444
file path=opt/SUNWdtrt/tst/common/tick-n/err.D_PDESC_ZEROonensec.d mode=0444
diff --git a/usr/src/pkg/manifests/system-library.man3c.inc b/usr/src/pkg/manifests/system-library.man3c.inc
index 06f6fe8e7c..846ed5bf99 100644
--- a/usr/src/pkg/manifests/system-library.man3c.inc
+++ b/usr/src/pkg/manifests/system-library.man3c.inc
@@ -303,6 +303,7 @@ file path=usr/share/man/man3c/pthread_attr_get_np.3c
file path=usr/share/man/man3c/pthread_attr_getdetachstate.3c
file path=usr/share/man/man3c/pthread_attr_getguardsize.3c
file path=usr/share/man/man3c/pthread_attr_getinheritsched.3c
+file path=usr/share/man/man3c/pthread_attr_getname_np.3c
file path=usr/share/man/man3c/pthread_attr_getschedparam.3c
file path=usr/share/man/man3c/pthread_attr_getschedpolicy.3c
file path=usr/share/man/man3c/pthread_attr_getscope.3c
@@ -328,6 +329,7 @@ file path=usr/share/man/man3c/pthread_detach.3c
file path=usr/share/man/man3c/pthread_equal.3c
file path=usr/share/man/man3c/pthread_exit.3c
file path=usr/share/man/man3c/pthread_getconcurrency.3c
+file path=usr/share/man/man3c/pthread_getname_np.3c
file path=usr/share/man/man3c/pthread_getschedparam.3c
file path=usr/share/man/man3c/pthread_getspecific.3c
file path=usr/share/man/man3c/pthread_join.3c
@@ -472,6 +474,7 @@ file path=usr/share/man/man3c/termios.3c
file path=usr/share/man/man3c/thr_create.3c
file path=usr/share/man/man3c/thr_exit.3c
file path=usr/share/man/man3c/thr_getconcurrency.3c
+file path=usr/share/man/man3c/thr_getname.3c
file path=usr/share/man/man3c/thr_getprio.3c
file path=usr/share/man/man3c/thr_join.3c
file path=usr/share/man/man3c/thr_keycreate.3c
@@ -1109,6 +1112,8 @@ link path=usr/share/man/man3c/pthread_attr_setguardsize.3c \
target=pthread_attr_getguardsize.3c
link path=usr/share/man/man3c/pthread_attr_setinheritsched.3c \
target=pthread_attr_getinheritsched.3c
+link path=usr/share/man/man3c/pthread_attr_setname_np.3c \
+ target=pthread_attr_getname_np.3c
link path=usr/share/man/man3c/pthread_attr_setschedparam.3c \
target=pthread_attr_getschedparam.3c
link path=usr/share/man/man3c/pthread_attr_setschedpolicy.3c \
@@ -1181,6 +1186,8 @@ link path=usr/share/man/man3c/pthread_rwlockattr_setpshared.3c \
target=pthread_rwlockattr_getpshared.3c
link path=usr/share/man/man3c/pthread_setconcurrency.3c \
target=pthread_getconcurrency.3c
+link path=usr/share/man/man3c/pthread_setname_np.3c \
+ target=pthread_getname_np.3c
link path=usr/share/man/man3c/pthread_setschedparam.3c \
target=pthread_getschedparam.3c
link path=usr/share/man/man3c/pthread_setspecific.3c \
@@ -1365,6 +1372,8 @@ link path=usr/share/man/man3c/thr_getspecific.3c target=thr_keycreate.3c
link path=usr/share/man/man3c/thr_keycreate_once.3c target=thr_keycreate.3c
link path=usr/share/man/man3c/thr_setconcurrency.3c \
target=thr_getconcurrency.3c
+link path=usr/share/man/man3c/thr_setname.3c \
+ target=thr_getname.3c
link path=usr/share/man/man3c/thr_setprio.3c target=thr_getprio.3c
link path=usr/share/man/man3c/thr_setspecific.3c target=thr_keycreate.3c
link path=usr/share/man/man3c/thrd_sleep.3c target=nanosleep.3c
diff --git a/usr/src/pkg/manifests/system-library.man3proc.inc b/usr/src/pkg/manifests/system-library.man3proc.inc
index d7eeb3e42f..8528acca7b 100644
--- a/usr/src/pkg/manifests/system-library.man3proc.inc
+++ b/usr/src/pkg/manifests/system-library.man3proc.inc
@@ -10,7 +10,7 @@
#
#
-# Copyright 2015 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
file path=usr/share/man/man3proc/proc_service.3proc
@@ -81,6 +81,7 @@ file path=usr/share/man/man3proc/Plmid.3proc
file path=usr/share/man/man3proc/Plookup_by_addr.3proc
file path=usr/share/man/man3proc/Plwp_getasrs.3proc
file path=usr/share/man/man3proc/Plwp_getgwindows.3proc
+file path=usr/share/man/man3proc/Plwp_getname.3proc
file path=usr/share/man/man3proc/Plwp_getpsinfo.3proc
file path=usr/share/man/man3proc/Plwp_getregs.3proc
file path=usr/share/man/man3proc/Plwp_getspymaster.3proc
diff --git a/usr/src/pkg/manifests/system-test-libctest.mf b/usr/src/pkg/manifests/system-test-libctest.mf
index 135822a5fd..f01471e5bf 100644
--- a/usr/src/pkg/manifests/system-test-libctest.mf
+++ b/usr/src/pkg/manifests/system-test-libctest.mf
@@ -13,6 +13,7 @@
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright 2015 Garrett D'Amore <garrett@damore.org>
+# Copyright 2018 Joyent, Inc.
#
set name=pkg.fmri value=pkg:/system/test/libctest@$(PKGVERS)
@@ -158,6 +159,7 @@ file path=opt/libc-tests/tests/strerror mode=0555
file path=opt/libc-tests/tests/symbols/setup mode=0555
file path=opt/libc-tests/tests/symbols/symbols_test.$(ARCH) mode=0555
file path=opt/libc-tests/tests/symbols/symbols_test.$(ARCH64) mode=0555
+file path=opt/libc-tests/tests/thread_name mode=0555
file path=opt/libc-tests/tests/timespec_get.32 mode=0555
file path=opt/libc-tests/tests/timespec_get.64 mode=0555
file path=opt/libc-tests/tests/wcsncasecmp-7344.32 mode=0555
diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf
index 70e9d378c1..935920cc83 100644
--- a/usr/src/pkg/manifests/system-test-ostest.mf
+++ b/usr/src/pkg/manifests/system-test-ostest.mf
@@ -72,10 +72,6 @@ file path=opt/os-tests/tests/sockfs/drop_priv mode=0555
file path=opt/os-tests/tests/sockfs/nosignal mode=0555
file path=opt/os-tests/tests/sockfs/sockpair mode=0555
file path=opt/os-tests/tests/spoof-ras mode=0555
-file path=opt/os-tests/tests/file-locking/runtests.32 mode=0555
-file path=opt/os-tests/tests/file-locking/runtests.64 mode=0555
-file path=opt/os-tests/tests/file-locking/acquire-lock.32 mode=0555
-file path=opt/os-tests/tests/file-locking/acquire-lock.64 mode=0555
file path=opt/os-tests/tests/stress/dladm-kstat mode=0555
license cr_Sun license=cr_Sun
license lic_CDDL license=lic_CDDL
diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run
index 6781cba483..228c15122e 100644
--- a/usr/src/test/libc-tests/runfiles/default.run
+++ b/usr/src/test/libc-tests/runfiles/default.run
@@ -12,7 +12,7 @@
#
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
-# Copyright 2017 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
[DEFAULT]
@@ -92,6 +92,7 @@ timeout = 600
[/opt/libc-tests/tests/set_constraint_handler_s.32]
[/opt/libc-tests/tests/set_constraint_handler_s.64]
[/opt/libc-tests/tests/strerror]
+[/opt/libc-tests/tests/thread_name]
[/opt/libc-tests/tests/timespec_get.32]
[/opt/libc-tests/tests/timespec_get.64]
diff --git a/usr/src/test/libc-tests/tests/threads/Makefile b/usr/src/test/libc-tests/tests/threads/Makefile
index 1e73e7b8c7..31cb1ddefe 100644
--- a/usr/src/test/libc-tests/tests/threads/Makefile
+++ b/usr/src/test/libc-tests/tests/threads/Makefile
@@ -10,7 +10,7 @@
#
#
-# Copyright 2016 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
include $(SRC)/Makefile.master
@@ -18,7 +18,7 @@ include $(SRC)/Makefile.master
ROOTOPTPKG = $(ROOT)/opt/libc-tests
TESTDIR = $(ROOTOPTPKG)/tests
-PROGS = pthread_attr_get_np
+PROGS = pthread_attr_get_np thread_name
include $(SRC)/cmd/Makefile.cmd
include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/libc-tests/tests/threads/thread_name.c b/usr/src/test/libc-tests/tests/threads/thread_name.c
new file mode 100644
index 0000000000..b164272644
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/threads/thread_name.c
@@ -0,0 +1,278 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
+/*
+ * Some basic pthread name API tests.
+ */
+
+#include <sys/stat.h>
+#include <pthread.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <thread.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <err.h>
+
+
+/*ARGSUSED*/
+static void *
+thr(void *unused)
+{
+ (void) sleep(100);
+ return (NULL);
+}
+
+/*ARGSUSED*/
+int
+main(int argc, char *argv[])
+{
+ char name[PTHREAD_MAX_NAMELEN_NP];
+ pthread_attr_t attr;
+ char path[PATH_MAX];
+ pthread_t tid;
+ ssize_t n;
+ int test;
+ int rc;
+ int fd;
+
+ /* Default thread name is empty string. */
+ test = 1;
+
+ rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* Can set name. */
+ test = 2;
+
+ (void) strlcpy(name, "main", sizeof (name));
+ rc = pthread_setname_np(pthread_self(), name);
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "main") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* ERANGE check. */
+ test = 3;
+
+ rc = pthread_getname_np(pthread_self(), name, 2);
+
+ if (rc != ERANGE)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* EINVAL check. */
+ test = 4;
+
+ rc = pthread_getname_np(pthread_self(), NULL, sizeof (name));
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* can clear thread name. */
+ test = 5;
+
+ rc = pthread_setname_np(pthread_self(), NULL);
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* non-existent thread check. */
+ test = 6;
+
+ rc = pthread_getname_np(808, name, sizeof (name));
+
+ if (rc != ESRCH)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_setname_np(808, "state");
+
+ if (rc != ESRCH)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* too long a name. */
+ test = 7;
+
+ rc = pthread_setname_np(pthread_self(),
+ "12345678901234567890123456789012");
+
+ if (rc != ERANGE)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* can name another thread. */
+ test = 8;
+
+ rc = pthread_create(&tid, NULL, thr, NULL);
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_setname_np(tid, "otherthread");
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* attr tests. */
+ test = 9;
+
+ (void) pthread_attr_init(&attr);
+
+ rc = pthread_attr_setname_np(&attr,
+ "12345678901234567890123456789012");
+
+ if (rc != ERANGE)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_setname_np(&attr, "thread2");
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_getname_np(&attr, NULL, sizeof (name));
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_getname_np(&attr, name, 2);
+
+ if (rc != ERANGE)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* does the attr actually apply? */
+ test = 10;
+
+ rc = pthread_create(&tid, &attr, thr, NULL);
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_getname_np(tid, name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "thread2") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* proc read tests */
+ test = 11;
+
+ (void) snprintf(path, sizeof (path),
+ "/proc/self/lwp/%d/lwpname", (int)tid);
+
+ fd = open(path, O_RDWR);
+
+ if (fd == -1)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = read(fd, name, sizeof (name));
+
+ if (n != sizeof (name) || strcmp(name, "thread2") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = read(fd, name, PTHREAD_MAX_NAMELEN_NP * 2);
+
+ if (n != sizeof (name) || strcmp(name, "thread2") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = read(fd, name, 4);
+
+ if (n != 4 || strncmp(name, "thre", 4) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* proc write tests */
+ test = 12;
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = write(fd, "1234567890123456789012345678901",
+ PTHREAD_MAX_NAMELEN_NP);
+
+ if (n != PTHREAD_MAX_NAMELEN_NP)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = write(fd, "foo", sizeof ("foo"));
+
+ if (n != sizeof ("foo"))
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = read(fd, name, sizeof (name));
+
+ if (n != sizeof (name) || strcmp(name, "foo") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ (void) close(fd);
+
+ /* thr_* API. */
+ test = 13;
+
+ rc = thr_setname(thr_self(), "main");
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = thr_getname(thr_self(), name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "main") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* badness */
+ test = 14;
+
+ rc = thr_setname(thr_self(), "\033]0;messeduptitle\a");
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = thr_setname(thr_self(), "ab\177\177\n");
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_setname_np(&attr, "\033]0;messeduptitle\a");
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_setname_np(&attr, "ab\177\177\n");
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ return (EXIT_SUCCESS);
+}
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_prctl.c b/usr/src/uts/common/brand/lx/syscall/lx_prctl.c
index 4aecb6e9cc..a8b3c3422c 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_prctl.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_prctl.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
*/
#include <sys/systm.h>
@@ -175,7 +175,9 @@ lx_prctl(int opt, uintptr_t data)
}
name[LX_PR_SET_NAME_NAMELEN - 1] = '\0';
- thread_setname(t, name);
+ if ((ret = thread_setname(t, name)) != 0) {
+ return (set_errno(ret));
+ }
/*
* In Linux, PR_SET_NAME sets the name of the thread, not the
diff --git a/usr/src/uts/common/disp/thread.c b/usr/src/uts/common/disp/thread.c
index aece8faaff..d576738e75 100644
--- a/usr/src/uts/common/disp/thread.c
+++ b/usr/src/uts/common/disp/thread.c
@@ -74,6 +74,7 @@
#include <sys/waitq.h>
#include <sys/cpucaps.h>
#include <sys/kiconv.h>
+#include <sys/ctype.h>
#include <sys/ht.h>
#ifndef STACK_GROWTH_DOWN
@@ -2334,7 +2335,7 @@ stkinfo_percent(caddr_t t_stk, caddr_t t_stkbase, caddr_t sp)
* It is also expected callers on behalf of userland clients have done
* any necessary permission checks.
*/
-void
+int
thread_setname(kthread_t *t, const char *name)
{
char *buf = NULL;
@@ -2355,6 +2356,11 @@ thread_setname(kthread_t *t, const char *name)
* usage in highly constrained situations (e.g. dtrace).
*/
if (name != NULL && name[0] != '\0') {
+ for (size_t i = 0; name[i] != '\0'; i++) {
+ if (!isprint(name[i]))
+ return (EINVAL);
+ }
+
buf = kmem_zalloc(THREAD_NAME_MAX, KM_SLEEP);
(void) strlcpy(buf, name, THREAD_NAME_MAX);
}
@@ -2371,4 +2377,25 @@ thread_setname(kthread_t *t, const char *name)
}
}
mutex_exit(&ttoproc(t)->p_lock);
+ return (0);
+}
+
+int
+thread_vsetname(kthread_t *t, const char *fmt, ...)
+{
+ char name[THREAD_NAME_MAX];
+ va_list va;
+ int rc;
+
+ va_start(va, fmt);
+ rc = vsnprintf(name, sizeof (name), fmt, va);
+ va_end(va);
+
+ if (rc < 0)
+ return (EINVAL);
+
+ if (rc >= sizeof (name))
+ return (ENAMETOOLONG);
+
+ return (thread_setname(t, name));
}
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c
index 9b53e08b6a..8184bc27b9 100644
--- a/usr/src/uts/common/dtrace/dtrace.c
+++ b/usr/src/uts/common/dtrace/dtrace.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
*/
@@ -3539,6 +3539,25 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
return ((uint64_t)lwp->lwp_errno);
}
+
+ case DIF_VAR_THREADNAME:
+ /*
+ * See comment in DIF_VAR_PID.
+ */
+ if (DTRACE_ANCHORED(mstate->dtms_probe) && CPU_ON_INTR(CPU))
+ return (0);
+
+ if (curthread->t_name == NULL)
+ return (0);
+
+ /*
+ * Once set, ->t_name itself is never changed: any updates are
+ * made to the same buffer that we are pointing out. So we are
+ * safe to dereference it here.
+ */
+ return (dtrace_dif_varstr((uintptr_t)curthread->t_name,
+ state, mstate));
+
default:
DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
return (0);
@@ -5563,7 +5582,7 @@ next:
* Stringify using RFC 1884 convention 2 - 16 bit
* hexadecimal values with a zero-run compression.
* Lower case hexadecimal digits are used.
- * eg, fe80::214:4fff:fe0b:76c8.
+ * eg, fe80::214:4fff:fe0b:76c8.
* The IPv4 embedded form is returned for inet_ntop,
* just the IPv4 string is returned for inet_ntoa6.
*/
@@ -5747,7 +5766,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
*/
mstate->dtms_difo = difo;
- regs[DIF_REG_R0] = 0; /* %r0 is fixed at zero */
+ regs[DIF_REG_R0] = 0; /* %r0 is fixed at zero */
while (pc < textlen && !(*flags & CPU_DTRACE_FAULT)) {
opc = pc;
diff --git a/usr/src/uts/common/exec/elf/elf_notes.c b/usr/src/uts/common/exec/elf/elf_notes.c
index 7453f6c745..d977d28540 100644
--- a/usr/src/uts/common/exec/elf/elf_notes.c
+++ b/usr/src/uts/common/exec/elf/elf_notes.c
@@ -26,7 +26,7 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright 2016, Joyent, Inc.
+ * Copyright 2018, Joyent, Inc.
*/
#include <sys/types.h>
@@ -94,7 +94,7 @@ setup_note_header(Phdr *v, proc_t *p)
v[0].p_type = PT_NOTE;
v[0].p_flags = PF_R;
- v[0].p_filesz = (sizeof (Note) * (10 + 2 * nlwp + nzomb + nfd))
+ v[0].p_filesz = (sizeof (Note) * (10 + 3 * nlwp + nzomb + nfd))
+ roundup(sizeof (psinfo_t), sizeof (Word))
+ roundup(sizeof (pstatus_t), sizeof (Word))
+ roundup(prgetprivsize(), sizeof (Word))
@@ -107,6 +107,7 @@ setup_note_header(Phdr *v, proc_t *p)
+ roundup(sizeof (prsecflags_t), sizeof (Word))
+ (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word))
+ nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word))
+ + nlwp * roundup(sizeof (prlwpname_t), sizeof (Word))
+ nfd * roundup(sizeof (prfdinfo_t), sizeof (Word));
if (curproc->p_agenttp != NULL) {
@@ -458,6 +459,7 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
nzomb = p->p_zombcnt;
/* for each entry in the lwp directory ... */
for (ldp = p->p_lwpdir; nlwp + nzomb != 0; ldp++) {
+ prlwpname_t name = { 0, };
if ((lep = ldp->ld_entry) == NULL) /* empty slot */
continue;
@@ -468,6 +470,10 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
lwp = ttolwp(t);
mutex_enter(&p->p_lock);
prgetlwpsinfo(t, &bigwad->lwpsinfo);
+ if (t->t_name != NULL) {
+ (void) strlcpy(name.pr_lwpname, t->t_name,
+ sizeof (name.pr_lwpname));
+ }
mutex_exit(&p->p_lock);
} else { /* zombie lwp */
ASSERT(nzomb != 0);
@@ -478,11 +484,15 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
bigwad->lwpsinfo.pr_sname = 'Z';
bigwad->lwpsinfo.pr_start.tv_sec = lep->le_start;
}
+
+ name.pr_lwpid = bigwad->lwpsinfo.pr_lwpid;
+
error = elfnote(vp, &offset, NT_LWPSINFO,
sizeof (bigwad->lwpsinfo), (caddr_t)&bigwad->lwpsinfo,
rlimit, credp);
if (error)
goto done;
+
if (t == NULL) /* nothing more to do for a zombie */
continue;
@@ -516,6 +526,11 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
if (error)
goto done;
+ if ((error = elfnote(vp, &offset, NT_LWPNAME, sizeof (name),
+ (caddr_t)&name, rlimit, credp)) != 0)
+ goto done;
+
+
#if defined(__sparc)
/*
* Unspilled SPARC register windows.
diff --git a/usr/src/uts/common/fs/proc/prdata.h b/usr/src/uts/common/fs/proc/prdata.h
index 35a76597b2..706e3ad14d 100644
--- a/usr/src/uts/common/fs/proc/prdata.h
+++ b/usr/src/uts/common/fs/proc/prdata.h
@@ -27,7 +27,7 @@
/* All Rights Reserved */
/*
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _SYS_PROC_PRDATA_H
@@ -137,6 +137,7 @@ typedef enum prnodetype {
PR_LWPDIR, /* /proc/<pid>/lwp */
PR_LWPIDDIR, /* /proc/<pid>/lwp/<lwpid> */
PR_LWPCTL, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
+ PR_LWPNAME, /* /proc/<pid>/lwp/<lwpid>/lwpname */
PR_LWPSTATUS, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
PR_LWPSINFO, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
PR_LWPUSAGE, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
@@ -363,7 +364,7 @@ extern void prgetaction(proc_t *, user_t *, uint_t, struct sigaction *);
extern void prgetusage(kthread_t *, struct prhusage *);
extern void praddusage(kthread_t *, struct prhusage *);
extern void prcvtusage(struct prhusage *, prusage_t *);
-extern void prscaleusage(prhusage_t *);
+extern void prscaleusage(prhusage_t *);
extern kthread_t *prchoose(proc_t *);
extern void allsetrun(proc_t *);
extern int setisempty(uint32_t *, uint_t);
diff --git a/usr/src/uts/common/fs/proc/prvnops.c b/usr/src/uts/common/fs/proc/prvnops.c
index fa5f637f05..57d01c86f0 100644
--- a/usr/src/uts/common/fs/proc/prvnops.c
+++ b/usr/src/uts/common/fs/proc/prvnops.c
@@ -21,12 +21,12 @@
/*
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
* Copyright (c) 2017 by Delphix. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
+/* All Rights Reserved */
#include <sys/types.h>
#include <sys/param.h>
@@ -64,6 +64,7 @@
#include <sys/contract_impl.h>
#include <sys/ctfs.h>
#include <sys/avl.h>
+#include <sys/ctype.h>
#include <fs/fs_subr.h>
#include <vm/rm.h>
#include <vm/as.h>
@@ -190,22 +191,24 @@ static prdirent_t lwpiddir[] = {
".." },
{ PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
"lwpctl" },
- { PR_LWPSTATUS, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
+ { PR_LWPNAME, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
+ "lwpname" },
+ { PR_LWPSTATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
"lwpstatus" },
- { PR_LWPSINFO, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
+ { PR_LWPSINFO, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
"lwpsinfo" },
- { PR_LWPUSAGE, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
+ { PR_LWPUSAGE, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
"lwpusage" },
- { PR_XREGS, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
+ { PR_XREGS, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
"xregs" },
- { PR_TMPLDIR, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
+ { PR_TMPLDIR, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
"templates" },
- { PR_SPYMASTER, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
+ { PR_SPYMASTER, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
"spymaster" },
#if defined(__sparc)
- { PR_GWINDOWS, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
+ { PR_GWINDOWS, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
"gwindows" },
- { PR_ASRS, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
+ { PR_ASRS, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
"asrs" },
#endif
};
@@ -595,7 +598,8 @@ static int pr_read_inval(), pr_read_as(), pr_read_status(),
pr_read_argv(),
pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
- pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(),
+ pr_read_lwpusage(), pr_read_lwpname(),
+ pr_read_xregs(), pr_read_priv(),
pr_read_spymaster(), pr_read_secflags(),
#if defined(__sparc)
pr_read_gwindows(), pr_read_asrs(),
@@ -635,6 +639,7 @@ static int (*pr_read_function[PR_NFILES])() = {
pr_read_inval, /* /proc/<pid>/lwp */
pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
+ pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
@@ -1117,7 +1122,7 @@ pr_read_auxv(prnode_t *pnp, uio_t *uiop)
* we have two kinds of LDT structures to export -- one for compatibility
* mode, and one for long mode, sigh.
*
- * For now lets just have a ldt of size 0 for 64-bit processes.
+ * For now let's just have a ldt of size 0 for 64-bit processes.
*/
static int
pr_read_ldt(prnode_t *pnp, uio_t *uiop)
@@ -1582,6 +1587,33 @@ out:
return (error);
}
+static int
+pr_read_lwpname(prnode_t *pnp, uio_t *uiop)
+{
+ char lwpname[THREAD_NAME_MAX];
+ kthread_t *t;
+ int error;
+
+ ASSERT(pnp->pr_type == PR_LWPNAME);
+
+ if (uiop->uio_offset >= THREAD_NAME_MAX)
+ return (0);
+
+ if ((error = prlock(pnp, ZNO)) != 0)
+ return (error);
+
+ bzero(lwpname, sizeof (lwpname));
+
+ t = pnp->pr_common->prc_thread;
+
+ if (t->t_name != NULL)
+ (void) strlcpy(lwpname, t->t_name, sizeof (lwpname));
+
+ prunlock(pnp);
+
+ return (pr_uioread(lwpname, sizeof (lwpname), uiop));
+}
+
/* ARGSUSED */
static int
pr_read_xregs(prnode_t *pnp, uio_t *uiop)
@@ -1853,6 +1885,7 @@ static int (*pr_read_function_32[PR_NFILES])() = {
pr_read_inval, /* /proc/<pid>/lwp */
pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
+ pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
@@ -2862,6 +2895,54 @@ pr_write_psinfo(prnode_t *pnp, uio_t *uiop)
}
+/* Note we intentionally don't handle partial writes/updates. */
+static int
+pr_write_lwpname(prnode_t *pnp, uio_t *uiop)
+{
+ kthread_t *t = NULL;
+ char *lwpname;
+ int error;
+
+ lwpname = kmem_zalloc(THREAD_NAME_MAX, KM_SLEEP);
+
+ if ((error = uiomove(lwpname, THREAD_NAME_MAX, UIO_WRITE, uiop)) != 0) {
+ kmem_free(lwpname, THREAD_NAME_MAX);
+ return (error);
+ }
+
+ /* Somebody tried to write too long a thread name... */
+ if (lwpname[THREAD_NAME_MAX - 1] != '\0' || uiop->uio_resid > 0) {
+ kmem_free(lwpname, THREAD_NAME_MAX);
+ return (EIO);
+ }
+
+ VERIFY3U(lwpname[THREAD_NAME_MAX - 1], ==, '\0');
+
+ for (size_t i = 0; lwpname[i] != '\0'; i++) {
+ if (!isprint(lwpname[i])) {
+ kmem_free(lwpname, THREAD_NAME_MAX);
+ return (EINVAL);
+ }
+ }
+
+ /* Equivalent of thread_setname(), but with the ZNO magic. */
+ if ((error = prlock(pnp, ZNO)) != 0) {
+ kmem_free(lwpname, THREAD_NAME_MAX);
+ return (error);
+ }
+
+ t = pnp->pr_common->prc_thread;
+ if (t->t_name == NULL) {
+ t->t_name = lwpname;
+ } else {
+ (void) strlcpy(t->t_name, lwpname, THREAD_NAME_MAX);
+ kmem_free(lwpname, THREAD_NAME_MAX);
+ }
+
+ prunlock(pnp);
+ return (0);
+}
+
/* ARGSUSED */
static int
prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
@@ -2943,6 +3024,9 @@ prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
case PR_PSINFO:
return (pr_write_psinfo(pnp, uiop));
+ case PR_LWPNAME:
+ return (pr_write_lwpname(pnp, uiop));
+
default:
return ((vp->v_type == VDIR)? EISDIR : EBADF);
}
@@ -3512,6 +3596,7 @@ static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
pr_lookup_lwpdir, /* /proc/<pid>/lwp */
pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
+ pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
@@ -4776,6 +4861,7 @@ prgetnode(vnode_t *dp, prnodetype_t type)
break;
case PR_PSINFO:
+ case PR_LWPNAME:
pnp->pr_mode = 0644; /* readable by all + owner can write */
break;
@@ -4904,6 +4990,7 @@ static int (*pr_readdir_function[PR_NFILES])() = {
pr_readdir_lwpdir, /* /proc/<pid>/lwp */
pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
+ pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h
index 44ca7d8ae7..ab6d4c4445 100644
--- a/usr/src/uts/common/sys/dtrace.h
+++ b/usr/src/uts/common/sys/dtrace.h
@@ -25,7 +25,7 @@
*/
/*
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -242,6 +242,7 @@ typedef enum dtrace_probespec {
#define DIF_VAR_UID 0x011e /* process user ID */
#define DIF_VAR_GID 0x011f /* process group ID */
#define DIF_VAR_ERRNO 0x0120 /* thread errno */
+#define DIF_VAR_THREADNAME 0x0121 /* thread name */
#define DIF_SUBR_RAND 0
#define DIF_SUBR_MUTEX_OWNED 1
@@ -2212,8 +2213,8 @@ extern void dtrace_probe(dtrace_id_t, uintptr_t arg0, uintptr_t arg1,
*/
typedef struct dtrace_helper_probedesc {
char *dthpb_mod; /* probe module */
- char *dthpb_func; /* probe function */
- char *dthpb_name; /* probe name */
+ char *dthpb_func; /* probe function */
+ char *dthpb_name; /* probe name */
uint64_t dthpb_base; /* base address */
uint32_t *dthpb_offs; /* offsets array */
uint32_t *dthpb_enoffs; /* is-enabled offsets array */
diff --git a/usr/src/uts/common/sys/elf.h b/usr/src/uts/common/sys/elf.h
index 0dd4f2d17e..1a2ca397ef 100644
--- a/usr/src/uts/common/sys/elf.h
+++ b/usr/src/uts/common/sys/elf.h
@@ -429,10 +429,10 @@ typedef struct {
#define ELFOSABI_OPENVMS 13 /* Open VMS */
#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */
#define ELFOSABI_AROS 15 /* Amiga Research OS */
-#define ELFOSABI_FENIXOS 16 /* The FenixOS highly scalable */
+#define ELFOSABI_FENIXOS 16 /* The FenixOS highly scalable */
/* multi-core OS */
-#define ELFOSABI_CLOUDABI 17 /* Nuxi CloudABI */
-#define ELFOSABI_OPENVOS 18 /* Stratus Technologies OpenVOS */
+#define ELFOSABI_CLOUDABI 17 /* Nuxi CloudABI */
+#define ELFOSABI_OPENVOS 18 /* Stratus Technologies OpenVOS */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* standalone (embedded) application */
@@ -820,7 +820,7 @@ typedef struct {
#define ELF32_R_INFO(sym, type) (((sym)<<8)+(unsigned char)(type))
#define ELF64_R_SYM(info) ((info)>>32)
-#define ELF64_R_TYPE(info) ((Elf64_Word)(info))
+#define ELF64_R_TYPE(info) ((Elf64_Word)(info))
#define ELF64_R_INFO(sym, type) (((Elf64_Xword)(sym)<<32)+(Elf64_Xword)(type))
@@ -867,7 +867,7 @@ typedef struct {
#if defined(_LP64) || defined(_LONGLONG_TYPE)
typedef struct {
Elf32_Lword m_value; /* symbol value */
- Elf32_Word m_info; /* size + index */
+ Elf32_Word m_info; /* size + index */
Elf32_Word m_poffset; /* symbol offset */
Elf32_Half m_repeat; /* repeat count */
Elf32_Half m_stride; /* stride info */
@@ -886,7 +886,7 @@ typedef struct {
typedef struct {
Elf64_Lword m_value; /* symbol value */
- Elf64_Xword m_info; /* size + index */
+ Elf64_Xword m_info; /* size + index */
Elf64_Xword m_poffset; /* symbol offset */
Elf64_Half m_repeat; /* repeat count */
Elf64_Half m_stride; /* stride info */
@@ -945,7 +945,7 @@ typedef Elf64_Word Elf64_Capchain;
* info = ELF64_C_INFO(sym, grp)
*/
#define ELF64_C_SYM(info) ((info)>>32)
-#define ELF64_C_GROUP(info) ((Elf64_Word)(info))
+#define ELF64_C_GROUP(info) ((Elf64_Word)(info))
#define ELF64_C_INFO(sym, grp) (((Elf64_Xword)(sym)<<32)+(Elf64_Xword)(grp))
#endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */
@@ -1014,10 +1014,11 @@ typedef Elf64_Word Elf64_Capchain;
#define NT_PRPRIVINFO 19 /* priv_impl_info_t <sys/priv.h> */
#define NT_CONTENT 20 /* core_content_t <sys/corectl.h> */
#define NT_ZONENAME 21 /* string from getzonenamebyid(3C) */
-#define NT_FDINFO 22 /* open fd info */
+#define NT_FDINFO 22 /* open fd info */
#define NT_SPYMASTER 23 /* psinfo_t for agent LWP spymaster */
#define NT_SECFLAGS 24 /* process security-flags */
-#define NT_NUM 24
+#define NT_LWPNAME 25 /* prlwpname_t */
+#define NT_NUM 25
#ifdef _KERNEL
diff --git a/usr/src/uts/common/sys/procfs.h b/usr/src/uts/common/sys/procfs.h
index 427d682d68..38c006f8f0 100644
--- a/usr/src/uts/common/sys/procfs.h
+++ b/usr/src/uts/common/sys/procfs.h
@@ -25,7 +25,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright 2015, Joyent, Inc.
+ * Copyright 2018, Joyent, Inc.
*/
#ifndef _SYS_PROCFS_H
@@ -66,6 +66,7 @@ extern "C" {
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/secflags.h>
+#include <sys/thread.h>
/*
* System call interfaces for /proc.
@@ -346,7 +347,7 @@ typedef struct prxmap {
int pr_shmid; /* SysV shmid, -1 if not SysV shared memory */
dev_t pr_dev; /* st_dev from stat64() of mapped object, or PRNODEV */
uint64_t pr_ino; /* st_ino from stat64() of mapped object, if any */
- size_t pr_rss; /* pages of resident memory */
+ size_t pr_rss; /* pages of resident memory */
size_t pr_anon; /* pages of resident anonymous memory */
size_t pr_locked; /* pages of locked memory */
size_t pr_pad; /* currently unused */
@@ -537,6 +538,16 @@ typedef struct prfdinfo {
} prfdinfo_t;
/*
+ * Representation of LWP name in core files. In /proc, we use a simple char
+ * array, but in core files we need to make it easy to correlate the note back
+ * to the right LWP. For simplicity, we'll use 32/64 consistent types.
+ */
+typedef struct prlwpname {
+ uint64_t pr_lwpid;
+ char pr_lwpname[THREAD_NAME_MAX];
+} prlwpname_t;
+
+/*
* Header for /proc/<pid>/lstatus /proc/<pid>/lpsinfo /proc/<pid>/lusage
*/
typedef struct prheader {
diff --git a/usr/src/uts/common/sys/thread.h b/usr/src/uts/common/sys/thread.h
index 678d356564..6cc474f864 100644
--- a/usr/src/uts/common/sys/thread.h
+++ b/usr/src/uts/common/sys/thread.h
@@ -607,7 +607,8 @@ extern disp_lock_t stop_lock; /* lock protecting stopped threads */
caddr_t thread_stk_init(caddr_t); /* init thread stack */
-void thread_setname(kthread_t *, const char *);
+int thread_setname(kthread_t *, const char *);
+int thread_vsetname(kthread_t *, const char *, ...);
extern int default_binding_mode;
extern int default_stksize;
diff --git a/usr/src/uts/i86pc/io/viona/viona.c b/usr/src/uts/i86pc/io/viona/viona.c
index c22c0bf646..5b60daabe2 100644
--- a/usr/src/uts/i86pc/io/viona/viona.c
+++ b/usr/src/uts/i86pc/io/viona/viona.c
@@ -1337,6 +1337,8 @@ viona_worker_rx(viona_vring_t *ring, viona_link_t *link)
{
proc_t *p = ttoproc(curthread);
+ thread_vsetname(curthread, "viona_rx_%p", ring);
+
ASSERT(MUTEX_HELD(&ring->vr_lock));
ASSERT3U(ring->vr_state, ==, VRS_RUN);
@@ -1370,6 +1372,8 @@ viona_worker_tx(viona_vring_t *ring, viona_link_t *link)
{
proc_t *p = ttoproc(curthread);
+ thread_vsetname(curthread, "viona_tx_%p", ring);
+
ASSERT(MUTEX_HELD(&ring->vr_lock));
ASSERT3U(ring->vr_state, ==, VRS_RUN);