--- old/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c	Mon Oct 15 13:24:01 2018
+++ new/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c	Mon Oct 15 13:24:01 2018
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  * Copyright 2016 Argo Technologie SA.
  * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>.
  */
@@ -457,6 +458,7 @@
 		(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);
@@ -1124,7 +1126,7 @@
 {
 	nvpair_t		*nvp = NULL;
 	char			*name, *strval = NULL;
-	ipmgmt_aobjmap_t 	node;
+	ipmgmt_aobjmap_t	node;
 	struct sockaddr_in6	*in6;
 
 	*errp = 0;
--- old/usr/src/cmd/dtrace/test/tst/common/Makefile	Mon Oct 15 13:24:01 2018
+++ new/usr/src/cmd/dtrace/test/tst/common/Makefile	Mon Oct 15 13:24:01 2018
@@ -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.
 #
 
 #
@@ -57,6 +57,8 @@
 
 ustack/tst.bigstack.exe := COPTFLAG += -xO1
 
+CSTD = $(CSTD_GNU99)
+
 nfs/%.o: $(SNOOPDIR)/%.c
 	$(COMPILE.c) -o $@ $< -I$(SNOOPDIR)
 	$(POST_PROCESS_O)
--- /dev/null	Mon Oct 15 13:24:01 2018
+++ new/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c	Mon Oct 15 13:24:01 2018
@@ -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);
+}
--- /dev/null	Mon Oct 15 13:24:01 2018
+++ new/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d	Mon Oct 15 13:24:01 2018
@@ -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);
+}
--- old/usr/src/cmd/halt/Makefile	Mon Oct 15 13:24:01 2018
+++ new/usr/src/cmd/halt/Makefile	Mon Oct 15 13:24:01 2018
@@ -21,6 +21,7 @@
 # Copyright 2016 Toomas Soome <tsoome@me.com>
 # Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
+# Copyright 2018 Joyent, Inc.
 #
 
 PROG = halt
@@ -60,10 +61,10 @@
 clean   :=	TARGET = clean
 clobber :=	TARGET = clobber
 lint    :=	TARGET = lint
-lint	:=	LINTFLAGS = -u
+lint	:=	LINTFLAGS += -u
 
 
-all: $(PROG) 
+all: $(PROG)
 
 install: all $(ROOTUSRSBINPROG) $(ROOTLINKS) $(ROOTSYMLINKS) $(SUBDIRS)
 
--- old/usr/src/cmd/ldapcachemgr/cachemgr_change.c	Mon Oct 15 13:24:01 2018
+++ new/usr/src/cmd/ldapcachemgr/cachemgr_change.c	Mon Oct 15 13:24:01 2018
@@ -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 @@
 	pid_t	pid;
 	int	always = 1, waiting;
 
+	(void) pthread_setname_np(pthread_self(), "chg_cleanup_thr");
+
 	if (op == NULL) {
 		waiting = 1;
 		type = CLEANUP_ALL;
--- old/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c	Mon Oct 15 13:24:05 2018
+++ new/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c	Mon Oct 15 13:24:05 2018
@@ -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 @@
  * 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,
--- old/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c	Mon Oct 15 13:24:09 2018
+++ new/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c	Mon Oct 15 13:24:09 2018
@@ -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 @@
 	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 @@
 	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 @@
 	int up;
 	rm_svr_t rms;
 
+	(void) pthread_setname_np(pthread_self(), "remove_server");
+
 	up = contact_server(addr);
 
 	rms.addr = addr;
--- old/usr/src/cmd/mdb/common/mdb/mdb_proc.c	Mon Oct 15 13:24:15 2018
+++ new/usr/src/cmd/mdb/common/mdb/mdb_proc.c	Mon Oct 15 13:24:15 2018
@@ -1303,6 +1303,23 @@
 	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 @@
 	int showargs = 0;
 	int count;
 	uintptr_t pc, sp;
+	char name[128];
 
 	if (!(flags & DCMD_ADDRSPEC))
 		return (DCMD_USAGE);
@@ -1334,7 +1352,10 @@
 #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);
 
--- old/usr/src/cmd/mdb/common/modules/genunix/findstack.c	Mon Oct 15 13:24:18 2018
+++ new/usr/src/cmd/mdb/common/modules/genunix/findstack.c	Mon Oct 15 13:24:18 2018
@@ -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 @@
     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 @@
 	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 @@
 	return (DCMD_OK);
 }
 
+#endif /* _KERNEL */
+
 static void
 uppercase(char *p)
 {
@@ -197,7 +209,7 @@
 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 @@
  * 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 @@
 	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 @@
 }
 
 /*ARGSUSED*/
-int
+static int
 stacks_thread_cb(uintptr_t addr, const void *ignored, void *cbarg)
 {
 	stacks_info_t *sip = cbarg;
@@ -421,7 +433,7 @@
 	return (WALK_NEXT);
 }
 
-int
+static int
 stacks_run_tlist(mdb_pipe_t *tlist, stacks_info_t *si)
 {
 	size_t idx;
@@ -445,7 +457,7 @@
 	return (-1);
 }
 
-int
+static int
 stacks_run(int verbose, mdb_pipe_t *tlist)
 {
 	stacks_info_t si;
--- old/usr/src/cmd/mdb/common/modules/genunix/genunix.c	Mon Oct 15 13:24:21 2018
+++ new/usr/src/cmd/mdb/common/modules/genunix/genunix.c	Mon Oct 15 13:24:21 2018
@@ -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 2017 Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
  * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
@@ -164,14 +164,19 @@
 	if (prt_flags & PS_PRTTHREADS)
 		mdb_printf("\tT  %?a <%b>\n", addr, t->t_state, t_state_bits);
 
-	if (prt_flags & PS_PRTLWPS)
-		mdb_printf("\tL  %?a ID: %u\n", t->t_lwp, t->t_tid);
+	if (prt_flags & PS_PRTLWPS) {
+		char desc[128] = "";
 
+		(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;
@@ -261,8 +266,8 @@
 
 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;
--- old/usr/src/cmd/mdb/common/modules/genunix/thread.c	Mon Oct 15 13:24:25 2018
+++ new/usr/src/cmd/mdb/common/modules/genunix/thread.c	Mon Oct 15 13:24:25 2018
@@ -24,11 +24,13 @@
  */
 /*
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc.
  */
 
 
 #include <mdb/mdb_modapi.h>
 #include <mdb/mdb_ks.h>
+#include <mdb/mdb_ctf.h>
 #include <sys/types.h>
 #include <sys/thread.h>
 #include <sys/lwp.h>
@@ -38,6 +40,7 @@
 #include <sys/disp.h>
 #include <sys/taskq_impl.h>
 #include <sys/stack.h>
+#include "thread.h"
 
 #ifndef	STACK_BIAS
 #define	STACK_BIAS	0
@@ -561,6 +564,89 @@
 }
 
 /*
+ * 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
@@ -571,8 +657,6 @@
 	uint_t verbose = FALSE;
 	uint_t notaskq = FALSE;
 	kthread_t t;
-	taskq_t tq;
-	proc_t p;
 	char cmd[80];
 	mdb_arg_t cmdarg;
 
@@ -618,51 +702,33 @@
 	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 {
-			mdb_printf(" %s/%u\n", p.p_user.u_comm, t.t_tid);
-		}
-	}
+	mdb_dec_indent(2);
 
+	mdb_printf("\n");
+
 	return (DCMD_OK);
 }
 
@@ -716,7 +782,6 @@
 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 */
@@ -730,6 +795,7 @@
 	int i = 0;
 	unsigned int ukmem_stackinfo;
 	uintptr_t allthreads;
+	char tdesc[128] = "";
 
 	/* handle options */
 	if (mdb_getopts(argc, argv,
@@ -775,7 +841,7 @@
 
 		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);
@@ -798,18 +864,15 @@
 			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);
@@ -824,7 +887,7 @@
 		}
 		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");
 	}
 
@@ -838,12 +901,6 @@
 		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).
@@ -878,14 +935,10 @@
 	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);
 	}
 
@@ -958,12 +1011,9 @@
 	} 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);
 }
@@ -978,7 +1028,7 @@
 	    "(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(
@@ -1002,6 +1052,6 @@
 	    "-h shows history, dead kthreads that used their "
 	    "kernel stack the most\n");
 	mdb_printf(
-	    "\nSee Solaris Modular Debugger Guide for detailed usage.\n");
+	    "\nSee illumos Modular Debugger Guide for detailed usage.\n");
 	mdb_flush();
 }
--- old/usr/src/cmd/mdb/common/modules/genunix/thread.h	Mon Oct 15 13:24:27 2018
+++ new/usr/src/cmd/mdb/common/modules/genunix/thread.h	Mon Oct 15 13:24:27 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2018, Joyent, Inc.
  */
 
 #ifndef	_THREAD_H
@@ -58,6 +60,8 @@
 int thread_text_to_state(const char *, uint_t *);
 void thread_walk_states(void (*)(uint_t, const char *, void *), void *);
 
+int thread_getdesc(uintptr_t, boolean_t, char *, size_t);
+
 #ifdef	__cplusplus
 }
 #endif
--- old/usr/src/cmd/nscd/cache.c	Mon Oct 15 13:24:28 2018
+++ new/usr/src/cmd/nscd/cache.c	Mon Oct 15 13:24:29 2018
@@ -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.
  */
 
 /*
@@ -1817,8 +1818,10 @@
 static void
 revalidate(nsc_ctx_t *ctx)
 {
+	(void) thr_setname(thr_self(), "revalidate");
+
 	for (;;) {
-		int 		i, slp, interval, count;
+		int i, slp, interval, count;
 
 		(void) rw_rdlock(&ctx->cfg_rwlp);
 		slp = ctx->cfg.pos_ttl;
@@ -1961,6 +1964,8 @@
 do_update(nsc_lookup_args_t *in) {
 	nss_pheader_t	*phdr = (nss_pheader_t *)in->buffer;
 
+	(void) thr_setname(thr_self(), "do_update");
+
 	/* update the length of the data buffer */
 	phdr->data_len = phdr->pbufsiz - phdr->data_off;
 
