8158 Want named threads API
9857 proc manpages should have LIBRARY section
Reviewed by: Andy Fiddaman <andy@omniosce.org>
Reviewed by: Gordon Ross <gwr@nexenta.com>
Approved by: Dan McDonald <danmcd@joyent.com>
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
index a5031e9..c199561 100644
--- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
+++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
@@ -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;
diff --git a/usr/src/cmd/dtrace/test/tst/common/Makefile b/usr/src/cmd/dtrace/test/tst/common/Makefile
index 808d0e4..a29d774 100644
--- a/usr/src/cmd/dtrace/test/tst/common/Makefile
+++ b/usr/src/cmd/dtrace/test/tst/common/Makefile
@@ -26,8 +26,8 @@
#
# Copyright (c) 2012 by Delphix. All rights reserved.
-# Copyright (c) 2013, Joyent, Inc. All rights reserved.
# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2018 Joyent, Inc.
#
#
@@ -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)
diff --git a/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c
new file mode 100644
index 0000000..49d9f21
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c
@@ -0,0 +1,99 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
+/*
+ * All we're doing is constantly modifying a thread name while DTrace is
+ * watching us, making sure we don't break.
+ */
+
+#include <sys/fcntl.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NR_THREADS (100)
+#define RUNTIME (30) /* seconds */
+
+static void
+random_ascii(char *buf, size_t bufsize)
+{
+ char table[] = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,.-#'?!";
+ size_t len = rand() % bufsize;
+
+ bzero(buf, bufsize);
+
+ for (size_t i = 0; i < len; i++) {
+ buf[i] = table[rand() % (sizeof (table) - 1)];
+ }
+}
+
+static void
+busy()
+{
+ struct timeval tv1;
+ struct timeval tv2;
+
+ if (gettimeofday(&tv1, NULL) != 0)
+ abort();
+
+ for (;;) {
+ static volatile int i;
+ for (i = 0; i < 2000000; i++)
+ ;
+
+ if (gettimeofday(&tv2, NULL) != 0)
+ abort();
+
+ /* janky, but we don't care */
+ if (tv2.tv_sec != tv1.tv_sec)
+ return;
+ }
+}
+
+static void *
+thread(void *arg)
+{
+ char name[PTHREAD_MAX_NAMELEN_NP];
+
+ for (size_t i = 0; ; i++) {
+ random_ascii(name, sizeof (name));
+
+ if ((i % 100) == 0) {
+ if (pthread_setname_np(pthread_self(), NULL) != 0)
+ abort();
+ } else {
+ (void) pthread_setname_np(pthread_self(), name);
+ }
+
+ busy();
+ }
+
+ return (NULL);
+}
+
+int
+main(int argc, char **argv)
+{
+ pthread_t tids[NR_THREADS];
+
+ for (size_t i = 0; i < NR_THREADS; i++) {
+ if (pthread_create(&tids[i], NULL, thread, NULL) != 0)
+ exit(EXIT_FAILURE);
+ }
+
+ sleep(RUNTIME);
+ exit(EXIT_SUCCESS);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d
new file mode 100644
index 0000000..289f6c5
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d
@@ -0,0 +1,26 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
+#pragma D option quiet
+
+profile-10ms /pid == $1 && threadname == "unlikely"/
+{
+ surprising++;
+}
+
+syscall::rexit:entry /pid == $1/
+{
+ exit(arg0);
+}
diff --git a/usr/src/cmd/halt/Makefile b/usr/src/cmd/halt/Makefile
index 98d8ecc..a515a0a 100644
--- a/usr/src/cmd/halt/Makefile
+++ b/usr/src/cmd/halt/Makefile
@@ -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)
diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_change.c b/usr/src/cmd/ldapcachemgr/cachemgr_change.c
index 85a15a1..727851f 100644
--- a/usr/src/cmd/ldapcachemgr/cachemgr_change.c
+++ b/usr/src/cmd/ldapcachemgr/cachemgr_change.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <strings.h>
@@ -33,6 +35,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <procfs.h>
+#include <pthread.h>
#include "cachemgr.h"
extern admin_t current_admin;
@@ -535,6 +538,8 @@
pid_t pid;
int always = 1, waiting;
+ (void) pthread_setname_np(pthread_self(), "chg_cleanup_thr");
+
if (op == NULL) {
waiting = 1;
type = CLEANUP_ALL;
diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c b/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c
index bb352ae..6650c9c 100644
--- a/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c
+++ b/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#ifdef SLP
@@ -539,9 +541,12 @@
* parameter 'r' should be a pointer to an unsigned int containing
* the requested interval at which the network should be queried.
*/
-void discover(void *r) {
+void
+discover(void *r) {
unsigned short reqrefresh = *((unsigned int *)r);
+ (void) pthread_setname_np(pthread_self(), "discover");
+
for (;;) {
find_all_contexts("ldap",
__cache_get_cfghandle,
diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c b/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
index 298e61f..b9bc3f7 100644
--- a/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
+++ b/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c
@@ -20,6 +20,8 @@
*/
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <assert.h>
@@ -1631,6 +1633,8 @@
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;
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_proc.c b/usr/src/cmd/mdb/common/mdb/mdb_proc.c
index 6c9f0aa..33994c1 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_proc.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_proc.c
@@ -1303,6 +1303,23 @@
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);
diff --git a/usr/src/cmd/mdb/common/modules/genunix/findstack.c b/usr/src/cmd/mdb/common/modules/genunix/findstack.c
index 12b90b8..fc8a4f8 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/findstack.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/findstack.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * Copyright 2018 Joyent, Inc.
*/
#include <mdb/mdb_modapi.h>
@@ -38,6 +39,12 @@
#include "thread.h"
#include "sobj.h"
+/*
+ * Parts of this file are shared between targets, but this section is only
+ * used for KVM and KMDB.
+ */
+#ifdef _KERNEL
+
int findstack_debug_on = 0;
/*
@@ -48,6 +55,7 @@
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;
diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
index 425911d..7192060 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
@@ -21,7 +21,7 @@
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 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;
diff --git a/usr/src/cmd/mdb/common/modules/genunix/thread.c b/usr/src/cmd/mdb/common/modules/genunix/thread.c
index 652e5af..410f997 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/thread.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/thread.c
@@ -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,50 +702,32 @@
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 (thread_getdesc(addr, B_TRUE, desc, sizeof (desc)) == -1)
+ return (DCMD_ERR);
+
+ mdb_printf("%0?p %?p %?p %s\n", addr, t.t_procp, t.t_lwp, desc);
+ return (DCMD_OK);
}
- if (mdb_vread(&tq, sizeof (taskq_t), (uintptr_t)t.t_taskq) == -1)
- tq.tq_name[0] = '\0';
+ 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);
- 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_inc_indent(2);
- mdb_inc_indent(2);
+ mdb_printf("PC: %a\n", t.t_pc);
- 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_snprintf(cmd, sizeof (cmd), "<.$c%d", count);
+ cmdarg.a_type = MDB_TYPE_STRING;
+ cmdarg.a_un.a_str = cmd;
- mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", count);
- cmdarg.a_type = MDB_TYPE_STRING;
- cmdarg.a_un.a_str = cmd;
+ (void) mdb_call_dcmd("findstack", addr, flags, 1, &cmdarg);
- (void) mdb_call_dcmd("findstack", addr, flags, 1, &cmdarg);
+ mdb_dec_indent(2);
- mdb_dec_indent(2);
-
- 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_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();
}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/thread.h b/usr/src/cmd/mdb/common/modules/genunix/thread.h
index 18952fd..901d962 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/thread.h
+++ b/usr/src/cmd/mdb/common/modules/genunix/thread.h
@@ -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
diff --git a/usr/src/cmd/nscd/cache.c b/usr/src/cmd/nscd/cache.c
index 2ffb95c..288c6e7 100644
--- a/usr/src/cmd/nscd/cache.c
+++ b/usr/src/cmd/nscd/cache.c
@@ -22,6 +22,7 @@
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -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;
diff --git a/usr/src/cmd/nscd/nscd_frontend.c b/usr/src/cmd/nscd/nscd_frontend.c
index 7ed5e71..134da3f 100644
--- a/usr/src/cmd/nscd/nscd_frontend.c
+++ b/usr/src/cmd/nscd/nscd_frontend.c
@@ -22,6 +22,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#include <stdlib.h>
@@ -89,6 +90,8 @@
{
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)
diff --git a/usr/src/cmd/nscd/nscd_getentctx.c b/usr/src/cmd/nscd/nscd_getentctx.c
index 2fed9a5..f4e6b89 100644
--- a/usr/src/cmd/nscd/nscd_getentctx.c
+++ b/usr/src/cmd/nscd/nscd_getentctx.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/ccompile.h>
@@ -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));
diff --git a/usr/src/cmd/nscd/nscd_selfcred.c b/usr/src/cmd/nscd/nscd_selfcred.c
index df4d2a2..b6cdba8 100644
--- a/usr/src/cmd/nscd/nscd_selfcred.c
+++ b/usr/src/cmd/nscd/nscd_selfcred.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2018 Joyent Inc.
*/
#include <stdio.h>
@@ -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);
diff --git a/usr/src/cmd/nscd/nscd_smfmonitor.c b/usr/src/cmd/nscd/nscd_smfmonitor.c
index bd2ff95..c5d5731 100644
--- a/usr/src/cmd/nscd/nscd_smfmonitor.c
+++ b/usr/src/cmd/nscd/nscd_smfmonitor.c
@@ -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
diff --git a/usr/src/cmd/prstat/Makefile.com b/usr/src/cmd/prstat/Makefile.com
index e317483..96c1450 100644
--- a/usr/src/cmd/prstat/Makefile.com
+++ b/usr/src/cmd/prstat/Makefile.com
@@ -21,6 +21,7 @@
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
+# Copyright 2018, Joyent, Inc.
#
# cmd/prstat/Makefile.com
#
@@ -31,6 +32,7 @@
include ../../Makefile.cmd
+CSTD = $(CSTD_GNU99)
CFLAGS += $(CCVERBOSE)
CERRWARN += -_gcc=-Wno-parentheses
LDLIBS += -lcurses -lproject
diff --git a/usr/src/cmd/prstat/prstat.c b/usr/src/cmd/prstat/prstat.c
index fc16e43..0ff4f51 100644
--- a/usr/src/cmd/prstat/prstat.c
+++ b/usr/src/cmd/prstat/prstat.c
@@ -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);
diff --git a/usr/src/cmd/prstat/prstat.h b/usr/src/cmd/prstat/prstat.h
index 293123c..e205a98 100644
--- a/usr/src/cmd/prstat/prstat.h
+++ b/usr/src/cmd/prstat/prstat.h
@@ -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
diff --git a/usr/src/cmd/prstat/prutil.c b/usr/src/cmd/prstat/prutil.c
index 0f9cbd6..551c72c 100644
--- a/usr/src/cmd/prstat/prutil.c
+++ b/usr/src/cmd/prstat/prutil.c
@@ -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,14 +325,16 @@
/*
* Remove all unprintable characters from process name
*/
-void
-stripfname(char *buf)
+static void
+stripfname(char *buf, size_t bufsize, const char *pname)
{
int bytesleft = PRFNSZ;
wchar_t wchar;
int length;
char *cp;
+ (void) strlcpy(buf, pname, bufsize);
+
buf[bytesleft - 1] = '\0';
for (cp = buf; *cp != '\0'; cp += length) {
@@ -351,3 +354,71 @@
bytesleft -= length;
}
}
+
+
+/*
+ * prstat has always implicitly wanted a terminal width of at least 80 columns
+ * (when a TTY is present). If run in a terminal narrower than 80 columns,
+ * prstat output may wrap. For wider terminals, we allow the last column to use
+ * the additional space.
+ *
+ * We never truncate if using -c, or not outputting to a TTY.
+ */
+static int
+format_namewidth(void)
+{
+ int prefixlen = 0;
+
+ if (opts.o_cols == 0 || !(opts.o_outpmode & (OPT_TERMCAP | OPT_TRUNC)))
+ return (0);
+
+ if (opts.o_outpmode & OPT_PSINFO) {
+ if (opts.o_outpmode & OPT_LGRP)
+ prefixlen = 64;
+ else
+ prefixlen = 59;
+ } else if (opts.o_outpmode & OPT_MSACCT) {
+ prefixlen = 64;
+ }
+
+ return (opts.o_cols - prefixlen);
+}
+
+void
+format_name(lwp_info_t *lwp, char *buf, size_t buflen)
+{
+ int pname_width = PRFNSZ;
+ char nr_suffix[20];
+ char pname[PRFNSZ];
+ int width;
+ int n;
+
+ stripfname(pname, sizeof (pname), lwp->li_info.pr_fname);
+
+ if (opts.o_outpmode & OPT_LWPS) {
+ n = snprintf(nr_suffix, sizeof (nr_suffix), "%d",
+ lwp->li_info.pr_lwp.pr_lwpid);
+ } else {
+ n = snprintf(nr_suffix, sizeof (nr_suffix), "%d",
+ lwp->li_info.pr_nlwp + lwp->li_info.pr_nzomb);
+ }
+
+ width = format_namewidth();
+
+ /* If we're over budget, truncate the process name not the LWP part. */
+ if (strlen(pname) > (width - n - 1)) {
+ pname_width = width - n - 1;
+ pname[pname_width - 1] = '*';
+ }
+
+ if ((opts.o_outpmode & OPT_LWPS) && lwp->li_lwpname[0] != '\0') {
+ n = snprintf(buf, buflen, "%.*s/%s [%s]", pname_width,
+ pname, nr_suffix, lwp->li_lwpname);
+ } else {
+ n = snprintf(buf, buflen, "%.*s/%s", pname_width,
+ pname, nr_suffix);
+ }
+
+ if (width > 0 && strlen(buf) > width)
+ buf[width] = '\0';
+}
diff --git a/usr/src/cmd/prstat/prutil.h b/usr/src/cmd/prstat/prutil.h
index cfa2133..ae2dbe5 100644
--- a/usr/src/cmd/prstat/prutil.h
+++ b/usr/src/cmd/prstat/prutil.h
@@ -25,6 +25,7 @@
* Use is subject to license terms.
*
* Portions Copyright 2009 Chad Mynhier
+ * Copyright 2018, Joyent, Inc.
*/
#ifndef _PRUTIL_H
@@ -54,7 +55,7 @@
extern void Priocntl(char *);
extern void getprojname(projid_t, char *, size_t, int, int, size_t);
extern void getzonename(projid_t, char *, size_t, int, size_t);
-extern void stripfname(char *);
+extern void format_name(lwp_info_t *, char *, size_t);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/ps/ps.c b/usr/src/cmd/ps/ps.c
index 78dabbc..1a3e916 100644
--- a/usr/src/cmd/ps/ps.c
+++ b/usr/src/cmd/ps/ps.c
@@ -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)
diff --git a/usr/src/cmd/ptools/pstack/pstack.c b/usr/src/cmd/ptools/pstack/pstack.c
index 0515ff6..d1d55d2 100644
--- a/usr/src/cmd/ptools/pstack/pstack.c
+++ b/usr/src/cmd/ptools/pstack/pstack.c
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/isa_defs.h>
@@ -137,7 +139,7 @@
static 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,15 +416,19 @@
static int
lwp_call_stack(void *data,
- const lwpstatus_t *psp, const lwpsinfo_t *pip)
+ const lwpstatus_t *psp, const lwpsinfo_t *pip)
{
+ char lwpname[THREAD_NAME_MAX] = "";
pstack_handle_t *h = data;
if (!proc_lwp_in_set(h->lwps, pip->pr_lwpid))
return (0);
h->count++;
- tlhead(0, pip->pr_lwpid);
+ (void) Plwp_getname(h->proc, pip->pr_lwpid,
+ lwpname, sizeof (lwpname));
+
+ tlhead(0, pip->pr_lwpid, lwpname);
if (psp)
call_stack(h, psp);
else
@@ -462,7 +472,7 @@
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*/
diff --git a/usr/src/cmd/sgs/elfdump/common/corenote.c b/usr/src/cmd/sgs/elfdump/common/corenote.c
index 0777025..a5ba4e31 100644
--- a/usr/src/cmd/sgs/elfdump/common/corenote.c
+++ b/usr/src/cmd/sgs/elfdump/common/corenote.c
@@ -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);
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
index e7488d5..253ea4a 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
@@ -22,6 +22,7 @@
#
# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+# Copyright 2018 Joyent, Inc.
#
@ _START_
@@ -469,6 +470,7 @@
@ MSG_CNOTE_DESC_STRUCT_UTSNAME "desc: (struct utsname)"
@ MSG_CNOTE_DESC_PRFDINFO_T "desc: (prfdinfo_t)"
@ MSG_CNOTE_DESC_PRSECFLAGS_T "desc: (prsecflags_t)"
+@ MSG_CNOTE_DESC_PRLWPNAME_T "desc: (prlwpname_t)"
@ MSG_CNOTE_FMT_LINE "%*s%-*s%s"
@ MSG_CNOTE_FMT_LINE_2UP "%*s%-*s%-*s%-*s%s"
@@ -535,6 +537,7 @@
@ MSG_CNOTE_T_PR_LWP "pr_lwp:"
@ MSG_CNOTE_T_PR_LWPHOLD "pr_lwphold:"
@ MSG_CNOTE_T_PR_LWPID "pr_lwpid:"
+@ MSG_CNOTE_T_PR_LWPNAME "pr_lwpname:"
@ MSG_CNOTE_T_PR_LWPPEND "pr_lwppend:"
@ MSG_CNOTE_T_PR_NAME "pr_name:"
@ MSG_CNOTE_T_PR_NGROUPS "pr_ngroups:"
diff --git a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
index f7af1c1..674972d 100644
--- a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
+++ b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
@@ -11,6 +11,7 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -58,3 +59,4 @@
struct utsname uts;
prfdinfo_t ptfd;
prsecflags_t psf;
+prlwpname_t psn;
diff --git a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
index d90363c..522c974 100644
--- a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
+++ b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
@@ -24,11 +24,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");
/*
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout.h b/usr/src/cmd/sgs/elfdump/common/struct_layout.h
index b0592d6..022640e 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout.h
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout.h
@@ -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;
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
index 2b9469a..42260b1 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
@@ -25,6 +25,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#include <struct_layout.h>
@@ -387,6 +388,13 @@
};
+static const sl_prlwpname_layout_t prlwpname_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
+ { 0, 8, 0, 0 }, /* pr_lwpid */
+ { 8, 1, 32, 0 }, /* pr_lwpname[] */
+};
+
+
static const sl_arch_layout_t layout_amd64 = {
@@ -411,6 +419,7 @@
&utsname_layout,
&prfdinfo_layout,
&prsecflags_layout,
+ &prlwpname_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
index 6a516bc..de104e9 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
@@ -25,6 +25,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#include <struct_layout.h>
@@ -387,6 +388,13 @@
};
+static const sl_prlwpname_layout_t prlwpname_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
+ { 0, 8, 0, 0 }, /* pr_lwpid */
+ { 8, 1, 32, 0 }, /* pr_lwpname[] */
+};
+
+
static const sl_arch_layout_t layout_i386 = {
@@ -411,6 +419,7 @@
&utsname_layout,
&prfdinfo_layout,
&prsecflags_layout,
+ &prlwpname_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
index 94760c3..ead0ae6 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
@@ -25,7 +25,9 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
+
#include <struct_layout.h>
@@ -386,6 +388,13 @@
};
+static const sl_prlwpname_layout_t prlwpname_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
+ { 0, 8, 0, 0 }, /* pr_lwpid */
+ { 8, 1, 32, 0 }, /* pr_lwpname[] */
+};
+
+
static const sl_arch_layout_t layout_sparc = {
@@ -410,6 +419,7 @@
&utsname_layout,
&prfdinfo_layout,
&prsecflags_layout,
+ &prlwpname_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
index a194d81..00eaae9 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
@@ -25,6 +25,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#include <struct_layout.h>
@@ -387,6 +388,13 @@
};
+static const sl_prlwpname_layout_t prlwpname_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
+ { 0, 8, 0, 0 }, /* pr_lwpid */
+ { 8, 1, 32, 0 }, /* pr_lwpname[] */
+};
+
+
static const sl_arch_layout_t layout_sparcv9 = {
@@ -411,6 +419,7 @@
&utsname_layout,
&prfdinfo_layout,
&prsecflags_layout,
+ &prlwpname_layout,
};
diff --git a/usr/src/cmd/sgs/libconv/Makefile.com b/usr/src/cmd/sgs/libconv/Makefile.com
index c6287c4..1bb482f 100644
--- a/usr/src/cmd/sgs/libconv/Makefile.com
+++ b/usr/src/cmd/sgs/libconv/Makefile.com
@@ -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)
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.c b/usr/src/cmd/sgs/libconv/common/corenote.c
index 02b3e5d..dc9b802 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.c
+++ b/usr/src/cmd/sgs/libconv/common/corenote.c
@@ -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 = {
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.msg b/usr/src/cmd/sgs/libconv/common/corenote.msg
index b55e67e..a36f2bd 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.msg
+++ b/usr/src/cmd/sgs/libconv/common/corenote.msg
@@ -49,6 +49,7 @@
@ MSG_NT_FDINFO "[ NT_FDINFO ]"
@ MSG_NT_SPYMASTER "[ NT_SPYMASTER ]"
@ MSG_NT_SECFLAGS "[ NT_SECFLAGS ]"
+@ MSG_NT_LWPNAME "[ NT_LWPNAME ]"
@ MSG_AUXV_AF_SUN_SETUGID "AF_SUN_SETUGID"
diff --git a/usr/src/cmd/svc/startd/graph.c b/usr/src/cmd/svc/startd/graph.c
index 62fbbf1..0e5253a 100644
--- a/usr/src/cmd/svc/startd/graph.c
+++ b/usr/src/cmd/svc/startd/graph.c
@@ -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);
diff --git a/usr/src/cmd/svc/startd/method.c b/usr/src/cmd/svc/startd/method.c
index cc9ce67..bddae9b 100644
--- a/usr/src/cmd/svc/startd/method.c
+++ b/usr/src/cmd/svc/startd/method.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 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. */
diff --git a/usr/src/cmd/svc/startd/restarter.c b/usr/src/cmd/svc/startd/restarter.c
index 676cded..a98c863 100644
--- a/usr/src/cmd/svc/startd/restarter.c
+++ b/usr/src/cmd/svc/startd/restarter.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -994,6 +994,8 @@
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) {
/*
diff --git a/usr/src/cmd/svc/startd/wait.c b/usr/src/cmd/svc/startd/wait.c
index ebd83be..12856ff 100644
--- a/usr/src/cmd/svc/startd/wait.c
+++ b/usr/src/cmd/svc/startd/wait.c
@@ -21,7 +21,8 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2012, Joyent, Inc. All rights reserved.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -252,6 +253,8 @@
void *
wait_thread(void *args)
{
+ (void) pthread_setname_np(pthread_self(), "wait");
+
for (;;) {
port_event_t pe;
int fd;
diff --git a/usr/src/head/pthread.h b/usr/src/head/pthread.h
index 91d268a..490a93f 100644
--- a/usr/src/head/pthread.h
+++ b/usr/src/head/pthread.h
@@ -21,7 +21,7 @@
/*
* Copyright 2014 Garrett D'Amore <garrett@damore.org>
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -139,6 +139,9 @@
/* 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
diff --git a/usr/src/head/thread.h b/usr/src/head/thread.h
index d0b0b3d..704174d 100644
--- a/usr/src/head/thread.h
+++ b/usr/src/head/thread.h
@@ -24,6 +24,8 @@
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _THREAD_H
@@ -87,6 +89,8 @@
extern int thr_setspecific(thread_key_t, void *);
extern int thr_getspecific(thread_key_t, void **);
extern size_t thr_min_stack(void);
+extern int thr_getname(thread_t, char *, size_t);
+extern int thr_setname(thread_t, const char *);
#endif /* _ASM */
diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h
index 81781fe..c9e2670 100644
--- a/usr/src/lib/libc/inc/thr_uberdata.h
+++ b/usr/src/lib/libc/inc/thr_uberdata.h
@@ -57,6 +57,7 @@
#include <sys/priocntl.h>
#include <thread_db.h>
#include <setjmp.h>
+#include <sys/thread.h>
#include "libc_int.h"
#include "tdb_agent.h"
#include "thr_debug.h"
@@ -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);
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index 953a08f..ba79795 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -23,7 +23,7 @@
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2018 Nexenta Systems, Inc.
# Copyright (c) 2012 by Delphix. All rights reserved.
-# Copyright 2016 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
# Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright (c) 2013 Gary Mills
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
@@ -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;
diff --git a/usr/src/lib/libc/port/threads/pthr_attr.c b/usr/src/lib/libc/port/threads/pthr_attr.c
index b04bcdb..7cfc970 100644
--- a/usr/src/lib/libc/port/threads/pthr_attr.c
+++ b/usr/src/lib/libc/port/threads/pthr_attr.c
@@ -25,11 +25,13 @@
*/
/*
- * Copyright 2015, Joyent, Inc.
+ * Copyright 2018, Joyent, Inc.
*/
#include "lint.h"
#include "thr_uberdata.h"
+#include <sys/ctype.h>
+#include <strings.h>
#include <sched.h>
/*
@@ -48,7 +50,8 @@
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:
diff --git a/usr/src/lib/libc/port/threads/pthread.c b/usr/src/lib/libc/port/threads/pthread.c
index 6a22995..34b4b4c 100644
--- a/usr/src/lib/libc/port/threads/pthread.c
+++ b/usr/src/lib/libc/port/threads/pthread.c
@@ -24,7 +24,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#include "lint.h"
@@ -128,7 +128,7 @@
flag = ap->scope | ap->detachstate | ap->daemonstate | THR_SUSPENDED;
error = _thrp_create(ap->stkaddr, ap->stksize, start_routine, arg,
- flag, &tid, ap->guardsize);
+ flag, &tid, ap->guardsize, ap->name);
if (error == 0) {
/*
* Record the original inheritence value for
diff --git a/usr/src/lib/libc/port/threads/thr.c b/usr/src/lib/libc/port/threads/thr.c
index 640c1c9..e849b19 100644
--- a/usr/src/lib/libc/port/threads/thr.c
+++ b/usr/src/lib/libc/port/threads/thr.c
@@ -25,7 +25,7 @@
* Copyright (c) 2017 by The MathWorks, Inc. All rights reserved.
*/
/*
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#include "lint.h"
@@ -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
diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c
index d6e90bd..eb88f7e 100644
--- a/usr/src/lib/libdtrace/common/dt_open.c
+++ b/usr/src/lib/libdtrace/common/dt_open.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
*/
@@ -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,
diff --git a/usr/src/lib/libfakekernel/common/sys/thread.h b/usr/src/lib/libfakekernel/common/sys/thread.h
index 6213be2..d6e05c6 100644
--- a/usr/src/lib/libfakekernel/common/sys/thread.h
+++ b/usr/src/lib/libfakekernel/common/sys/thread.h
@@ -24,6 +24,7 @@
* Use is subject to license terms.
*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _SYS_THREAD_H
@@ -82,6 +83,7 @@
#define _KTHREAD_INVALID ((void *)(uintptr_t)-1)
+#define THREAD_NAME_MAX (32)
struct proc;
extern struct proc *_curproc(void);
diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h
index ce5063f..e05ff8b 100644
--- a/usr/src/lib/libproc/common/Pcontrol.h
+++ b/usr/src/lib/libproc/common/Pcontrol.h
@@ -24,8 +24,8 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright (c) 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);
diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c
index afc5f45..3772819 100644
--- a/usr/src/lib/libproc/common/Pcore.c
+++ b/usr/src/lib/libproc/common/Pcore.c
@@ -24,7 +24,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright (c) 2014, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright 2015 Gary Mills
*/
@@ -726,6 +726,32 @@
}
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
diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c
index 6ddf92a..64ef980 100644
--- a/usr/src/lib/libproc/common/Pgcore.c
+++ b/usr/src/lib/libproc/common/Pgcore.c
@@ -25,7 +25,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright 2015 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -509,6 +509,7 @@
{
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);
diff --git a/usr/src/lib/libproc/common/Plwpregs.c b/usr/src/lib/libproc/common/Plwpregs.c
index c2b1500..bf35c91 100644
--- a/usr/src/lib/libproc/common/Plwpregs.c
+++ b/usr/src/lib/libproc/common/Plwpregs.c
@@ -24,7 +24,7 @@
*/
/*
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -353,6 +353,38 @@
}
int
+Plwp_getname(struct ps_prochandle *P, lwpid_t lwpid,
+ char *buf, size_t bufsize)
+{
+ char lwpname[THREAD_NAME_MAX];
+ char *from = NULL;
+ lwp_info_t *lwp;
+
+ if (P->state == PS_IDLE) {
+ errno = ENODATA;
+ return (-1);
+ }
+
+ if (P->state != PS_DEAD) {
+ if (getlwpfile(P, lwpid, "lwpname",
+ lwpname, sizeof (lwpname)) != 0)
+ return (-1);
+ from = lwpname;
+ } else {
+ if ((lwp = getlwpcore(P, lwpid)) == NULL)
+ return (-1);
+ from = lwp->lwp_name;
+ }
+
+ if (strlcpy(buf, from, bufsize) >= bufsize) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
Plwp_getspymaster(struct ps_prochandle *P, lwpid_t lwpid, psinfo_t *ps)
{
lwpstatus_t lps;
diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h
index d74c08e..eb73039 100644
--- a/usr/src/lib/libproc/common/libproc.h
+++ b/usr/src/lib/libproc/common/libproc.h
@@ -25,7 +25,7 @@
*
* Portions Copyright 2007 Chad Mynhier
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright 2015, Joyent, Inc.
+ * Copyright 2018, Joyent, Inc.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -436,6 +436,7 @@
extern int proc_get_ldt(pid_t, struct ssd *, int);
#endif /* __i386 || __amd64 */
+extern int Plwp_getname(struct ps_prochandle *, lwpid_t, char *, size_t);
extern int Plwp_getpsinfo(struct ps_prochandle *, lwpid_t, lwpsinfo_t *);
extern int Plwp_getspymaster(struct ps_prochandle *, lwpid_t, psinfo_t *);
diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers
index b3f9df9..3b2fe58 100644
--- a/usr/src/lib/libproc/common/mapfile-vers
+++ b/usr/src/lib/libproc/common/mapfile-vers
@@ -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;
diff --git a/usr/src/man/man1/ps.1 b/usr/src/man/man1/ps.1
index f0f01d4..3c83872 100644
--- a/usr/src/man/man1/ps.1
+++ b/usr/src/man/man1/ps.1
@@ -44,9 +44,9 @@
.\" Portions Copyright (c) 1992, X/Open Company Limited All Rights Reserved
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved
.\" Copyright (c) 2013 Gary Mills
-.\" Copyright (c) 2017, Joyent, Inc.
+.\" Copyright (c) 2018, Joyent, Inc.
.\"
-.TH PS 1 "Jun 13, 2017"
+.TH PS 1 "August 22, 2018"
.SH NAME
ps \- report process status
.SH SYNOPSIS
@@ -882,14 +882,14 @@
started, or is a version of the arguments as they might have been modified by
the application. Applications cannot depend on being able to modify their
argument list and having that modification be reflected in the output of
-\fBps\fR. The Solaris implementation limits the string to 80 bytes; the string
+\fBps\fR. The illumos implementation limits the string to 80 bytes; the string
is the version of the argument list as it was passed to the command when it
started.
.RE
.sp
.LP
-The following names are recognized in the Solaris implementation:
+The following names are recognized in the illumos implementation:
.sp
.ne 2
.na
@@ -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 illumos implementation variables, are not.
.sp
.LP
The following table specifies the default header to be used in the POSIX locale
@@ -1196,12 +1206,12 @@
nice NI tty TT
pcpu %CPU user USER
pgid PGID vsz VSZ
-pid PID
+pid PID
.TE
.sp
.LP
-The following table lists the Solaris implementation format specifiers and the
+The following table lists the illumos implementation format specifiers and the
default header used with each.
.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
diff --git a/usr/src/man/man1m/prstat.1m b/usr/src/man/man1m/prstat.1m
index a5f0262..d181c9a 100644
--- a/usr/src/man/man1m/prstat.1m
+++ b/usr/src/man/man1m/prstat.1m
@@ -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
diff --git a/usr/src/man/man3c/Makefile b/usr/src/man/man3c/Makefile
index 2c890a7..9d1c679 100644
--- a/usr/src/man/man3c/Makefile
+++ b/usr/src/man/man3c/Makefile
@@ -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
diff --git a/usr/src/man/man3c/pthread_attr_getname_np.3c b/usr/src/man/man3c/pthread_attr_getname_np.3c
new file mode 100644
index 0000000..fbac370
--- /dev/null
+++ b/usr/src/man/man3c/pthread_attr_getname_np.3c
@@ -0,0 +1,105 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Joyent, Inc.
+.\"
+.Dd "August 22, 2018"
+.Dt PTHREAD_ATTR_GETNAME_NP 3C
+.Os
+.Sh NAME
+.Nm pthread_attr_getname_np ,
+.Nm pthread_attr_setname_np
+.Nd get or set thread name attribute
+.Sh SYNOPSIS
+.In pthread.h
+.
+.Ft int
+.Fo pthread_attr_getname_np
+.Fa "pthread_attr_t *restrict attr"
+.Fa "char *name"
+.Fa "size_t len"
+.Fc
+.
+.Ft int
+.Fo pthread_attr_setname_np
+.Fa "pthread_attr_t *restrict attr"
+.Fa "const char *name"
+.Fc
+.
+.Sh DESCRIPTION
+The
+.Fn pthread_attr_setname_np
+and
+.Fn pthread_attr_getname_np
+functions, respectively, set and get the thread name attribute in
+.Fa attr
+to
+.Fa name .
+For
+.Fn pthread_attr_getname_np ,
+.Fa len
+is the size of
+.Fa name .
+Any threads created with
+.Xr pthread_create 3c
+using
+.Fa attr
+will have their name set to
+.Fa name
+upon creation.
+.Pp
+Thread names are limited to
+.Dv PTHREAD_MAX_NAMELEN_NP
+including the terminating NUL.
+They may only contain printable ASCII characters.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn pthread_attr_getname_np
+and
+.Fn pthread_attr_setname_np
+functions return
+.Sy 0 .
+Otherwise, an error number is returned to indicate the error.
+.Sh ERRORS
+The
+.Fn pthread_attr_getname_np
+function may fail with:
+.Bl -tag -width Er
+.It Er EINVAL
+The
+.Fa name
+argument is
+.Sy NULL .
+.It Er ERANGE
+The size of
+.Fa name
+as indicated by
+.Fa len
+is too small to contain the thread name.
+The buffer may be over-written with partial contents of the thread name.
+.El
+.Pp
+The
+.Fn pthread_attr_setname_np
+function may fail with:
+.Bl -tag -width Er
+.It Er ERANGE
+The length of name given in
+.Fa name
+exceeds the maximum size allowed.
+.El
+.Sh INTERFACE STABILITY
+.Sy Uncommitted
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr pthread_create 3c ,
+.Xr pthread_getname_np 3c
diff --git a/usr/src/man/man3c/pthread_getname_np.3c b/usr/src/man/man3c/pthread_getname_np.3c
new file mode 100644
index 0000000..7404a4a
--- /dev/null
+++ b/usr/src/man/man3c/pthread_getname_np.3c
@@ -0,0 +1,124 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Joyent, Inc.
+.\"
+.Dd "August 22, 2018"
+.Dt PTHREAD_GETNAME_NP 3C
+.Os
+.Sh NAME
+.Nm pthread_getname_np ,
+.Nm pthread_setname_np
+.Nd get or set the name of a thread
+.Sh SYNOPSIS
+.In pthread.h
+.
+.Ft int
+.Fo pthread_getname_np
+.Fa "pthread_t tid"
+.Fa "char *name"
+.Fa "size_t len"
+.Fc
+.
+.Ft int
+.Fo pthread_setname_np
+.Fa "pthread_t tid"
+.Fa "const char *name"
+.Fc
+.
+.Sh DESCRIPTION
+The
+.Fn pthread_getname_np
+and
+.Fn pthread_setname_np
+functions, respectively, get and set the names of the thread whose id is given
+by the
+.Fa tid
+parameter.
+For
+.Fn pthread_getname_np ,
+.Fa len
+indicates the size of
+.Fa name .
+.Pp
+Thread names are limited to
+.Dv PTHREAD_MAX_NAMELEN_NP
+including the terminating NUL.
+They may only contain printable ASCII characters.
+.Pp
+To clear a thread name, call
+.Fn pthread_setname_np
+with
+.Sy NULL .
+.Pp
+Unlike some other systems, threads do not inherit the process name by default.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn pthread_getname_np
+and
+.Fn pthread_setname_np
+functions return
+.Sy 0 .
+Otherwise, an error number is returned to indicate the error.
+If the thread identified by
+.Fa tid
+does not have a name set,
+.Fa pthread_getname_np
+will be set to an empty string (length = 0).
+.Sh ERRORS
+On failure, the contents of the buffer are undefined.
+Errors from
+.Xr open 2 ,
+.Xr read 2 ,
+or
+.Xr write 2
+are possible.
+In addition, the
+.Fn pthread_getname_np
+function will fail with:
+.Bl -tag -width Er
+.It Er EINVAL
+The
+.Fa name
+argument is
+.Sy NULL .
+.It Er ERANGE
+The size of
+.Fa name
+as given by
+.Fa len
+was not large enough to contain the name of the thread.
+.It Er ESRCH
+The thread
+.Fa tid
+was not found.
+.El
+.Pp
+The
+.Fn pthread_setname_np
+function will fail with:
+.Bl -tag -width Er
+.It Er ERANGE
+The length of
+.Fa name
+exceeds the maximum allowed size.
+.It Er ESRCH
+The thread
+.Fa tid
+was not found.
+.El
+.Sh INTERFACE STABILITY
+.Sy Uncommitted
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr pthread_attr_getname_np 3c ,
+.Xr pthread_create 3c
diff --git a/usr/src/man/man3c/thr_getname.3c b/usr/src/man/man3c/thr_getname.3c
new file mode 100644
index 0000000..551e620
--- /dev/null
+++ b/usr/src/man/man3c/thr_getname.3c
@@ -0,0 +1,124 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Joyent, Inc.
+.\"
+.Dd "August 22, 2018"
+.Dt THR_GETNAME 3C
+.Os
+.Sh NAME
+.Nm thr_getname ,
+.Nm thr_setname
+.Nd get or set the name of a thread
+.Sh SYNOPSIS
+.In thread.h
+.
+.Ft int
+.Fo thr_getname
+.Fa "thread_t tid"
+.Fa "char *name"
+.Fa "size_t len"
+.Fc
+.
+.Ft int
+.Fo thr_setname
+.Fa "thread_t tid"
+.Fa "const char *name"
+.Fc
+.
+.Sh DESCRIPTION
+The
+.Fn thr_getname
+and
+.Fn thr_setname
+functions, respectively, get and set the names of the thread whose id is given
+by the
+.Fa tid
+parameter.
+For
+.Fn thr_getname ,
+.Fa len
+indicates the size of
+.Fa name .
+.Pp
+Thread names are limited to
+.Dv THREAD_NAME_MAX
+including the terminating NUL.
+They may only contain printable ASCII characters.
+.Pp
+To clear a thread name, call
+.Fn thr_setname
+with
+.Sy NULL .
+.Pp
+Unlike some other systems, threads do not inherit the process name by default.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn thr_getname
+and
+.Fn thr_setname
+functions return
+.Sy 0 .
+Otherwise, an error number is returned to indicate the error.
+If the thread identified by
+.Fa tid
+does not have a name set,
+.Fa thr_getname
+will be set to an empty string (length = 0).
+.Sh ERRORS
+On failure, the contents of the buffer are undefined.
+Errors from
+.Xr open 2 ,
+.Xr read 2 ,
+or
+.Xr write 2
+are possible.
+In addition, the
+.Fn thr_getname
+function will fail with:
+.Bl -tag -width Er
+.It Er EINVAL
+The
+.Fa name
+argument is
+.Sy NULL .
+.It Er ERANGE
+The size of
+.Fa name
+as given by
+.Fa len
+was not large enough to contain the name of the thread.
+.It Er ESRCH
+The thread
+.Fa tid
+was not found.
+.El
+.Pp
+The
+.Fn thr_setname
+function will fail with:
+.Bl -tag -width Er
+.It Er ERANGE
+The length of
+.Fa name
+exceeds the maximum allowed size.
+.It Er ESRCH
+The thread
+.Fa tid
+was not found.
+.El
+.Sh INTERFACE STABILITY
+.Sy Uncommitted
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr pthread_setname_np 3c ,
+.Xr thr_create 3c
diff --git a/usr/src/man/man3lib/libproc.3lib b/usr/src/man/man3lib/libproc.3lib
index 915febe..6b1e26e 100644
--- a/usr/src/man/man3lib/libproc.3lib
+++ b/usr/src/man/man3lib/libproc.3lib
@@ -9,9 +9,9 @@
.\" http://www.illumos.org/license/CDDL.
.\"
.\"
-.\" Copyright 2015 Joyent, Inc.
+.\" Copyright 2018 Joyent, Inc.
.\"
-.Dd June 06, 2016
+.Dd August 31, 2018
.Dt LIBPROC 3LIB
.Os
.Sh NAME
@@ -217,34 +217,34 @@
.It Sy Plmid_to_loadobj Ta Sy Plmid_to_map
.It Sy Plookup_by_addr Ta Sy Plookup_by_name
.It Sy Plwp_alt_stack Ta Sy Plwp_getfpregs
-.It Sy Plwp_getpsinfo Ta Sy Plwp_getregs
-.It Sy Plwp_getspymaster Ta Sy Plwp_main_stack
-.It Sy Plwp_setfpregs Ta Sy Plwp_setregs
-.It Sy Plwp_stack Ta Sy Pname_to_ctf
-.It Sy Pname_to_loadobj Ta Sy Pname_to_map
-.It Sy Pobjname Ta Sy Pobjname_resolved
-.It Sy Pplatform Ta Sy Ppltdest
-.It Sy Ppriv Ta Sy Ppsinfo
-.It Sy Pputareg Ta Sy Prd_agent
-.It Sy Pread Ta Sy Pread_string
-.It Sy Preset_maps Ta Sy Psetbkpt
-.It Sy Psecflags Ta Sy Psetcred
-.It Sy Psetfault Ta Sy Psetflags
-.It Sy Psetpriv Ta Sy Psetrun
-.It Sy Psetsignal Ta Sy Psetsysentry
-.It Sy Psetsysexit Ta Sy Psetwapt
-.It Sy Psetzoneid Ta Sy Psignal
-.It Sy Pstate Ta Sy Pstatus
-.It Sy Pstop Ta Sy Pstopstatus
-.It Sy Psync Ta Sy Psysentry
-.It Sy Psysexit Ta Sy Puname
-.It Sy Punsetflags Ta Sy Pupdate_maps
-.It Sy Pupdate_syms Ta Sy Pwait
-.It Sy Pwrite Ta Sy Pxecbkpt
-.It Sy Pxecwapt Ta Sy Pxlookup_by_addr
-.It Sy Pxlookup_by_addr_resolved Ta Sy Pxlookup_by_name
-.It Sy Pzonename Ta Sy Pzonepath
-.It Sy Pzoneroot Ta
+.It Sy Plwp_getname Ta Sy Plwp_getpsinfo
+.It Sy Plwp_getregs Ta Sy Plwp_getspymaster
+.It Sy Plwp_main_stack Ta Sy Plwp_setfpregs
+.It Sy Plwp_setregs Ta Sy Plwp_stack
+.It Sy Pname_to_ctf Ta Sy Pname_to_loadobj
+.It Sy Pname_to_map Ta Sy Pobjname
+.It Sy Pobjname_resolved Ta Sy Pplatform
+.It Sy Ppltdest Ta Sy Ppriv
+.It Sy Ppsinfo Ta Sy Pputareg
+.It Sy Prd_agent Ta Sy Pread
+.It Sy Pread_string Ta Sy Preset_maps
+.It Sy Psetbkpt Ta Sy Psecflags
+.It Sy Psetcred Ta Sy Psetfault
+.It Sy Psetflags Ta Sy Psetpriv
+.It Sy Psetrun Ta Sy Psetsignal
+.It Sy Psetsysentry Ta Sy Psetsysexit
+.It Sy Psetwapt Ta Sy Psetzoneid
+.It Sy Psignal Ta Sy Pstate
+.It Sy Pstatus Ta Sy Pstop
+.It Sy Pstopstatus Ta Sy Psync
+.It Sy Psysentry Ta Sy Psysexit
+.It Sy Puname Ta Sy Punsetflags
+.It Sy Pupdate_maps Ta Sy Pupdate_syms
+.It Sy Pwait Ta Sy Pwrite
+.It Sy Pxecbkpt Ta Sy Pxecwapt
+.It Sy Pxlookup_by_addr Ta Sy Pxlookup_by_addr_resolved
+.It Sy Pxlookup_by_name Ta Sy Pzonename
+.It Sy Pzonepath Ta Sy Pzoneroot Ta
.El
.Ss Thread interrogation and manipulation
The following routines obtain information about a thread and allow
diff --git a/usr/src/man/man3proc/Makefile b/usr/src/man/man3proc/Makefile
index 0984b68..e59e81f 100644
--- a/usr/src/man/man3proc/Makefile
+++ b/usr/src/man/man3proc/Makefile
@@ -12,12 +12,12 @@
#
# Copyright 2011, Richard Lowe
# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
-# Copyright 2015 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
include $(SRC)/Makefile.master
-MANSECT= 3proc
+MANSECT= 3proc
MANFILES= \
Lctlfd.3proc \
@@ -64,6 +64,7 @@
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
diff --git a/usr/src/man/man3proc/Paddr_to_ctf.3proc b/usr/src/man/man3proc/Paddr_to_ctf.3proc
index 5eb4183..0364940 100644
--- a/usr/src/man/man3proc/Paddr_to_ctf.3proc
+++ b/usr/src/man/man3proc/Paddr_to_ctf.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Paddr_to_loadobj.3proc b/usr/src/man/man3proc/Paddr_to_loadobj.3proc
index 6430d8e..54f129e 100644
--- a/usr/src/man/man3proc/Paddr_to_loadobj.3proc
+++ b/usr/src/man/man3proc/Paddr_to_loadobj.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Paddr_to_map.3proc b/usr/src/man/man3proc/Paddr_to_map.3proc
index d49067e..f9fcd6b 100644
--- a/usr/src/man/man3proc/Paddr_to_map.3proc
+++ b/usr/src/man/man3proc/Paddr_to_map.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pasfd.3proc b/usr/src/man/man3proc/Pasfd.3proc
index a5ae8a9..501d006 100644
--- a/usr/src/man/man3proc/Pasfd.3proc
+++ b/usr/src/man/man3proc/Pasfd.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pclearfault.3proc b/usr/src/man/man3proc/Pclearfault.3proc
index 0c1f7ed..744b43f 100644
--- a/usr/src/man/man3proc/Pclearfault.3proc
+++ b/usr/src/man/man3proc/Pclearfault.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pclearsig.3proc b/usr/src/man/man3proc/Pclearsig.3proc
index 577fcf9..23f81df 100644
--- a/usr/src/man/man3proc/Pclearsig.3proc
+++ b/usr/src/man/man3proc/Pclearsig.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pcontent.3proc b/usr/src/man/man3proc/Pcontent.3proc
index 27d9d67..5ea261d 100644
--- a/usr/src/man/man3proc/Pcontent.3proc
+++ b/usr/src/man/man3proc/Pcontent.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pcreate.3proc b/usr/src/man/man3proc/Pcreate.3proc
index 6185e60..94552a1 100644
--- a/usr/src/man/man3proc/Pcreate.3proc
+++ b/usr/src/man/man3proc/Pcreate.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pcreate_agent.3proc b/usr/src/man/man3proc/Pcreate_agent.3proc
index a421938..d492b38 100644
--- a/usr/src/man/man3proc/Pcreate_agent.3proc
+++ b/usr/src/man/man3proc/Pcreate_agent.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pcreate_error.3proc b/usr/src/man/man3proc/Pcreate_error.3proc
index 73a2538..647294e 100644
--- a/usr/src/man/man3proc/Pcreate_error.3proc
+++ b/usr/src/man/man3proc/Pcreate_error.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pcred.3proc b/usr/src/man/man3proc/Pcred.3proc
index bec0030..a71ea1c 100644
--- a/usr/src/man/man3proc/Pcred.3proc
+++ b/usr/src/man/man3proc/Pcred.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pctlfd.3proc b/usr/src/man/man3proc/Pctlfd.3proc
index 66679f5..7a51968 100644
--- a/usr/src/man/man3proc/Pctlfd.3proc
+++ b/usr/src/man/man3proc/Pctlfd.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pdelbkpt.3proc b/usr/src/man/man3proc/Pdelbkpt.3proc
index e00c5f7..15e04a8 100644
--- a/usr/src/man/man3proc/Pdelbkpt.3proc
+++ b/usr/src/man/man3proc/Pdelbkpt.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pdelwapt.3proc b/usr/src/man/man3proc/Pdelwapt.3proc
index 4a3d23d..38bd63c 100644
--- a/usr/src/man/man3proc/Pdelwapt.3proc
+++ b/usr/src/man/man3proc/Pdelwapt.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pdestroy_agent.3proc b/usr/src/man/man3proc/Pdestroy_agent.3proc
index 30c6772..9d683a9 100644
--- a/usr/src/man/man3proc/Pdestroy_agent.3proc
+++ b/usr/src/man/man3proc/Pdestroy_agent.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Penv_iter.3proc b/usr/src/man/man3proc/Penv_iter.3proc
index 8dc616e..658154d 100644
--- a/usr/src/man/man3proc/Penv_iter.3proc
+++ b/usr/src/man/man3proc/Penv_iter.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pexecname.3proc b/usr/src/man/man3proc/Pexecname.3proc
index f7560c7..e6c205a 100644
--- a/usr/src/man/man3proc/Pexecname.3proc
+++ b/usr/src/man/man3proc/Pexecname.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pfault.3proc b/usr/src/man/man3proc/Pfault.3proc
index 7c1d8ed..cb106a4 100644
--- a/usr/src/man/man3proc/Pfault.3proc
+++ b/usr/src/man/man3proc/Pfault.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pfdinfo_iter.3proc b/usr/src/man/man3proc/Pfdinfo_iter.3proc
index 055355e..cb03a77 100644
--- a/usr/src/man/man3proc/Pfdinfo_iter.3proc
+++ b/usr/src/man/man3proc/Pfdinfo_iter.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pgetareg.3proc b/usr/src/man/man3proc/Pgetareg.3proc
index 1904ea7..e141b87 100644
--- a/usr/src/man/man3proc/Pgetareg.3proc
+++ b/usr/src/man/man3proc/Pgetareg.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pgetauxval.3proc b/usr/src/man/man3proc/Pgetauxval.3proc
index 2d6122b..5a4abad 100644
--- a/usr/src/man/man3proc/Pgetauxval.3proc
+++ b/usr/src/man/man3proc/Pgetauxval.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pgetauxvec.3proc b/usr/src/man/man3proc/Pgetauxvec.3proc
index 348e01e..5880105 100644
--- a/usr/src/man/man3proc/Pgetauxvec.3proc
+++ b/usr/src/man/man3proc/Pgetauxvec.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pgetenv.3proc b/usr/src/man/man3proc/Pgetenv.3proc
index bb34119..b72eea5 100644
--- a/usr/src/man/man3proc/Pgetenv.3proc
+++ b/usr/src/man/man3proc/Pgetenv.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pgrab.3proc b/usr/src/man/man3proc/Pgrab.3proc
index a6df261..67109a8 100644
--- a/usr/src/man/man3proc/Pgrab.3proc
+++ b/usr/src/man/man3proc/Pgrab.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pgrab_core.3proc b/usr/src/man/man3proc/Pgrab_core.3proc
index 2b864bd..9cb0113 100644
--- a/usr/src/man/man3proc/Pgrab_core.3proc
+++ b/usr/src/man/man3proc/Pgrab_core.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pgrab_error.3proc b/usr/src/man/man3proc/Pgrab_error.3proc
index 01be5d1..0c22aaa 100644
--- a/usr/src/man/man3proc/Pgrab_error.3proc
+++ b/usr/src/man/man3proc/Pgrab_error.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pgrab_file.3proc b/usr/src/man/man3proc/Pgrab_file.3proc
index fa3e3b3..1db5929 100644
--- a/usr/src/man/man3proc/Pgrab_file.3proc
+++ b/usr/src/man/man3proc/Pgrab_file.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pisprocdir.3proc b/usr/src/man/man3proc/Pisprocdir.3proc
index 18aef39..74d9d15 100644
--- a/usr/src/man/man3proc/Pisprocdir.3proc
+++ b/usr/src/man/man3proc/Pisprocdir.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pissyscall.3proc b/usr/src/man/man3proc/Pissyscall.3proc
index 58b4d36..2628b1f 100644
--- a/usr/src/man/man3proc/Pissyscall.3proc
+++ b/usr/src/man/man3proc/Pissyscall.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pldt.3proc b/usr/src/man/man3proc/Pldt.3proc
index c39a0b6..e702875 100644
--- a/usr/src/man/man3proc/Pldt.3proc
+++ b/usr/src/man/man3proc/Pldt.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plmid.3proc b/usr/src/man/man3proc/Plmid.3proc
index ecb9a9a..fb54231 100644
--- a/usr/src/man/man3proc/Plmid.3proc
+++ b/usr/src/man/man3proc/Plmid.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plookup_by_addr.3proc b/usr/src/man/man3proc/Plookup_by_addr.3proc
index b848796..d1b1593 100644
--- a/usr/src/man/man3proc/Plookup_by_addr.3proc
+++ b/usr/src/man/man3proc/Plookup_by_addr.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plwp_getasrs.3proc b/usr/src/man/man3proc/Plwp_getasrs.3proc
index 85fa41e..ea0fa5d 100644
--- a/usr/src/man/man3proc/Plwp_getasrs.3proc
+++ b/usr/src/man/man3proc/Plwp_getasrs.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plwp_getname.3proc b/usr/src/man/man3proc/Plwp_getname.3proc
new file mode 100644
index 0000000..961cc52
--- /dev/null
+++ b/usr/src/man/man3proc/Plwp_getname.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plwp_getpsinfo.3proc b/usr/src/man/man3proc/Plwp_getpsinfo.3proc
index 4d7d64f..53b01ea 100644
--- a/usr/src/man/man3proc/Plwp_getpsinfo.3proc
+++ b/usr/src/man/man3proc/Plwp_getpsinfo.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plwp_getregs.3proc b/usr/src/man/man3proc/Plwp_getregs.3proc
index 5d4e776..e11f4f5 100644
--- a/usr/src/man/man3proc/Plwp_getregs.3proc
+++ b/usr/src/man/man3proc/Plwp_getregs.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plwp_getspymaster.3proc b/usr/src/man/man3proc/Plwp_getspymaster.3proc
index 8b7adbf..762485d 100644
--- a/usr/src/man/man3proc/Plwp_getspymaster.3proc
+++ b/usr/src/man/man3proc/Plwp_getspymaster.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plwp_getxregs.3proc b/usr/src/man/man3proc/Plwp_getxregs.3proc
index e1801ee..f1c191f 100644
--- a/usr/src/man/man3proc/Plwp_getxregs.3proc
+++ b/usr/src/man/man3proc/Plwp_getxregs.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plwp_iter.3proc b/usr/src/man/man3proc/Plwp_iter.3proc
index 15de2f1..487190b 100644
--- a/usr/src/man/man3proc/Plwp_iter.3proc
+++ b/usr/src/man/man3proc/Plwp_iter.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Plwp_stack.3proc b/usr/src/man/man3proc/Plwp_stack.3proc
index 2cf3303..77d8466 100644
--- a/usr/src/man/man3proc/Plwp_stack.3proc
+++ b/usr/src/man/man3proc/Plwp_stack.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pmapping_iter.3proc b/usr/src/man/man3proc/Pmapping_iter.3proc
index 7f2fb46..6d43906 100644
--- a/usr/src/man/man3proc/Pmapping_iter.3proc
+++ b/usr/src/man/man3proc/Pmapping_iter.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pobjname.3proc b/usr/src/man/man3proc/Pobjname.3proc
index 4b75abb..300d4fa 100644
--- a/usr/src/man/man3proc/Pobjname.3proc
+++ b/usr/src/man/man3proc/Pobjname.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pplatform.3proc b/usr/src/man/man3proc/Pplatform.3proc
index c17f9aa..82ff02b 100644
--- a/usr/src/man/man3proc/Pplatform.3proc
+++ b/usr/src/man/man3proc/Pplatform.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Ppltdest.3proc b/usr/src/man/man3proc/Ppltdest.3proc
index 56eea82f..98dd3e9 100644
--- a/usr/src/man/man3proc/Ppltdest.3proc
+++ b/usr/src/man/man3proc/Ppltdest.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Ppriv.3proc b/usr/src/man/man3proc/Ppriv.3proc
index f7adf48..7f698f4 100644
--- a/usr/src/man/man3proc/Ppriv.3proc
+++ b/usr/src/man/man3proc/Ppriv.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Ppsinfo.3proc b/usr/src/man/man3proc/Ppsinfo.3proc
index 7032494..f3151c1 100644
--- a/usr/src/man/man3proc/Ppsinfo.3proc
+++ b/usr/src/man/man3proc/Ppsinfo.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Prd_agent.3proc b/usr/src/man/man3proc/Prd_agent.3proc
index 1fdc63e..2de9dd3 100644
--- a/usr/src/man/man3proc/Prd_agent.3proc
+++ b/usr/src/man/man3proc/Prd_agent.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pread.3proc b/usr/src/man/man3proc/Pread.3proc
index 5a1e449..89c6cd1 100644
--- a/usr/src/man/man3proc/Pread.3proc
+++ b/usr/src/man/man3proc/Pread.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Prelease.3proc b/usr/src/man/man3proc/Prelease.3proc
index 3d66a0d..61fe282 100644
--- a/usr/src/man/man3proc/Prelease.3proc
+++ b/usr/src/man/man3proc/Prelease.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Preopen.3proc b/usr/src/man/man3proc/Preopen.3proc
index 088480a..01beb6c 100644
--- a/usr/src/man/man3proc/Preopen.3proc
+++ b/usr/src/man/man3proc/Preopen.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Preset_maps.3proc b/usr/src/man/man3proc/Preset_maps.3proc
index c842757..2e110af 100644
--- a/usr/src/man/man3proc/Preset_maps.3proc
+++ b/usr/src/man/man3proc/Preset_maps.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psecflags.3proc b/usr/src/man/man3proc/Psecflags.3proc
index 4f4b342..9eaf351 100644
--- a/usr/src/man/man3proc/Psecflags.3proc
+++ b/usr/src/man/man3proc/Psecflags.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetbkpt.3proc b/usr/src/man/man3proc/Psetbkpt.3proc
index 430063e..8ebdbe2 100644
--- a/usr/src/man/man3proc/Psetbkpt.3proc
+++ b/usr/src/man/man3proc/Psetbkpt.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetcred.3proc b/usr/src/man/man3proc/Psetcred.3proc
index afc0ce6..1586570 100644
--- a/usr/src/man/man3proc/Psetcred.3proc
+++ b/usr/src/man/man3proc/Psetcred.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetfault.3proc b/usr/src/man/man3proc/Psetfault.3proc
index 7cb467c..fff818b 100644
--- a/usr/src/man/man3proc/Psetfault.3proc
+++ b/usr/src/man/man3proc/Psetfault.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetflags.3proc b/usr/src/man/man3proc/Psetflags.3proc
index a911264..0affa7a 100644
--- a/usr/src/man/man3proc/Psetflags.3proc
+++ b/usr/src/man/man3proc/Psetflags.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetpriv.3proc b/usr/src/man/man3proc/Psetpriv.3proc
index 4d32728..bfaece0 100644
--- a/usr/src/man/man3proc/Psetpriv.3proc
+++ b/usr/src/man/man3proc/Psetpriv.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetrun.3proc b/usr/src/man/man3proc/Psetrun.3proc
index 68b6f92..b211791 100644
--- a/usr/src/man/man3proc/Psetrun.3proc
+++ b/usr/src/man/man3proc/Psetrun.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetsignal.3proc b/usr/src/man/man3proc/Psetsignal.3proc
index 58745ff..ae39020 100644
--- a/usr/src/man/man3proc/Psetsignal.3proc
+++ b/usr/src/man/man3proc/Psetsignal.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetsysentry.3proc b/usr/src/man/man3proc/Psetsysentry.3proc
index 4c7cce7..5367d3f 100644
--- a/usr/src/man/man3proc/Psetsysentry.3proc
+++ b/usr/src/man/man3proc/Psetsysentry.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetwapt.3proc b/usr/src/man/man3proc/Psetwapt.3proc
index 4ef992c..e119d90 100644
--- a/usr/src/man/man3proc/Psetwapt.3proc
+++ b/usr/src/man/man3proc/Psetwapt.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psetzoneid.3proc b/usr/src/man/man3proc/Psetzoneid.3proc
index 7a83fc5..ef25c5d 100644
--- a/usr/src/man/man3proc/Psetzoneid.3proc
+++ b/usr/src/man/man3proc/Psetzoneid.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psignal.3proc b/usr/src/man/man3proc/Psignal.3proc
index 1ff9009..b4f1fe0 100644
--- a/usr/src/man/man3proc/Psignal.3proc
+++ b/usr/src/man/man3proc/Psignal.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pstack_iter.3proc b/usr/src/man/man3proc/Pstack_iter.3proc
index bd3da0d..bcb116d 100644
--- a/usr/src/man/man3proc/Pstack_iter.3proc
+++ b/usr/src/man/man3proc/Pstack_iter.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pstate.3proc b/usr/src/man/man3proc/Pstate.3proc
index 9ec03c0..b91696c 100644
--- a/usr/src/man/man3proc/Pstate.3proc
+++ b/usr/src/man/man3proc/Pstate.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pstatus.3proc b/usr/src/man/man3proc/Pstatus.3proc
index 7a917ee..8f9b24d 100644
--- a/usr/src/man/man3proc/Pstatus.3proc
+++ b/usr/src/man/man3proc/Pstatus.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pstopstatus.3proc b/usr/src/man/man3proc/Pstopstatus.3proc
index 8ce88fb..15f9f41 100644
--- a/usr/src/man/man3proc/Pstopstatus.3proc
+++ b/usr/src/man/man3proc/Pstopstatus.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psymbol_iter.3proc b/usr/src/man/man3proc/Psymbol_iter.3proc
index 2378a19..69e893a 100644
--- a/usr/src/man/man3proc/Psymbol_iter.3proc
+++ b/usr/src/man/man3proc/Psymbol_iter.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psync.3proc b/usr/src/man/man3proc/Psync.3proc
index cc5637e..be7fa46 100644
--- a/usr/src/man/man3proc/Psync.3proc
+++ b/usr/src/man/man3proc/Psync.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Psysentry.3proc b/usr/src/man/man3proc/Psysentry.3proc
index fa7999e..ca0a923 100644
--- a/usr/src/man/man3proc/Psysentry.3proc
+++ b/usr/src/man/man3proc/Psysentry.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Puname.3proc b/usr/src/man/man3proc/Puname.3proc
index ba0779f..f6134de 100644
--- a/usr/src/man/man3proc/Puname.3proc
+++ b/usr/src/man/man3proc/Puname.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pupdate_maps.3proc b/usr/src/man/man3proc/Pupdate_maps.3proc
index 7fb482e..0f81eb3 100644
--- a/usr/src/man/man3proc/Pupdate_maps.3proc
+++ b/usr/src/man/man3proc/Pupdate_maps.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pupdate_syms.3proc b/usr/src/man/man3proc/Pupdate_syms.3proc
index 9e6e819..ee7fdb7 100644
--- a/usr/src/man/man3proc/Pupdate_syms.3proc
+++ b/usr/src/man/man3proc/Pupdate_syms.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pwrite.3proc b/usr/src/man/man3proc/Pwrite.3proc
index 411dbb8..a98f02c 100644
--- a/usr/src/man/man3proc/Pwrite.3proc
+++ b/usr/src/man/man3proc/Pwrite.3proc
@@ -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
diff --git a/usr/src/man/man3proc/Pzonename.3proc b/usr/src/man/man3proc/Pzonename.3proc
index 0dc78d5..828e107 100644
--- a/usr/src/man/man3proc/Pzonename.3proc
+++ b/usr/src/man/man3proc/Pzonename.3proc
@@ -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
diff --git a/usr/src/man/man4/proc.4 b/usr/src/man/man4/proc.4
index 59fd43f..61279bd 100644
--- a/usr/src/man/man4/proc.4
+++ b/usr/src/man/man4/proc.4
@@ -1,11 +1,11 @@
'\" te
.\" Copyright 1989 AT&T
.\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved.
-.\" Copyright (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
diff --git a/usr/src/pkg/manifests/system-dtrace-tests.mf b/usr/src/pkg/manifests/system-dtrace-tests.mf
index 4dee59e..a8f0f92 100644
--- a/usr/src/pkg/manifests/system-dtrace-tests.mf
+++ b/usr/src/pkg/manifests/system-dtrace-tests.mf
@@ -22,6 +22,7 @@
#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2018 Joyent, Inc.
#
set name=pkg.fmri value=pkg:/system/dtrace/tests@$(PKGVERS)
@@ -115,6 +116,7 @@
dir path=opt/SUNWdtrt/tst/common/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
diff --git a/usr/src/pkg/manifests/system-library.man3c.inc b/usr/src/pkg/manifests/system-library.man3c.inc
index 06f6fe8..846ed5b 100644
--- a/usr/src/pkg/manifests/system-library.man3c.inc
+++ b/usr/src/pkg/manifests/system-library.man3c.inc
@@ -303,6 +303,7 @@
file path=usr/share/man/man3c/pthread_attr_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
diff --git a/usr/src/pkg/manifests/system-library.man3proc.inc b/usr/src/pkg/manifests/system-library.man3proc.inc
index d7eeb3e..8528acc 100644
--- a/usr/src/pkg/manifests/system-library.man3proc.inc
+++ b/usr/src/pkg/manifests/system-library.man3proc.inc
@@ -10,7 +10,7 @@
#
#
-# Copyright 2015 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
file path=usr/share/man/man3proc/proc_service.3proc
@@ -81,6 +81,7 @@
file path=usr/share/man/man3proc/Plookup_by_addr.3proc
file path=usr/share/man/man3proc/Plwp_getasrs.3proc
file path=usr/share/man/man3proc/Plwp_getgwindows.3proc
+file path=usr/share/man/man3proc/Plwp_getname.3proc
file path=usr/share/man/man3proc/Plwp_getpsinfo.3proc
file path=usr/share/man/man3proc/Plwp_getregs.3proc
file path=usr/share/man/man3proc/Plwp_getspymaster.3proc
diff --git a/usr/src/pkg/manifests/system-test-libctest.mf b/usr/src/pkg/manifests/system-test-libctest.mf
index 135822a..f01471e 100644
--- a/usr/src/pkg/manifests/system-test-libctest.mf
+++ b/usr/src/pkg/manifests/system-test-libctest.mf
@@ -13,6 +13,7 @@
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright 2015 Garrett D'Amore <garrett@damore.org>
+# Copyright 2018 Joyent, Inc.
#
set name=pkg.fmri value=pkg:/system/test/libctest@$(PKGVERS)
@@ -158,6 +159,7 @@
file path=opt/libc-tests/tests/symbols/setup mode=0555
file path=opt/libc-tests/tests/symbols/symbols_test.$(ARCH) mode=0555
file path=opt/libc-tests/tests/symbols/symbols_test.$(ARCH64) mode=0555
+file path=opt/libc-tests/tests/thread_name mode=0555
file path=opt/libc-tests/tests/timespec_get.32 mode=0555
file path=opt/libc-tests/tests/timespec_get.64 mode=0555
file path=opt/libc-tests/tests/wcsncasecmp-7344.32 mode=0555
diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run
index 9c7e893..cde5a5f 100644
--- a/usr/src/test/libc-tests/runfiles/default.run
+++ b/usr/src/test/libc-tests/runfiles/default.run
@@ -12,7 +12,7 @@
#
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2014 Garrett D'Amore <garrett@damore.org>
-# Copyright 2017 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
[DEFAULT]
@@ -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]
diff --git a/usr/src/test/libc-tests/tests/threads/Makefile b/usr/src/test/libc-tests/tests/threads/Makefile
index 1e73e7b..31cb1dd 100644
--- a/usr/src/test/libc-tests/tests/threads/Makefile
+++ b/usr/src/test/libc-tests/tests/threads/Makefile
@@ -10,7 +10,7 @@
#
#
-# Copyright 2016 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
include $(SRC)/Makefile.master
@@ -18,7 +18,7 @@
ROOTOPTPKG = $(ROOT)/opt/libc-tests
TESTDIR = $(ROOTOPTPKG)/tests
-PROGS = pthread_attr_get_np
+PROGS = pthread_attr_get_np thread_name
include $(SRC)/cmd/Makefile.cmd
include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/libc-tests/tests/threads/thread_name.c b/usr/src/test/libc-tests/tests/threads/thread_name.c
new file mode 100644
index 0000000..b164272
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/threads/thread_name.c
@@ -0,0 +1,278 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
+/*
+ * Some basic pthread name API tests.
+ */
+
+#include <sys/stat.h>
+#include <pthread.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <thread.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <err.h>
+
+
+/*ARGSUSED*/
+static void *
+thr(void *unused)
+{
+ (void) sleep(100);
+ return (NULL);
+}
+
+/*ARGSUSED*/
+int
+main(int argc, char *argv[])
+{
+ char name[PTHREAD_MAX_NAMELEN_NP];
+ pthread_attr_t attr;
+ char path[PATH_MAX];
+ pthread_t tid;
+ ssize_t n;
+ int test;
+ int rc;
+ int fd;
+
+ /* Default thread name is empty string. */
+ test = 1;
+
+ rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* Can set name. */
+ test = 2;
+
+ (void) strlcpy(name, "main", sizeof (name));
+ rc = pthread_setname_np(pthread_self(), name);
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "main") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* ERANGE check. */
+ test = 3;
+
+ rc = pthread_getname_np(pthread_self(), name, 2);
+
+ if (rc != ERANGE)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* EINVAL check. */
+ test = 4;
+
+ rc = pthread_getname_np(pthread_self(), NULL, sizeof (name));
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* can clear thread name. */
+ test = 5;
+
+ rc = pthread_setname_np(pthread_self(), NULL);
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* non-existent thread check. */
+ test = 6;
+
+ rc = pthread_getname_np(808, name, sizeof (name));
+
+ if (rc != ESRCH)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_setname_np(808, "state");
+
+ if (rc != ESRCH)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* too long a name. */
+ test = 7;
+
+ rc = pthread_setname_np(pthread_self(),
+ "12345678901234567890123456789012");
+
+ if (rc != ERANGE)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* can name another thread. */
+ test = 8;
+
+ rc = pthread_create(&tid, NULL, thr, NULL);
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_setname_np(tid, "otherthread");
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* attr tests. */
+ test = 9;
+
+ (void) pthread_attr_init(&attr);
+
+ rc = pthread_attr_setname_np(&attr,
+ "12345678901234567890123456789012");
+
+ if (rc != ERANGE)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_setname_np(&attr, "thread2");
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_getname_np(&attr, NULL, sizeof (name));
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_getname_np(&attr, name, 2);
+
+ if (rc != ERANGE)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* does the attr actually apply? */
+ test = 10;
+
+ rc = pthread_create(&tid, &attr, thr, NULL);
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_getname_np(tid, name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "thread2") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* proc read tests */
+ test = 11;
+
+ (void) snprintf(path, sizeof (path),
+ "/proc/self/lwp/%d/lwpname", (int)tid);
+
+ fd = open(path, O_RDWR);
+
+ if (fd == -1)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = read(fd, name, sizeof (name));
+
+ if (n != sizeof (name) || strcmp(name, "thread2") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = read(fd, name, PTHREAD_MAX_NAMELEN_NP * 2);
+
+ if (n != sizeof (name) || strcmp(name, "thread2") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = read(fd, name, 4);
+
+ if (n != 4 || strncmp(name, "thre", 4) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* proc write tests */
+ test = 12;
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = write(fd, "1234567890123456789012345678901",
+ PTHREAD_MAX_NAMELEN_NP);
+
+ if (n != PTHREAD_MAX_NAMELEN_NP)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = write(fd, "foo", sizeof ("foo"));
+
+ if (n != sizeof ("foo"))
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ if (lseek(fd, 0, SEEK_SET) != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+ n = read(fd, name, sizeof (name));
+
+ if (n != sizeof (name) || strcmp(name, "foo") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ (void) close(fd);
+
+ /* thr_* API. */
+ test = 13;
+
+ rc = thr_setname(thr_self(), "main");
+
+ if (rc != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = thr_getname(thr_self(), name, sizeof (name));
+
+ if (rc != 0 || strcmp(name, "main") != 0)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ /* badness */
+ test = 14;
+
+ rc = thr_setname(thr_self(), "\033]0;messeduptitle\a");
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = thr_setname(thr_self(), "ab\177\177\n");
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_setname_np(&attr, "\033]0;messeduptitle\a");
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ rc = pthread_attr_setname_np(&attr, "ab\177\177\n");
+
+ if (rc != EINVAL)
+ errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+ return (EXIT_SUCCESS);
+}
diff --git a/usr/src/uts/common/disp/thread.c b/usr/src/uts/common/disp/thread.c
index f2685af..854b337 100644
--- a/usr/src/uts/common/disp/thread.c
+++ b/usr/src/uts/common/disp/thread.c
@@ -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.
@@ -2127,3 +2133,75 @@
}
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));
+}
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c
index b1685f4..6267faa 100644
--- a/usr/src/uts/common/dtrace/dtrace.c
+++ b/usr/src/uts/common/dtrace/dtrace.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
*/
@@ -3539,6 +3539,25 @@
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;
diff --git a/usr/src/uts/common/exec/elf/elf_notes.c b/usr/src/uts/common/exec/elf/elf_notes.c
index 4037507..fbc87fe 100644
--- a/usr/src/uts/common/exec/elf/elf_notes.c
+++ b/usr/src/uts/common/exec/elf/elf_notes.c
@@ -26,7 +26,7 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright (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.
diff --git a/usr/src/uts/common/fs/proc/prdata.h b/usr/src/uts/common/fs/proc/prdata.h
index 70daaf8..de816d4 100644
--- a/usr/src/uts/common/fs/proc/prdata.h
+++ b/usr/src/uts/common/fs/proc/prdata.h
@@ -27,7 +27,7 @@
/* All Rights Reserved */
/*
- * Copyright (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);
diff --git a/usr/src/uts/common/fs/proc/prvnops.c b/usr/src/uts/common/fs/proc/prvnops.c
index fdef53d..2cf007c 100644
--- a/usr/src/uts/common/fs/proc/prvnops.c
+++ b/usr/src/uts/common/fs/proc/prvnops.c
@@ -21,12 +21,12 @@
/*
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2018, Joyent, Inc.
* Copyright (c) 2017 by Delphix. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
+/* All Rights Reserved */
#include <sys/types.h>
#include <sys/param.h>
@@ -64,6 +64,7 @@
#include <sys/contract_impl.h>
#include <sys/ctfs.h>
#include <sys/avl.h>
+#include <sys/ctype.h>
#include <fs/fs_subr.h>
#include <vm/rm.h>
#include <vm/as.h>
@@ -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 */
diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h
index 44ca7d8..ab6d4c4 100644
--- a/usr/src/uts/common/sys/dtrace.h
+++ b/usr/src/uts/common/sys/dtrace.h
@@ -25,7 +25,7 @@
*/
/*
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -242,6 +242,7 @@
#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 */
diff --git a/usr/src/uts/common/sys/elf.h b/usr/src/uts/common/sys/elf.h
index ab768ef..4bd884e 100644
--- a/usr/src/uts/common/sys/elf.h
+++ b/usr/src/uts/common/sys/elf.h
@@ -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
diff --git a/usr/src/uts/common/sys/procfs.h b/usr/src/uts/common/sys/procfs.h
index 6bf2e4d..dfb54ea 100644
--- a/usr/src/uts/common/sys/procfs.h
+++ b/usr/src/uts/common/sys/procfs.h
@@ -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 {
diff --git a/usr/src/uts/common/sys/thread.h b/usr/src/uts/common/sys/thread.h
index d917944..f9f1d64 100644
--- a/usr/src/uts/common/sys/thread.h
+++ b/usr/src/uts/common/sys/thread.h
@@ -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