@@ -2017,7 +2022,7 @@
 static void
 ctx_invalidate(nsc_ctx_t *ctx)
 {
-	int 		i;
+	int		i;
 	nsc_entry_t	*entry;
 	char		*me = "ctx_invalidate";
 
@@ -2190,6 +2195,8 @@
 	ulong_t		nsc_entries;
 	char		*me = "reaper";
 
+	(void) thr_setname(thr_self(), me);
+
 	for (;;) {
 		(void) mutex_lock(&ctx->stats_mutex);
 		nsc_entries = ctx->stats.entries;
--- old/usr/src/cmd/nscd/nscd_frontend.c	Mon Oct 15 13:24:33 2018
+++ new/usr/src/cmd/nscd/nscd_frontend.c	Mon Oct 15 13:24:33 2018
@@ -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 @@
 {
 	static void *value = 0;
 
+	(void) thr_setname(thr_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 @@
  * 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 @@
  * 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 @@
 	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 @@
 	struct ifa_msghdr *ifam = &mbuf.ifam;
 	char	*me = "rts_mon";
 
+	(void) thr_setname(thr_self(), me);
+
 	rt_sock = socket(PF_ROUTE, SOCK_RAW, 0);
 	if (rt_sock < 0) {
 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
--- old/usr/src/cmd/nscd/nscd_getentctx.c	Mon Oct 15 13:24:35 2018
+++ new/usr/src/cmd/nscd/nscd_getentctx.c	Mon Oct 15 13:24:35 2018
@@ -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>
@@ -658,6 +660,8 @@
 	nss_getent_t		nssctx = { 0 };
 	char			*me = "reclaim_getent_ctx";
 
+	(void) thr_setname(thr_self(), me);
+
 	/*CONSTCOND*/
 	while (1) {
 
@@ -744,7 +748,8 @@
 }
 
 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 +768,7 @@
 	 * 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));
--- old/usr/src/cmd/nscd/nscd_selfcred.c	Mon Oct 15 13:24:37 2018
+++ new/usr/src/cmd/nscd/nscd_selfcred.c	Mon Oct 15 13:24:37 2018
@@ -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>
@@ -425,6 +426,8 @@
 	char		*fmri;
 	char		*me = "forker_monitor";
 
+	(void) thr_setname(thr_self(), me);
+
 	/* wait until forker exits */
 	fpid = forker_pid;
 	(void) selfcred_pulse(forking_door);
@@ -1416,7 +1419,7 @@
 	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 +1469,8 @@
 	int		found;
 	char		*me = "check_user_process";
 
+	(void) thr_setname(thr_self(), me);
+
 	for (;;) {
 		(void) sleep(60);
 
--- old/usr/src/cmd/nscd/nscd_smfmonitor.c	Mon Oct 15 13:24:38 2018
+++ new/usr/src/cmd/nscd/nscd_smfmonitor.c	Mon Oct 15 13:24:38 2018
@@ -21,6 +21,8 @@
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
  */
 
 #include <stdlib.h>
@@ -107,6 +109,8 @@
 	int	i;
 	int	st;
 
+	(void) thr_setname(thr_self(), "set_smf_state");
+
 	/*
 	 * the forker nscd needs not monitor the state
 	 * of the client services
--- old/usr/src/cmd/prstat/Makefile.com	Mon Oct 15 13:24:40 2018
+++ new/usr/src/cmd/prstat/Makefile.com	Mon Oct 15 13:24:40 2018
@@ -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 @@
 
 include ../../Makefile.cmd
 
+CSTD = $(CSTD_GNU99)
 CFLAGS += $(CCVERBOSE)
 CERRWARN += -_gcc=-Wno-parentheses
 LDLIBS += -lcurses -lproject
--- old/usr/src/cmd/prstat/prstat.c	Mon Oct 15 13:24:41 2018
+++ new/usr/src/cmd/prstat/prstat.c	Mon Oct 15 13:24:41 2018
@@ -26,6 +26,7 @@
  * Use is subject to license terms.
  *
  * Portions Copyright 2009 Chad Mynhier
+ * Copyright 2018 Joyent, Inc.  All rights reserved.
  */
 
 #include <sys/types.h>
@@ -86,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 \
@@ -110,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 \
@@ -149,8 +150,8 @@
 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 */
@@ -172,7 +173,7 @@
 
 /* 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 */
@@ -361,11 +362,12 @@
 	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;
@@ -385,54 +387,59 @@
 		(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');
@@ -499,15 +506,14 @@
 			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);
@@ -536,21 +542,17 @@
 					    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');
@@ -570,12 +572,11 @@
 				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');
 			}
@@ -877,6 +878,27 @@
 }
 
 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;
@@ -891,6 +913,7 @@
 	(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
@@ -1113,7 +1136,7 @@
 }
 
 static void
-curses_on()
+curses_on(void)
 {
 	if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) {
 		(void) initscr();
@@ -1124,7 +1147,7 @@
 }
 
 static void
-curses_off()
+curses_off(void)
 {
 	if ((is_curses_on == TRUE) && (opts.o_outpmode & OPT_TERMCAP)) {
 		(void) putp(t_rmcup);
@@ -1135,26 +1158,40 @@
 }
 
 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;
 		}
 	}
-	return (-1);
+	if ((envp = getenv("COLUMNS")) != NULL) {
+		if ((n = Atoi(envp)) > 0) {
+			*colsp = n;
+		}
+	}
+
+	return ((*linesp > 0 && *colsp > 0) ? 0 : -1);
 }
 
 static void
-setmovecur()
+setmovecur(void)
 {
 	int i, n;
 	if ((opts.o_outpmode & OPT_FULLSCREEN) &&
@@ -1184,17 +1221,19 @@
 }
 
 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);
--- old/usr/src/cmd/prstat/prstat.h	Mon Oct 15 13:24:44 2018
+++ new/usr/src/cmd/prstat/prstat.h	Mon Oct 15 13:24:44 2018
@@ -26,6 +26,7 @@
  * Use is subject to license terms.
  *
  * Portions Copyright 2009 Chad Mynhier
+ * Copyright 2018 Joyent, Inc.  All rights reserved.
  */
 
 #ifndef	_PRSTAT_H
@@ -113,6 +114,7 @@
 	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;
@@ -167,8 +169,11 @@
 	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
--- old/usr/src/cmd/prstat/prutil.c	Mon Oct 15 13:24:45 2018
+++ new/usr/src/cmd/prstat/prutil.c	Mon Oct 15 13:24:45 2018
@@ -25,6 +25,7 @@
  * Use is subject to license terms.
  *
  * Portions Copyright 2009 Chad Mynhier
+ * Copyright 2018 Joyent, Inc.  All rights reserved.
  */
 
 #include <sys/types.h>
@@ -324,8 +325,8 @@
 /*
  * 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;
@@ -332,6 +333,8 @@
 	int length;
 	char *cp;
 
+	(void) strlcpy(buf, pname, bufsize);
+
 	buf[bytesleft - 1] = '\0';
 
 	for (cp = buf; *cp != '\0'; cp += length) {
@@ -350,4 +353,72 @@
 		}
 		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';
 }
--- old/usr/src/cmd/prstat/prutil.h	Mon Oct 15 13:24:46 2018
+++ new/usr/src/cmd/prstat/prutil.h	Mon Oct 15 13:24:46 2018
@@ -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 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
 }
--- old/usr/src/cmd/ps/ps.c	Mon Oct 15 13:24:48 2018
+++ new/usr/src/cmd/ps/ps.c	Mon Oct 15 13:24:48 2018
@@ -27,11 +27,11 @@
  */
 
 /*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * 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 @@
 	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 @@
 	{ "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 @@
 	{ "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]))
@@ -803,6 +805,7 @@
 					(void) printf("%-*s",
 					    f->width, f->header);
 					break;
+				case F_LWPNAME:
 				case F_FNAME:
 				case F_COMM:
 				case F_ARGS:
@@ -1178,7 +1181,8 @@
 	}
 	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;
 		}
@@ -1754,6 +1758,27 @@
 	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, "%s/%d/lwp/%d/lwpname", procdir,
+		    (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;
@@ -2077,7 +2102,7 @@
 
 static void
 pr_fields(psinfo_t *psinfo, const char *ttyp,
-	void (*print_fld)(psinfo_t *, struct field *, const char *))
+    void (*print_fld)(psinfo_t *, struct field *, const char *))
 {
 	struct field *f;
 
@@ -2367,7 +2392,7 @@
 	}
 	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 */
 
@@ -2447,9 +2472,9 @@
 /*
  * 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)
@@ -2484,9 +2509,9 @@
 /*
  * 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)
--- old/usr/src/cmd/ptools/pstack/pstack.c	Mon Oct 15 13:24:52 2018
+++ new/usr/src/cmd/ptools/pstack/pstack.c	Mon Oct 15 13:24:52 2018
@@ -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	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 @@
 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 @@
 	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,8 +416,9 @@
 
 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))
@@ -418,7 +425,10 @@
 		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 @@
 			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 @@
 	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 && 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);
+	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));
+	}
 
-	(void) printf("--------------------\n");
+	if (name != NULL && strlen(name) > 0) {
+		(void) strlcat(buf, " [", sizeof (buf));
+		(void) strlcat(buf, name, sizeof (buf));
+		(void) strlcat(buf, "]", sizeof (buf));
+	}
+
+	amt = (HEAD_WIDTH - strlen(buf) - 2);
+	if (amt < 4)
+		amt = 4;
+
+	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*/
--- old/usr/src/cmd/sgs/elfdump/common/corenote.c	Mon Oct 15 13:24:55 2018
+++ new/usr/src/cmd/sgs/elfdump/common/corenote.c	Mon Oct 15 13:24:55 2018
@@ -1256,6 +1256,20 @@
 }
 
 
+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 @@
 		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);
--- old/usr/src/cmd/sgs/elfdump/common/elfdump.msg	Mon Oct 15 13:24:58 2018
+++ new/usr/src/cmd/sgs/elfdump/common/elfdump.msg	Mon Oct 15 13:24:59 2018
@@ -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:"
--- old/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c	Mon Oct 15 13:25:01 2018
+++ new/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c	Mon Oct 15 13:25:01 2018
@@ -11,6 +11,7 @@
 
 /*
  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 /*
@@ -58,3 +59,4 @@
 struct utsname uts;
 prfdinfo_t ptfd;
 prsecflags_t psf;
+prlwpname_t psn;
--- old/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c	Mon Oct 15 13:25:02 2018
+++ new/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c	Mon Oct 15 13:25:02 2018
@@ -24,11 +24,12 @@
  * 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 +600,15 @@
 	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 +650,7 @@
 	gen_utsname();
 	gen_prfdinfo();
 	gen_prsecflags();
+	gen_prlwpname();
 
 	/*
 	 * Generate the full arch_layout description
@@ -668,6 +679,7 @@
 	(void) printf(fmt, "utsname");
 	(void) printf(fmt, "prfdinfo");
 	(void) printf(fmt, "prsecflags");
+	(void) printf(fmt, "prlwpname");
 	(void) printf("};\n");
 
 	/*
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout.h	Mon Oct 15 13:25:03 2018
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout.h	Mon Oct 15 13:25:03 2018
@@ -26,6 +26,7 @@
 
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 #ifndef	_STRUCT_LAYOUT_H
@@ -98,7 +99,7 @@
  */
 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 +536,12 @@
 	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 +568,7 @@
 	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;
 
 
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c	Mon Oct 15 13:25:04 2018
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c	Mon Oct 15 13:25:04 2018
@@ -25,6 +25,7 @@
  */
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 #include <struct_layout.h>
@@ -387,8 +388,15 @@
 };
 
 
+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 = {
 	&auxv_layout,
 	&fltset_layout,
@@ -411,6 +419,7 @@
 	&utsname_layout,
 	&prfdinfo_layout,
 	&prsecflags_layout,
+	&prlwpname_layout,
 };
 
 
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c	Mon Oct 15 13:25:06 2018
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c	Mon Oct 15 13:25:06 2018
@@ -25,6 +25,7 @@
  */
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 #include <struct_layout.h>
@@ -387,8 +388,15 @@
 };
 
 
+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 = {
 	&auxv_layout,
 	&fltset_layout,
@@ -411,6 +419,7 @@
 	&utsname_layout,
 	&prfdinfo_layout,
 	&prsecflags_layout,
+	&prlwpname_layout,
 };
 
 
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c	Mon Oct 15 13:25:09 2018
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c	Mon Oct 15 13:25:09 2018
@@ -25,7 +25,9 @@
  */
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
+
 #include <struct_layout.h>
 
 
@@ -386,8 +388,15 @@
 };
 
 
+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 = {
 	&auxv_layout,
 	&fltset_layout,
@@ -410,6 +419,7 @@
 	&utsname_layout,
 	&prfdinfo_layout,
 	&prsecflags_layout,
+	&prlwpname_layout,
 };
 
 
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c	Mon Oct 15 13:25:11 2018
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c	Mon Oct 15 13:25:11 2018
@@ -25,6 +25,7 @@
  */
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 #include <struct_layout.h>
@@ -387,8 +388,15 @@
 };
 
 
+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 = {
 	&auxv_layout,
 	&fltset_layout,
@@ -411,6 +419,7 @@
 	&utsname_layout,
 	&prfdinfo_layout,
 	&prsecflags_layout,
+	&prlwpname_layout,
 };
 
 
--- old/usr/src/cmd/sgs/libconv/Makefile.com	Mon Oct 15 13:25:11 2018
+++ new/usr/src/cmd/sgs/libconv/Makefile.com	Mon Oct 15 13:25:11 2018
@@ -21,7 +21,7 @@
 
 #
 # Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2018, Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
 #
 
 LIBRARY =	libconv.a
@@ -124,8 +124,8 @@
 
 SGSMSGTARG=	$(BLTOBJS:%_msg.o=../common/%.msg)
 
-LINTFLAGS +=	-u
-LINTFLAGS64 +=	-u
+LINTFLAGS +=	-u -erroff=E_NAME_DECL_NOT_USED_DEF2
+LINTFLAGS64 +=	-u -erroff=E_NAME_DECL_NOT_USED_DEF2
 
 CLEANFILES +=	$(BLTDATA) $(LINTOUTS) bld_vernote vernote.s
 CLOBBERFILES +=	$(LINTLIBS)
--- old/usr/src/cmd/sgs/libconv/common/corenote.c	Mon Oct 15 13:25:11 2018
+++ new/usr/src/cmd/sgs/libconv/common/corenote.c	Mon Oct 15 13:25:11 2018
@@ -58,9 +58,10 @@
 		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 = {
--- old/usr/src/cmd/sgs/libconv/common/corenote.msg	Mon Oct 15 13:25:11 2018
+++ new/usr/src/cmd/sgs/libconv/common/corenote.msg	Mon Oct 15 13:25:11 2018
@@ -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"
--- old/usr/src/cmd/svc/startd/graph.c	Mon Oct 15 13:25:12 2018
+++ new/usr/src/cmd/svc/startd/graph.c	Mon Oct 15 13:25:12 2018
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  * Copyright (c) 2015, Syneto S.R.L. All rights reserved.
  * Copyright 2016 Toomas Soome <tsoome@me.com>
  * Copyright 2016 RackTop Systems.
@@ -576,7 +577,7 @@
 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 *);
@@ -3849,6 +3850,8 @@
 static void *
 sulogin_thread(void *unused)
 {
+	(void) pthread_setname_np(pthread_self(), "sulogin");
+
 	MUTEX_LOCK(&dgraph_lock);
 
 	assert(sulogin_thread_running);
@@ -3876,6 +3879,8 @@
 	char *buf;
 	int r;
 
+	(void) pthread_setname_np(pthread_self(), "single_user");
+
 	MUTEX_LOCK(&single_user_thread_lock);
 	single_user_thread_count++;
 
@@ -5779,6 +5784,8 @@
 	scf_handle_t *h;
 	int err;
 
+	(void) pthread_setname_np(pthread_self(), "graph_event");
+
 	h = libscf_handle_create_bound_loop();
 
 	/*CONSTCOND*/
@@ -6138,6 +6145,8 @@
 	scf_handle_t *h;
 	int err;
 
+	(void) pthread_setname_np(pthread_self(), "graph");
+
 	h = libscf_handle_create_bound_loop();
 
 	if (st->st_initial)
@@ -6794,6 +6803,8 @@
 	char *pg_name = startd_alloc(max_scf_value_size);
 	int r;
 
+	(void) pthread_setname_np(pthread_self(), "repository_event");
+
 	h = libscf_handle_create_bound_loop();
 
 	pg = safe_scf_pg_create(h);
--- old/usr/src/cmd/svc/startd/method.c	Mon Oct 15 13:25:12 2018
+++ new/usr/src/cmd/svc/startd/method.c	Mon Oct 15 13:25:12 2018
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Joyent Inc.
+ * Copyright 2018 Joyent, Inc.
  */
 
 /*
@@ -1115,6 +1115,8 @@
 	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. */
--- old/usr/src/cmd/svc/startd/restarter.c	Mon Oct 15 13:25:12 2018
+++ new/usr/src/cmd/svc/startd/restarter.c	Mon Oct 15 13:25:12 2018
@@ -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 @@
 	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 @@
 	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 @@
 }
 
 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 @@
 {
 	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 @@
 	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 @@
 	 * is not empty.
 	 */
 
+	(void) pthread_setname_np(pthread_self(), "restarter_timeouts_event");
+
 	/*CONSTCOND*/
 	while (1) {
 		/*
--- old/usr/src/cmd/svc/startd/wait.c	Mon Oct 15 13:25:13 2018
+++ new/usr/src/cmd/svc/startd/wait.c	Mon Oct 15 13:25:13 2018
@@ -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 @@
 void *
 wait_thread(void *args)
 {
+	(void) pthread_setname_np(pthread_self(), "wait");
+
 	for (;;) {
 		port_event_t pe;
 		int fd;
--- old/usr/src/head/pthread.h	Mon Oct 15 13:25:13 2018
+++ new/usr/src/head/pthread.h	Mon Oct 15 13:25:13 2018
@@ -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 @@
 /* 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 @@
 		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_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
--- old/usr/src/head/thread.h	Mon Oct 15 13:25:13 2018
+++ new/usr/src/head/thread.h	Mon Oct 15 13:25:13 2018
@@ -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_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 */
 
--- old/usr/src/lib/libc/inc/thr_uberdata.h	Mon Oct 15 13:25:13 2018
+++ new/usr/src/lib/libc/inc/thr_uberdata.h	Mon Oct 15 13:25:13 2018
@@ -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"
@@ -1233,6 +1234,7 @@
 	int	policy;
 	int	inherit;
 	size_t	guardsize;
+	char	name[THREAD_NAME_MAX];
 } thrattr_t;
 
 typedef	struct	_rwlattr {
@@ -1492,7 +1494,7 @@
 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);
 
--- old/usr/src/lib/libc/port/mapfile-vers	Mon Oct 15 13:25:13 2018
+++ new/usr/src/lib/libc/port/mapfile-vers	Mon Oct 15 13:25:13 2018
@@ -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>
@@ -77,6 +77,16 @@
 $add amd64
 $endif
 
+SYMBOL_VERSION ILLUMOS_0.28 {
+    protected:
+	pthread_attr_getname_np;
+	pthread_attr_setname_np;
+	pthread_getname_np;
+	pthread_setname_np;
+	thr_getname;
+	thr_setname;
+} ILLUMOS_0.27;
+
 SYMBOL_VERSION ILLUMOS_0.27 {	# memset_s(3C) and set_constraint_handler_s(3C)
     protected:
 	abort_handler_s;
--- old/usr/src/lib/libc/port/threads/pthr_attr.c	Mon Oct 15 13:25:14 2018
+++ new/usr/src/lib/libc/port/threads/pthr_attr.c	Mon Oct 15 13:25:14 2018
@@ -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 @@
 		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 @@
 {
 	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 @@
 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 @@
 	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 @@
 	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:
--- old/usr/src/lib/libc/port/threads/pthread.c	Mon Oct 15 13:25:14 2018
+++ new/usr/src/lib/libc/port/threads/pthread.c	Mon Oct 15 13:25:14 2018
@@ -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 @@
 
 	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
--- old/usr/src/lib/libc/port/threads/thr.c	Mon Oct 15 13:25:14 2018
+++ new/usr/src/lib/libc/port/threads/thr.c	Mon Oct 15 13:25:14 2018
@@ -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"
@@ -560,7 +560,7 @@
 
 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;
@@ -715,6 +715,9 @@
 
 	exit_critical(self);
 
+	if (name != NULL)
+		(void) pthread_setname_np(tid, name);
+
 	if (!(flags & THR_SUSPENDED))
 		(void) _thrp_continue(tid, TSTP_REGULAR);
 
@@ -725,7 +728,8 @@
 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));
 }
 
 /*
@@ -2398,6 +2402,87 @@
 	return (curthread->ul_uberdata->nthreads);
 }
 
+/* "/proc/self/lwp/%u/lwpname" w/o stdio */
+static void
+lwpname_path(pthread_t tid, char *buf, size_t bufsize)
+{
+	(void) strlcpy(buf, "/proc/self/lwp/", bufsize);
+	ultos((uint64_t)tid, 10, buf + strlen(buf));
+	(void) strlcat(buf, "/lwpname", bufsize);
+}
+
+#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);
+
+	lwpname_path(tid, path, 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);
+
+	lwpname_path(tid, path, 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
--- old/usr/src/lib/libdtrace/common/dt_open.c	Mon Oct 15 13:25:14 2018
+++ new/usr/src/lib/libdtrace/common/dt_open.c	Mon Oct 15 13:25:14 2018
@@ -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.
  */
 
@@ -116,8 +116,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 */
@@ -144,6 +145,7 @@
 	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
 };
 
@@ -401,6 +403,8 @@
 	&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,
--- old/usr/src/lib/libfakekernel/common/sys/thread.h	Mon Oct 15 13:25:15 2018
+++ new/usr/src/lib/libfakekernel/common/sys/thread.h	Mon Oct 15 13:25:15 2018
@@ -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 @@
 
 #define	_KTHREAD_INVALID	((void *)(uintptr_t)-1)
 
+#define	THREAD_NAME_MAX	(32)
 
 struct proc;
 extern struct proc	*_curproc(void);
--- old/usr/src/lib/libproc/common/Pcontrol.h	Mon Oct 15 13:25:15 2018
+++ new/usr/src/lib/libproc/common/Pcontrol.h	Mon Oct 15 13:25:15 2018
@@ -24,8 +24,8 @@
  */
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
- * Copyright (c) 2014, 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
@@ -136,6 +137,7 @@
 	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 */
@@ -273,7 +275,7 @@
 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);
--- old/usr/src/lib/libproc/common/Pcore.c	Mon Oct 15 13:25:15 2018
+++ new/usr/src/lib/libproc/common/Pcore.c	Mon Oct 15 13:25:15 2018
@@ -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 @@
 }
 
 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 @@
 	note_fdinfo,		/* 22	NT_FDINFO		*/
 	note_spymaster,		/* 23	NT_SPYMASTER		*/
 	note_secflags,		/* 24	NT_SECFLAGS		*/
+	note_lwpname,		/* 25	NT_LWPNAME		*/
 };
 
 static void
--- old/usr/src/lib/libproc/common/Pgcore.c	Mon Oct 15 13:25:15 2018
+++ new/usr/src/lib/libproc/common/Pgcore.c	Mon Oct 15 13:25:15 2018
@@ -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 @@
 {
 	pgcore_t *pgc = data;
 	struct ps_prochandle *P = pgc->P;
+	prlwpname_t name = { 0, "" };
 	psinfo_t ps;
 
 	/*
@@ -577,6 +578,14 @@
 #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);
 
--- old/usr/src/lib/libproc/common/Plwpregs.c	Mon Oct 15 13:25:16 2018
+++ new/usr/src/lib/libproc/common/Plwpregs.c	Mon Oct 15 13:25:16 2018
@@ -24,7 +24,7 @@
  */
 
 /*
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
@@ -352,6 +352,38 @@
 	return (-1);
 }
 
+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)
 {
--- old/usr/src/lib/libproc/common/libproc.h	Mon Oct 15 13:25:16 2018
+++ new/usr/src/lib/libproc/common/libproc.h	Mon Oct 15 13:25:16 2018
@@ -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	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 *);
 
--- old/usr/src/lib/libproc/common/mapfile-vers	Mon Oct 15 13:25:17 2018
+++ new/usr/src/lib/libproc/common/mapfile-vers	Mon Oct 15 13:25:17 2018
@@ -21,7 +21,7 @@
 #
 # 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 2018 Joyent, Inc.
 # Copyright (c) 2013 by Delphix. All rights reserved.
 #
 
@@ -136,6 +136,7 @@
 	Plookup_by_name;
 	Plwp_alt_stack;
 	Plwp_getfpregs;
+	Plwp_getname;
 	Plwp_getpsinfo;
 	Plwp_getregs;
 	Plwp_getspymaster;
--- old/usr/src/man/man1/ps.1	Mon Oct 15 13:25:20 2018
+++ new/usr/src/man/man1/ps.1	Mon Oct 15 13:25:21 2018
@@ -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
@@ -1049,6 +1049,16 @@
 .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
@@ -1173,8 +1183,8 @@
 
 .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
@@ -1196,7 +1206,7 @@
 nice	NI	tty	TT
 pcpu	%CPU	user	USER
 pgid	PGID	vsz	VSZ
-pid	PID		
+pid	PID
 .TE
 
 .sp
@@ -1221,12 +1231,13 @@
 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
--- old/usr/src/man/man1m/prstat.1m	Mon Oct 15 13:25:27 2018
+++ new/usr/src/man/man1m/prstat.1m	Mon Oct 15 13:25:27 2018
@@ -1,10 +1,11 @@
 '\" te
 .\" Copyright (c) 2013 Gary Mills
 .\" Copyright (c) 2006, 2009 Sun Microsystems, 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 "Nov 14, 2014"
+.TH PRSTAT 1M "September 1, 2018"
 .SH NAME
 prstat \- report active process statistics
 .SH SYNOPSIS
@@ -580,11 +581,12 @@
 .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
--- old/usr/src/man/man3c/Makefile	Mon Oct 15 13:25:33 2018
+++ new/usr/src/man/man3c/Makefile	Mon Oct 15 13:25:33 2018
@@ -307,6 +307,7 @@
 		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			\
@@ -332,6 +333,7 @@
 		pthread_equal.3c				\
 		pthread_exit.3c					\
 		pthread_getconcurrency.3c			\
+		pthread_getname_np.3c				\
 		pthread_getschedparam.3c			\
 		pthread_getspecific.3c				\
 		pthread_join.3c					\
@@ -475,6 +477,7 @@
 		termios.3c					\
 		thr_create.3c					\
 		thr_exit.3c					\
+		thr_getname.3c					\
 		thr_getconcurrency.3c				\
 		thr_getprio.3c					\
 		thr_join.3c					\
@@ -1092,6 +1095,7 @@
 		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		\
@@ -1128,6 +1132,7 @@
 		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			\
@@ -1291,6 +1296,7 @@
 		thr_continue.3c				\
 		thr_getspecific.3c			\
 		thr_keycreate_once.3c			\
+		thr_setname.3c				\
 		thr_setconcurrency.3c			\
 		thr_setprio.3c				\
 		thr_setspecific.3c			\
@@ -2140,6 +2146,8 @@
 
 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
@@ -2174,6 +2182,8 @@
 
 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
@@ -2408,6 +2418,8 @@
 
 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
--- /dev/null	Mon Oct 15 13:25:39 2018
+++ new/usr/src/man/man3c/pthread_attr_getname_np.3c	Mon Oct 15 13:25:39 2018
@@ -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
--- /dev/null	Mon Oct 15 13:25:41 2018
+++ new/usr/src/man/man3c/pthread_getname_np.3c	Mon Oct 15 13:25:41 2018
@@ -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
--- /dev/null	Mon Oct 15 13:25:43 2018
+++ new/usr/src/man/man3c/thr_getname.3c	Mon Oct 15 13:25:43 2018
@@ -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
--- old/usr/src/man/man3lib/libproc.3lib	Mon Oct 15 13:25:44 2018
+++ new/usr/src/man/man3lib/libproc.3lib	Mon Oct 15 13:25:44 2018
@@ -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 @@
 .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
--- old/usr/src/man/man3proc/Makefile	Mon Oct 15 13:25:51 2018
+++ new/usr/src/man/man3proc/Makefile	Mon Oct 15 13:25:51 2018
@@ -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 @@
 		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 @@
 		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 @@
 		Pxlookup_by_name.3proc		\
 		Pxsymbol_iter.3proc		\
 		Pzonepath.3proc			\
-		Pzoneroot.3proc			
+		Pzoneroot.3proc
 
 
 ps_lgetfpregs.3proc		:= LINKSRC = ps_lgetregs.3proc
--- old/usr/src/man/man3proc/Paddr_to_ctf.3proc	Mon Oct 15 13:25:54 2018
+++ new/usr/src/man/man3proc/Paddr_to_ctf.3proc	Mon Oct 15 13:25:54 2018
@@ -19,8 +19,9 @@
 .Nm Plmid_to_ctf ,
 .Nm Pname_to_ctf
 .Nd lookup CTF data
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "ctf_file_t *"
 .Fo Paddr_to_ctf
--- old/usr/src/man/man3proc/Paddr_to_loadobj.3proc	Mon Oct 15 13:25:57 2018
+++ new/usr/src/man/man3proc/Paddr_to_loadobj.3proc	Mon Oct 15 13:25:57 2018
@@ -19,8 +19,9 @@
 .Nm Plmid_to_loadobj ,
 .Nm Pname_to_loadobj
 .Nd lookup loaded object information
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "const rd_loadobj_t *"
 .Fo Paddr_to_loadobj
--- old/usr/src/man/man3proc/Paddr_to_map.3proc	Mon Oct 15 13:26:01 2018
+++ new/usr/src/man/man3proc/Paddr_to_map.3proc	Mon Oct 15 13:26:01 2018
@@ -20,8 +20,9 @@
 .Nm Plmid_to_map ,
 .Nm Pname_to_map
 .Nd lookup memory map information
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "const prmap_t *"
 .Fo Paddr_to_map
--- old/usr/src/man/man3proc/Pasfd.3proc	Mon Oct 15 13:26:07 2018
+++ new/usr/src/man/man3proc/Pasfd.3proc	Mon Oct 15 13:26:07 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pasfd
 .Nd obtain the process address space file descriptor
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pasfd
--- old/usr/src/man/man3proc/Pclearfault.3proc	Mon Oct 15 13:26:11 2018
+++ new/usr/src/man/man3proc/Pclearfault.3proc	Mon Oct 15 13:26:11 2018
@@ -18,8 +18,9 @@
 .Nm Pclearfault ,
 .Nm Lclearfault
 .Nd clear process and thread faults
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pclearfault
--- old/usr/src/man/man3proc/Pclearsig.3proc	Mon Oct 15 13:26:14 2018
+++ new/usr/src/man/man3proc/Pclearsig.3proc	Mon Oct 15 13:26:15 2018
@@ -18,8 +18,9 @@
 .Nm Pclearsig ,
 .Nm Lclearsig
 .Nd clear process signals
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pclearsig
--- old/usr/src/man/man3proc/Pcontent.3proc	Mon Oct 15 13:26:18 2018
+++ new/usr/src/man/man3proc/Pcontent.3proc	Mon Oct 15 13:26:18 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pconent
 .Nd obtain process content types available
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "core_content_t"
 .Fo Pcontent
--- old/usr/src/man/man3proc/Pcreate.3proc	Mon Oct 15 13:26:22 2018
+++ new/usr/src/man/man3proc/Pcreate.3proc	Mon Oct 15 13:26:22 2018
@@ -19,8 +19,9 @@
 .Nm Pxcreate ,
 .Nm Pcreate_callback
 .Nd create and control a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "struct ps_prochandle *"
 .Fo Pcreate
--- old/usr/src/man/man3proc/Pcreate_agent.3proc	Mon Oct 15 13:26:25 2018
+++ new/usr/src/man/man3proc/Pcreate_agent.3proc	Mon Oct 15 13:26:25 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pcreate_agent
 .Nd create the agent LWP
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pcreate_agent
--- old/usr/src/man/man3proc/Pcreate_error.3proc	Mon Oct 15 13:26:26 2018
+++ new/usr/src/man/man3proc/Pcreate_error.3proc	Mon Oct 15 13:26:26 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pcreate_error
 .Nd get Pcreate, Pxcreate error message string
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "const char *"
 .Fo Pcreate_error
--- old/usr/src/man/man3proc/Pcred.3proc	Mon Oct 15 13:26:28 2018
+++ new/usr/src/man/man3proc/Pcred.3proc	Mon Oct 15 13:26:28 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pcred
 .Nd obtain process credentials
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pcred
--- old/usr/src/man/man3proc/Pctlfd.3proc	Mon Oct 15 13:26:31 2018
+++ new/usr/src/man/man3proc/Pctlfd.3proc	Mon Oct 15 13:26:31 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pctlfd
 .Nd obtain the process control file descriptor
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pctlfd
--- old/usr/src/man/man3proc/Pdelbkpt.3proc	Mon Oct 15 13:26:34 2018
+++ new/usr/src/man/man3proc/Pdelbkpt.3proc	Mon Oct 15 13:26:35 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pdelbkpt
 .Nd clear a breakpoint in a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pdelbkpt
--- old/usr/src/man/man3proc/Pdelwapt.3proc	Mon Oct 15 13:26:38 2018
+++ new/usr/src/man/man3proc/Pdelwapt.3proc	Mon Oct 15 13:26:38 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pdelwapt
 .Nd remove a watchpoint in a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pdelwapt
--- old/usr/src/man/man3proc/Pdestroy_agent.3proc	Mon Oct 15 13:26:41 2018
+++ new/usr/src/man/man3proc/Pdestroy_agent.3proc	Mon Oct 15 13:26:41 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pdestroy_agent
 .Nd destroy the agent LWP
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Pdestroy_agent
--- old/usr/src/man/man3proc/Penv_iter.3proc	Mon Oct 15 13:26:44 2018
+++ new/usr/src/man/man3proc/Penv_iter.3proc	Mon Oct 15 13:26:44 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Penv_iter
 .Nd iterate process environment
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Penv_iter
--- old/usr/src/man/man3proc/Pexecname.3proc	Mon Oct 15 13:26:46 2018
+++ new/usr/src/man/man3proc/Pexecname.3proc	Mon Oct 15 13:26:47 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pexecname
 .Nd obtain full path to process executable
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "char *"
 .Fo Pexecname
--- old/usr/src/man/man3proc/Pfault.3proc	Mon Oct 15 13:26:51 2018
+++ new/usr/src/man/man3proc/Pfault.3proc	Mon Oct 15 13:26:51 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pfault
 .Nd enable and disable the tracing of faults
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "int"
 .Fo Pfault
--- old/usr/src/man/man3proc/Pfdinfo_iter.3proc	Mon Oct 15 13:26:56 2018
+++ new/usr/src/man/man3proc/Pfdinfo_iter.3proc	Mon Oct 15 13:26:56 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pfdinfo_iter
 .Nd iterate open files in a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pfdinfo_iter
--- old/usr/src/man/man3proc/Pgetareg.3proc	Mon Oct 15 13:26:59 2018
+++ new/usr/src/man/man3proc/Pgetareg.3proc	Mon Oct 15 13:26:59 2018
@@ -20,8 +20,9 @@
 .Nm Lgetareg ,
 .Nm Lputareg
 .Nd set and get a register from a stopped process or thread
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pgetareg
--- old/usr/src/man/man3proc/Pgetauxval.3proc	Mon Oct 15 13:27:02 2018
+++ new/usr/src/man/man3proc/Pgetauxval.3proc	Mon Oct 15 13:27:02 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pgetauxval
 .Nd obtain auxiliary vector value
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pgetauxval
--- old/usr/src/man/man3proc/Pgetauxvec.3proc	Mon Oct 15 13:27:04 2018
+++ new/usr/src/man/man3proc/Pgetauxvec.3proc	Mon Oct 15 13:27:04 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pgetauxvec
 .Nd obtain process auxiliary vector
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "const auxv_t *"
 .Fo Pgetauxvec
--- old/usr/src/man/man3proc/Pgetenv.3proc	Mon Oct 15 13:27:07 2018
+++ new/usr/src/man/man3proc/Pgetenv.3proc	Mon Oct 15 13:27:07 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pgetenv
 .Nd get process environment variable
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "char *"
 .Fo Pgetenv
--- old/usr/src/man/man3proc/Pgrab.3proc	Mon Oct 15 13:27:09 2018
+++ new/usr/src/man/man3proc/Pgrab.3proc	Mon Oct 15 13:27:09 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pgrab
 .Nd grab and control a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "struct ps_prochandle *"
 .Fo Pgrab
--- old/usr/src/man/man3proc/Pgrab_core.3proc	Mon Oct 15 13:27:11 2018
+++ new/usr/src/man/man3proc/Pgrab_core.3proc	Mon Oct 15 13:27:11 2018
@@ -18,8 +18,9 @@
 .Nm Pgrab_core ,
 .Nm Pfgrab_core
 .Nd grab a core file
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "struct ps_prochandle *"
 .Fo Pgrab_core
--- old/usr/src/man/man3proc/Pgrab_error.3proc	Mon Oct 15 13:27:12 2018
+++ new/usr/src/man/man3proc/Pgrab_error.3proc	Mon Oct 15 13:27:12 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pgrab_error
 .Nd get Pgrab error message string
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "const char *"
 .Fo Pgrab_error
--- old/usr/src/man/man3proc/Pgrab_file.3proc	Mon Oct 15 13:27:16 2018
+++ new/usr/src/man/man3proc/Pgrab_file.3proc	Mon Oct 15 13:27:16 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pgrab_file
 .Nd grab and inspect an ELF object
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft struct ps_prochandle
 .Fo Pgrab_file
--- old/usr/src/man/man3proc/Pisprocdir.3proc	Mon Oct 15 13:27:21 2018
+++ new/usr/src/man/man3proc/Pisprocdir.3proc	Mon Oct 15 13:27:21 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pisprocdir
 .Nd determine if a directory is the /proc directory
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pisprocdir
--- old/usr/src/man/man3proc/Pissyscall.3proc	Mon Oct 15 13:27:25 2018
+++ new/usr/src/man/man3proc/Pissyscall.3proc	Mon Oct 15 13:27:25 2018
@@ -18,8 +18,9 @@
 .Nm Pissyscall ,
 .Nm Pissyscall_prev
 .Nd determine if instructions are system call instructions
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pissyscall
--- old/usr/src/man/man3proc/Pldt.3proc	Mon Oct 15 13:27:29 2018
+++ new/usr/src/man/man3proc/Pldt.3proc	Mon Oct 15 13:27:29 2018
@@ -18,8 +18,9 @@
 .Nm Pldt ,
 .Nm proc_get_ldt
 .Nd obtain local descriptor table of a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pldt
--- old/usr/src/man/man3proc/Plmid.3proc	Mon Oct 15 13:27:35 2018
+++ new/usr/src/man/man3proc/Plmid.3proc	Mon Oct 15 13:27:35 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Plmid
 .Nd get the link-map identifier of an address
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plmid
--- old/usr/src/man/man3proc/Plookup_by_addr.3proc	Mon Oct 15 13:27:40 2018
+++ new/usr/src/man/man3proc/Plookup_by_addr.3proc	Mon Oct 15 13:27:40 2018
@@ -21,8 +21,9 @@
 .Nm Plookup_by_name ,
 .Nm Pxlookup_by_name
 .Nd lookup symbols in a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plookup_by_addr
--- old/usr/src/man/man3proc/Plwp_getasrs.3proc	Mon Oct 15 13:27:45 2018
+++ new/usr/src/man/man3proc/Plwp_getasrs.3proc	Mon Oct 15 13:27:46 2018
@@ -18,8 +18,9 @@
 .Nm Plwp_getasrs ,
 .Nm Plwp_setasrs
 .Nd get and set SPARCv9 ancillary state registers
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plwp_getasrs
--- /dev/null	Mon Oct 15 13:27:51 2018
+++ new/usr/src/man/man3proc/Plwp_getname.3proc	Mon Oct 15 13:27:51 2018
@@ -0,0 +1,95 @@
+.\"
+.\" 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 LIBRARY
+.Lb libproc
+.Sh SYNOPSIS
+.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
--- old/usr/src/man/man3proc/Plwp_getpsinfo.3proc	Mon Oct 15 13:27:53 2018
+++ new/usr/src/man/man3proc/Plwp_getpsinfo.3proc	Mon Oct 15 13:27:53 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Plwp_getpsinfo
 .Nd get thread specific ps information
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plwp_getpsinfo
--- old/usr/src/man/man3proc/Plwp_getregs.3proc	Mon Oct 15 13:27:57 2018
+++ new/usr/src/man/man3proc/Plwp_getregs.3proc	Mon Oct 15 13:27:57 2018
@@ -20,8 +20,9 @@
 .Nm Plwp_getregs ,
 .Nm Plwp_setregs
 .Nd get and set thread registers
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plwp_getfpregs
--- old/usr/src/man/man3proc/Plwp_getspymaster.3proc	Mon Oct 15 13:28:01 2018
+++ new/usr/src/man/man3proc/Plwp_getspymaster.3proc	Mon Oct 15 13:28:01 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Plwp_getspymaster
 .Nd get agent LWP spy master information
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plwp_getspymaster
--- old/usr/src/man/man3proc/Plwp_getxregs.3proc	Mon Oct 15 13:28:04 2018
+++ new/usr/src/man/man3proc/Plwp_getxregs.3proc	Mon Oct 15 13:28:04 2018
@@ -18,8 +18,9 @@
 .Nm Plwp_getxregs ,
 .Nm Plwp_setxregs
 .Nd get and set extended register state
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plwp_getxregs
--- old/usr/src/man/man3proc/Plwp_iter.3proc	Mon Oct 15 13:28:08 2018
+++ new/usr/src/man/man3proc/Plwp_iter.3proc	Mon Oct 15 13:28:08 2018
@@ -18,8 +18,9 @@
 .Nm Plwp_iter ,
 .Nm Plwp_iter_all
 .Nd iterate over threads
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plwp_iter
--- old/usr/src/man/man3proc/Plwp_stack.3proc	Mon Oct 15 13:28:10 2018
+++ new/usr/src/man/man3proc/Plwp_stack.3proc	Mon Oct 15 13:28:10 2018
@@ -22,8 +22,9 @@
 .Nm Lalt_stack ,
 .Nm Lmain_stack
 .Nd get thread stack information
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Plwp_stack
--- old/usr/src/man/man3proc/Pmapping_iter.3proc	Mon Oct 15 13:28:15 2018
+++ new/usr/src/man/man3proc/Pmapping_iter.3proc	Mon Oct 15 13:28:15 2018
@@ -20,8 +20,9 @@
 .Nm Pobject_iter ,
 .Nm Pobject_iter_resolved
 .Nd iterate over process mappings and objects
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pmapping_iter
--- old/usr/src/man/man3proc/Pobjname.3proc	Mon Oct 15 13:28:20 2018
+++ new/usr/src/man/man3proc/Pobjname.3proc	Mon Oct 15 13:28:20 2018
@@ -18,8 +18,9 @@
 .Nm Pobjname ,
 .Nm Pobjname_resolved
 .Nd turn a virtual address into its mapped object
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "char *"
 .Fo Pobjname
--- old/usr/src/man/man3proc/Pplatform.3proc	Mon Oct 15 13:28:24 2018
+++ new/usr/src/man/man3proc/Pplatform.3proc	Mon Oct 15 13:28:24 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pplatform
 .Nd get platform string
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "char *"
 .Fo Pplatform
--- old/usr/src/man/man3proc/Ppltdest.3proc	Mon Oct 15 13:28:27 2018
+++ new/usr/src/man/man3proc/Ppltdest.3proc	Mon Oct 15 13:28:27 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Ppltdest
 .Nd determine PLT destination symbol
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "const char *"
 .Fo Ppltdest
--- old/usr/src/man/man3proc/Ppriv.3proc	Mon Oct 15 13:28:29 2018
+++ new/usr/src/man/man3proc/Ppriv.3proc	Mon Oct 15 13:28:29 2018
@@ -18,8 +18,9 @@
 .Nm Ppriv ,
 .Nm Ppriv_free
 .Nd get and free process privilege sets
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Ppriv
--- old/usr/src/man/man3proc/Ppsinfo.3proc	Mon Oct 15 13:28:30 2018
+++ new/usr/src/man/man3proc/Ppsinfo.3proc	Mon Oct 15 13:28:30 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Ppsinfo
 .Nd get process ps information
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "const psinfo_t *"
 .Fo Ppsinfo
--- old/usr/src/man/man3proc/Prd_agent.3proc	Mon Oct 15 13:28:31 2018
+++ new/usr/src/man/man3proc/Prd_agent.3proc	Mon Oct 15 13:28:31 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Prd_agent
 .Nd get librtld_db agent
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "rd_agent_t *"
 .Fo Prd_agent
--- old/usr/src/man/man3proc/Pread.3proc	Mon Oct 15 13:28:31 2018
+++ new/usr/src/man/man3proc/Pread.3proc	Mon Oct 15 13:28:31 2018
@@ -18,8 +18,9 @@
 .Nm Pread ,
 .Nm Pread_string
 .Nd read data from a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft ssize_t
 .Fo Pread
--- old/usr/src/man/man3proc/Prelease.3proc	Mon Oct 15 13:28:31 2018
+++ new/usr/src/man/man3proc/Prelease.3proc	Mon Oct 15 13:28:31 2018
@@ -18,8 +18,9 @@
 .Nm Prelease ,
 .Nm Pfree
 .Nd release a process control handle
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Prelease
--- old/usr/src/man/man3proc/Preopen.3proc	Mon Oct 15 13:28:31 2018
+++ new/usr/src/man/man3proc/Preopen.3proc	Mon Oct 15 13:28:31 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Preopen
 .Nd reopen a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Preopen
--- old/usr/src/man/man3proc/Preset_maps.3proc	Mon Oct 15 13:28:32 2018
+++ new/usr/src/man/man3proc/Preset_maps.3proc	Mon Oct 15 13:28:32 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Preset_maps
 .Nd reset memory mapping data after exec
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Preset_maps
--- old/usr/src/man/man3proc/Psecflags.3proc	Mon Oct 15 13:28:33 2018
+++ new/usr/src/man/man3proc/Psecflags.3proc	Mon Oct 15 13:28:33 2018
@@ -18,8 +18,9 @@
 .Nm Psecflags ,
 .Nm Psecflags_free
 .Nd get and free process security flags
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psecflags
--- old/usr/src/man/man3proc/Psetbkpt.3proc	Mon Oct 15 13:28:33 2018
+++ new/usr/src/man/man3proc/Psetbkpt.3proc	Mon Oct 15 13:28:33 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Psetbkpt
 .Nd set a breakpoint trap in a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psetbkpt
--- old/usr/src/man/man3proc/Psetcred.3proc	Mon Oct 15 13:28:33 2018
+++ new/usr/src/man/man3proc/Psetcred.3proc	Mon Oct 15 13:28:33 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Psetcred
 .Nd set process credentials
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psetcred
--- old/usr/src/man/man3proc/Psetfault.3proc	Mon Oct 15 13:28:34 2018
+++ new/usr/src/man/man3proc/Psetfault.3proc	Mon Oct 15 13:28:34 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Psetfault
 .Nd set fault tracing flags
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Psetfault
--- old/usr/src/man/man3proc/Psetflags.3proc	Mon Oct 15 13:28:34 2018
+++ new/usr/src/man/man3proc/Psetflags.3proc	Mon Oct 15 13:28:34 2018
@@ -18,8 +18,9 @@
 .Nm Psetflags ,
 .Nm Punsetflags
 .Nd set and unset process flags
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psetflags
--- old/usr/src/man/man3proc/Psetpriv.3proc	Mon Oct 15 13:28:34 2018
+++ new/usr/src/man/man3proc/Psetpriv.3proc	Mon Oct 15 13:28:34 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Psetpriv
 .Nd set process privileges
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psetpriv
--- old/usr/src/man/man3proc/Psetrun.3proc	Mon Oct 15 13:28:34 2018
+++ new/usr/src/man/man3proc/Psetrun.3proc	Mon Oct 15 13:28:34 2018
@@ -18,8 +18,9 @@
 .Nm Psetrun ,
 .Nm Lsetrun
 .Nd run a stopped process or thread
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psetrun
--- old/usr/src/man/man3proc/Psetsignal.3proc	Mon Oct 15 13:28:35 2018
+++ new/usr/src/man/man3proc/Psetsignal.3proc	Mon Oct 15 13:28:35 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Psetsignal
 .Nd set signal tracing flags
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Psetsignal
--- old/usr/src/man/man3proc/Psetsysentry.3proc	Mon Oct 15 13:28:35 2018
+++ new/usr/src/man/man3proc/Psetsysentry.3proc	Mon Oct 15 13:28:35 2018
@@ -18,8 +18,9 @@
 .Nm Psetsysentry ,
 .Nm Psetsysexit
 .Nd set system call tracing flags
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Psetsysentry
--- old/usr/src/man/man3proc/Psetwapt.3proc	Mon Oct 15 13:28:35 2018
+++ new/usr/src/man/man3proc/Psetwapt.3proc	Mon Oct 15 13:28:35 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Psetwapt
 .Nd set a watchpoint in a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psetwapt
--- old/usr/src/man/man3proc/Psetzoneid.3proc	Mon Oct 15 13:28:35 2018
+++ new/usr/src/man/man3proc/Psetzoneid.3proc	Mon Oct 15 13:28:35 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Psetzoneid
 .Nd change processes zone id
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psetzoneid
--- old/usr/src/man/man3proc/Psignal.3proc	Mon Oct 15 13:28:35 2018
+++ new/usr/src/man/man3proc/Psignal.3proc	Mon Oct 15 13:28:35 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Psignal
 .Nd set signal tracing action
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psignal
--- old/usr/src/man/man3proc/Pstack_iter.3proc	Mon Oct 15 13:28:36 2018
+++ new/usr/src/man/man3proc/Pstack_iter.3proc	Mon Oct 15 13:28:36 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pstack_iter
 .Nd iterate process stack frames
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pstack_iter
--- old/usr/src/man/man3proc/Pstate.3proc	Mon Oct 15 13:28:36 2018
+++ new/usr/src/man/man3proc/Pstate.3proc	Mon Oct 15 13:28:36 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pstate
 .Nd obtain process handle state
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pstate
--- old/usr/src/man/man3proc/Pstatus.3proc	Mon Oct 15 13:28:36 2018
+++ new/usr/src/man/man3proc/Pstatus.3proc	Mon Oct 15 13:28:36 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pstatus
 .Nd obtain process status structure
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft "const pstatus_t *"
 .Fo Pstatus
--- old/usr/src/man/man3proc/Pstopstatus.3proc	Mon Oct 15 13:28:36 2018
+++ new/usr/src/man/man3proc/Pstopstatus.3proc	Mon Oct 15 13:28:36 2018
@@ -23,8 +23,9 @@
 .Nm Lstop ,
 .Nm Lwait
 .Nd process and thread stop operations
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Pdstop
--- old/usr/src/man/man3proc/Psymbol_iter.3proc	Mon Oct 15 13:28:37 2018
+++ new/usr/src/man/man3proc/Psymbol_iter.3proc	Mon Oct 15 13:28:37 2018
@@ -21,8 +21,9 @@
 .Nm Psymbol_iter_by_name ,
 .Nm Pxsymbol_iter
 .Nd iterate symbols in a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psymbol_iter
--- old/usr/src/man/man3proc/Psync.3proc	Mon Oct 15 13:28:37 2018
+++ new/usr/src/man/man3proc/Psync.3proc	Mon Oct 15 13:28:37 2018
@@ -18,8 +18,9 @@
 .Nm Psync ,
 .Nm Lsync
 .Nd synchronize cached tracing flags and modifications
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Psync
--- old/usr/src/man/man3proc/Psysentry.3proc	Mon Oct 15 13:28:37 2018
+++ new/usr/src/man/man3proc/Psysentry.3proc	Mon Oct 15 13:28:37 2018
@@ -18,8 +18,9 @@
 .Nm Psysentry ,
 .Nm Psysexit
 .Nd set system call entry and exit actions
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Psysentry
--- old/usr/src/man/man3proc/Puname.3proc	Mon Oct 15 13:28:37 2018
+++ new/usr/src/man/man3proc/Puname.3proc	Mon Oct 15 13:28:37 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Puname
 .Nd get uname information from a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft int
 .Fo Puname
--- old/usr/src/man/man3proc/Pupdate_maps.3proc	Mon Oct 15 13:28:37 2018
+++ new/usr/src/man/man3proc/Pupdate_maps.3proc	Mon Oct 15 13:28:37 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pupdate_maps
 .Nd update address space mappings
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Pupdate_maps
--- old/usr/src/man/man3proc/Pupdate_syms.3proc	Mon Oct 15 13:28:38 2018
+++ new/usr/src/man/man3proc/Pupdate_syms.3proc	Mon Oct 15 13:28:38 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pupdate_syms
 .Nd update cached symbol tables
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft void
 .Fo Pupdate_syms
--- old/usr/src/man/man3proc/Pwrite.3proc	Mon Oct 15 13:28:38 2018
+++ new/usr/src/man/man3proc/Pwrite.3proc	Mon Oct 15 13:28:38 2018
@@ -17,8 +17,9 @@
 .Sh NAME
 .Nm Pwrite
 .Nd write data to the address space of a process
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft ssize_t
 .Fo Pwrite
--- old/usr/src/man/man3proc/Pzonename.3proc	Mon Oct 15 13:28:38 2018
+++ new/usr/src/man/man3proc/Pzonename.3proc	Mon Oct 15 13:28:38 2018
@@ -19,8 +19,9 @@
 .Nm Pzoneroot ,
 .Nm Pzonepath
 .Nd get zone name, root, and full object path
-.Sh SYNOPSIS
+.Sh LIBRARY
 .Lb libproc
+.Sh SYNOPSIS
 .In libproc.h
 .Ft char *
 .Fo Pzonename
--- old/usr/src/man/man4/proc.4	Mon Oct 15 13:28:38 2018
+++ new/usr/src/man/man4/proc.4	Mon Oct 15 13:28:38 2018
@@ -1,11 +1,11 @@
 '\" te
 .\" Copyright 1989 AT&T
 .\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved.
-.\" Copyright (c) 2013, Joyent, Inc. All rights reserved.
+.\" 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]
-.TH PROC 4 "Jun 6, 2016"
+.TH PROC 4 "August 22, 2018"
 .SH NAME
 proc \- /proc, the process file system
 .SH DESCRIPTION
@@ -894,12 +894,12 @@
     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;
 .fi
 .in -2
@@ -1484,6 +1484,14 @@
 Write-only control file. The messages written to this file affect the specific
 lwp rather than the representative lwp, as is the case for the process's
 \fBctl\fR file.
+.SS lwpname
+A buffer of \fBTHREAD_NAME_MAX\fR 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
+\fBTHREAD_NAME_MAX\fR 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. \fBTHREAD_NAME_MAX\fR may increase
+in the future; clients should be prepared for this.
 .SS "lwpstatus"
 .LP
 lwp-specific state information. This file contains the \fBlwpstatus\fR
--- old/usr/src/pkg/manifests/system-dtrace-tests.mf	Mon Oct 15 13:28:39 2018
+++ new/usr/src/pkg/manifests/system-dtrace-tests.mf	Mon Oct 15 13:28:39 2018
@@ -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/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
@@ -1846,6 +1848,8 @@
 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/threadname/tst.threadname.d mode=0444
+file path=opt/SUNWdtrt/tst/common/threadname/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
--- old/usr/src/pkg/manifests/system-library.man3c.inc	Mon Oct 15 13:28:39 2018
+++ new/usr/src/pkg/manifests/system-library.man3c.inc	Mon Oct 15 13:28:39 2018
@@ -303,6 +303,7 @@
 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_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/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 @@
     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 @@
     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_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
--- old/usr/src/pkg/manifests/system-library.man3proc.inc	Mon Oct 15 13:28:39 2018
+++ new/usr/src/pkg/manifests/system-library.man3proc.inc	Mon Oct 15 13:28:39 2018
@@ -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/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
--- old/usr/src/pkg/manifests/system-test-libctest.mf	Mon Oct 15 13:28:40 2018
+++ new/usr/src/pkg/manifests/system-test-libctest.mf	Mon Oct 15 13:28:40 2018
@@ -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/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
--- old/usr/src/test/libc-tests/runfiles/default.run	Mon Oct 15 13:28:40 2018
+++ new/usr/src/test/libc-tests/runfiles/default.run	Mon Oct 15 13:28:40 2018
@@ -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]
@@ -88,6 +88,7 @@
 [/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]
 
--- old/usr/src/test/libc-tests/tests/threads/Makefile	Mon Oct 15 13:28:40 2018
+++ new/usr/src/test/libc-tests/tests/threads/Makefile	Mon Oct 15 13:28:40 2018
@@ -10,7 +10,7 @@
 #
 
 #
-# Copyright 2016 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
 #
 
 include $(SRC)/Makefile.master
@@ -18,7 +18,7 @@
 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
--- /dev/null	Mon Oct 15 13:28:40 2018
+++ new/usr/src/test/libc-tests/tests/threads/thread_name.c	Mon Oct 15 13:28:40 2018
@@ -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);
+}
--- old/usr/src/uts/common/disp/thread.c	Mon Oct 15 13:28:40 2018
+++ new/usr/src/uts/common/disp/thread.c	Mon Oct 15 13:28:40 2018
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2018 Joyent, Inc.
  */
 
 #include <sys/types.h>
@@ -74,6 +74,7 @@
 #include <sys/waitq.h>
 #include <sys/cpucaps.h>
 #include <sys/kiconv.h>
+#include <sys/ctype.h>
 
 struct kmem_cache *thread_cache;	/* cache of free threads */
 struct kmem_cache *lwp_cache;		/* cache of free lwps */
@@ -791,6 +792,11 @@
 	nthread--;
 	mutex_exit(&pidlock);
 
+	if (t->t_name != NULL) {
+		kmem_free(t->t_name, THREAD_NAME_MAX);
+		t->t_name = NULL;
+	}
+
 	/*
 	 * Free thread, lwp and stack.  This needs to be done carefully, since
 	 * if T_TALLOCSTK is set, the thread is part of the stack.
@@ -2126,4 +2132,76 @@
 		percent = 100;
 	}
 	return (percent);
+}
+
+/*
+ * NOTE: This will silently truncate a name > THREAD_NAME_MAX - 1 characters
+ * long.  It is expected that callers (acting on behalf of userland clients)
+ * will perform any required checks to return the correct error semantics.
+ * It is also expected callers on behalf of userland clients have done
+ * any necessary permission checks.
+ */
+int
+thread_setname(kthread_t *t, const char *name)
+{
+	char *buf = NULL;
+
+	/*
+	 * We optimistically assume that a thread's name will only be set
+	 * once and so allocate memory in preparation of setting t_name.
+	 * If it turns out a name has already been set, we just discard (free)
+	 * the buffer we just allocated and reuse the current buffer
+	 * (as all should be THREAD_NAME_MAX large).
+	 *
+	 * Such an arrangement means over the lifetime of a kthread_t, t_name
+	 * is either NULL or has one value (the address of the buffer holding
+	 * the current thread name).   The assumption is that most kthread_t
+	 * instances will not have a name assigned, so dynamically allocating
+	 * the memory should minimize the footprint of this feature, but by
+	 * having the buffer persist for the life of the thread, it simplifies
+	 * 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);
+	}
+
+	mutex_enter(&ttoproc(t)->p_lock);
+	if (t->t_name == NULL) {
+		t->t_name = buf;
+	} else {
+		if (buf != NULL) {
+			(void) strlcpy(t->t_name, name, THREAD_NAME_MAX);
+			kmem_free(buf, THREAD_NAME_MAX);
+		} else {
+			bzero(t->t_name, THREAD_NAME_MAX);
+		}
+	}
+	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));
 }
--- old/usr/src/uts/common/dtrace/dtrace.c	Mon Oct 15 13:28:40 2018
+++ new/usr/src/uts/common/dtrace/dtrace.c	Mon Oct 15 13:28:40 2018
@@ -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 @@
 
 		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 @@
 			 * 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 @@
 	 */
 	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;
--- old/usr/src/uts/common/exec/elf/elf_notes.c	Mon Oct 15 13:28:41 2018
+++ new/usr/src/uts/common/exec/elf/elf_notes.c	Mon Oct 15 13:28:41 2018
@@ -26,7 +26,7 @@
 
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
- * Copyright (c) 2014, Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 #include <sys/types.h>
@@ -94,7 +94,7 @@
 
 	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 @@
 	    + 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) {
@@ -456,6 +457,7 @@
 	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;
@@ -466,6 +468,10 @@
 			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);
@@ -476,11 +482,15 @@
 			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;
 
@@ -514,6 +524,11 @@
 		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.
--- old/usr/src/uts/common/fs/proc/prdata.h	Mon Oct 15 13:28:41 2018
+++ new/usr/src/uts/common/fs/proc/prdata.h	Mon Oct 15 13:28:41 2018
@@ -27,7 +27,7 @@
 /*	  All Rights Reserved	*/
 
 /*
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 #ifndef _SYS_PROC_PRDATA_H
@@ -136,6 +136,7 @@
 	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	*/
@@ -360,7 +361,7 @@
 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);
--- old/usr/src/uts/common/fs/proc/prvnops.c	Mon Oct 15 13:28:42 2018
+++ new/usr/src/uts/common/fs/proc/prvnops.c	Mon Oct 15 13:28:42 2018
@@ -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>
@@ -183,22 +184,24 @@
 		".." },
 	{ 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
 };
@@ -587,7 +590,8 @@
 #endif
 	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(),
@@ -626,6 +630,7 @@
 	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	*/
@@ -1073,7 +1078,7 @@
  *	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)
@@ -1538,6 +1543,33 @@
 	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)
@@ -1808,6 +1840,7 @@
 	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	*/
@@ -2720,6 +2753,54 @@
 #endif
 }
 
+/* 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)
@@ -2798,6 +2879,9 @@
 			uiop->uio_resid = resid;
 		return (error);
 
+	case PR_LWPNAME:
+		return (pr_write_lwpname(pnp, uiop));
+
 	default:
 		return ((vp->v_type == VDIR)? EISDIR : EBADF);
 	}
@@ -3358,6 +3442,7 @@
 	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	*/
@@ -4621,6 +4706,10 @@
 		pnp->pr_mode = 0600;	/* read-write by owner only */
 		break;
 
+	case PR_LWPNAME:
+		pnp->pr_mode = 0644;	/* readable by all + owner can write */
+		break;
+
 	case PR_PSINFO:
 	case PR_LPSINFO:
 	case PR_LWPSINFO:
@@ -4745,6 +4834,7 @@
 	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	*/
--- old/usr/src/uts/common/sys/dtrace.h	Mon Oct 15 13:28:42 2018
+++ new/usr/src/uts/common/sys/dtrace.h	Mon Oct 15 13:28:42 2018
@@ -25,7 +25,7 @@
  */
 
 /*
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
  * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
@@ -242,6 +242,7 @@
 #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 @@
  */
 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 */
--- old/usr/src/uts/common/sys/elf.h	Mon Oct 15 13:28:43 2018
+++ new/usr/src/uts/common/sys/elf.h	Mon Oct 15 13:28:43 2018
@@ -429,10 +429,10 @@
 #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 */
 
@@ -776,7 +776,7 @@
 #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))
 
 
@@ -823,7 +823,7 @@
 #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 */
@@ -842,7 +842,7 @@
 
 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 */
@@ -901,7 +901,7 @@
  *	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) */
@@ -970,10 +970,11 @@
 #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
--- old/usr/src/uts/common/sys/procfs.h	Mon Oct 15 13:28:44 2018
+++ new/usr/src/uts/common/sys/procfs.h	Mon Oct 15 13:28:44 2018
@@ -25,6 +25,7 @@
  */
 /*
  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
+ * Copyright 2018 Joyent, Inc.
  */
 
 #ifndef _SYS_PROCFS_H
@@ -65,6 +66,7 @@
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/secflags.h>
+#include <sys/thread.h>
 
 /*
  * System call interfaces for /proc.
@@ -344,7 +346,7 @@
 	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 */
@@ -535,6 +537,16 @@
 } 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 {
--- old/usr/src/uts/common/sys/thread.h	Mon Oct 15 13:28:44 2018
+++ new/usr/src/uts/common/sys/thread.h	Mon Oct 15 13:28:45 2018
@@ -24,6 +24,10 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
 #ifndef	_SYS_THREAD_H
 #define	_SYS_THREAD_H
 
@@ -345,6 +349,8 @@
 	kmutex_t	t_ctx_lock;	/* protects t_ctx in removectx() */
 	struct waitq	*t_waitq;	/* wait queue */
 	kmutex_t	t_wait_mutex;	/* used in CV wait functions */
+
+	char		*t_name;	/* thread name */
 } kthread_t;
 
 /*
@@ -589,10 +595,15 @@
 
 caddr_t	thread_stk_init(caddr_t);	/* init thread stack */
 
+int thread_setname(kthread_t *, const char *);
+int thread_vsetname(kthread_t *, const char *, ...);
+
 extern int default_binding_mode;
 
 #endif	/* _KERNEL */
 
+#define	THREAD_NAME_MAX	32	/* includes terminating NUL */
+
 /*
  * Macros to indicate that the thread holds resources that could be critical
  * to other kernel threads, so this thread needs to have kernel priority
