diff options
author | John Levon <john.levon@joyent.com> | 2018-10-08 15:34:11 +0100 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2018-10-19 16:40:54 -0400 |
commit | ab618543cc6fc4bc273c077ef5d247961cdb29d4 (patch) | |
tree | 24c80e35e958a4c5fef77d444eacb1b4f45798a2 | |
parent | 62f63298eba531d48f87aa8c2089298cb7821962 (diff) | |
download | illumos-joyent-ab618543cc6fc4bc273c077ef5d247961cdb29d4.tar.gz |
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>
156 files changed, 2258 insertions, 384 deletions
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 a5031e9950..c1995611e9 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 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) (void) pthread_attr_init(&attr); (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + (void) pthread_attr_setname_np(&attr, "db_restore"); err = pthread_create(&tid, &attr, ipmgmt_db_restore_thread, NULL); (void) pthread_attr_destroy(&attr); @@ -1124,7 +1126,7 @@ ipmgmt_aobjmap_init(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, { nvpair_t *nvp = NULL; char *name, *strval = NULL; - ipmgmt_aobjmap_t node; + ipmgmt_aobjmap_t node; struct sockaddr_in6 *in6; *errp = 0; diff --git a/usr/src/cmd/dtrace/test/tst/common/Makefile b/usr/src/cmd/dtrace/test/tst/common/Makefile index 808d0e4e8e..a29d774069 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 @@ sysevent/tst.post_chan.exe := LDLIBS += -lsysevent 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 0000000000..49d9f2155c --- /dev/null +++ b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.c @@ -0,0 +1,99 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2018 Joyent, Inc. + */ + +/* + * All we're doing is constantly modifying a thread name while DTrace is + * watching us, making sure we don't break. + */ + +#include <sys/fcntl.h> +#include <pthread.h> +#include <stdlib.h> +#include <stdio.h> + +#define NR_THREADS (100) +#define RUNTIME (30) /* seconds */ + +static void +random_ascii(char *buf, size_t bufsize) +{ + char table[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,.-#'?!"; + size_t len = rand() % bufsize; + + bzero(buf, bufsize); + + for (size_t i = 0; i < len; i++) { + buf[i] = table[rand() % (sizeof (table) - 1)]; + } +} + +static void +busy() +{ + struct timeval tv1; + struct timeval tv2; + + if (gettimeofday(&tv1, NULL) != 0) + abort(); + + for (;;) { + static volatile int i; + for (i = 0; i < 2000000; i++) + ; + + if (gettimeofday(&tv2, NULL) != 0) + abort(); + + /* janky, but we don't care */ + if (tv2.tv_sec != tv1.tv_sec) + return; + } +} + +static void * +thread(void *arg) +{ + char name[PTHREAD_MAX_NAMELEN_NP]; + + for (size_t i = 0; ; i++) { + random_ascii(name, sizeof (name)); + + if ((i % 100) == 0) { + if (pthread_setname_np(pthread_self(), NULL) != 0) + abort(); + } else { + (void) pthread_setname_np(pthread_self(), name); + } + + busy(); + } + + return (NULL); +} + +int +main(int argc, char **argv) +{ + pthread_t tids[NR_THREADS]; + + for (size_t i = 0; i < NR_THREADS; i++) { + if (pthread_create(&tids[i], NULL, thread, NULL) != 0) + exit(EXIT_FAILURE); + } + + sleep(RUNTIME); + exit(EXIT_SUCCESS); +} diff --git a/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d new file mode 100644 index 0000000000..289f6c5bbc --- /dev/null +++ b/usr/src/cmd/dtrace/test/tst/common/threadname/tst.threadname.d @@ -0,0 +1,26 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2018 Joyent, Inc. + */ + +#pragma D option quiet + +profile-10ms /pid == $1 && threadname == "unlikely"/ +{ + surprising++; +} + +syscall::rexit:entry /pid == $1/ +{ + exit(arg0); +} diff --git a/usr/src/cmd/halt/Makefile b/usr/src/cmd/halt/Makefile index 98d8eccee4..a515a0a1ef 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 @@ install := TARGET = install 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 85a15a1054..727851ffbc 100644 --- a/usr/src/cmd/ldapcachemgr/cachemgr_change.c +++ b/usr/src/cmd/ldapcachemgr/cachemgr_change.c @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2018 Joyent, Inc. */ #include <strings.h> @@ -33,6 +35,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <procfs.h> +#include <pthread.h> #include "cachemgr.h" extern admin_t current_admin; @@ -535,6 +538,8 @@ chg_cleanup_waiting_threads(void *arg) pid_t pid; int always = 1, waiting; + (void) pthread_setname_np(pthread_self(), "chg_cleanup_thr"); + if (op == NULL) { waiting = 1; type = CLEANUP_ALL; diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c b/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c index bb352ae7c4..6650c9c221 100644 --- a/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c +++ b/usr/src/cmd/ldapcachemgr/cachemgr_discovery.c @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2018 Joyent, Inc. */ #ifdef SLP @@ -539,9 +541,12 @@ done: * parameter 'r' should be a pointer to an unsigned int containing * the requested interval at which the network should be queried. */ -void discover(void *r) { +void +discover(void *r) { unsigned short reqrefresh = *((unsigned int *)r); + (void) pthread_setname_np(pthread_self(), "discover"); + for (;;) { find_all_contexts("ldap", __cache_get_cfghandle, diff --git a/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c b/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c index 298e61fcb0..b9bc3f77b6 100644 --- a/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c +++ b/usr/src/cmd/ldapcachemgr/cachemgr_getldap.c @@ -20,6 +20,8 @@ */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright 2018 Joyent, Inc. */ #include <assert.h> @@ -1631,6 +1633,8 @@ getldap_serverInfo_op(info_op_t op, char *input, char **output) static time_t prev_refresh = 0, next_refresh = 0; ns_server_status_t changed = 0; + (void) pthread_setname_np(pthread_self(), "getldap_serverinfo"); + if (current_admin.debug_level >= DBG_ALL) { logit("getldap_serverInfo_op()...\n"); } @@ -2542,6 +2546,8 @@ getldap_refresh() int sig_done = 0; int dbg_level; + (void) pthread_setname_np(pthread_self(), "getldap_refresh"); + if (current_admin.debug_level >= DBG_ALL) { logit("getldap_refresh()...\n"); } @@ -2892,6 +2898,8 @@ remove_server_thread(void *arg) int up; rm_svr_t rms; + (void) pthread_setname_np(pthread_self(), "remove_server"); + up = contact_server(addr); rms.addr = addr; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_proc.c b/usr/src/cmd/mdb/common/mdb/mdb_proc.c index 6c9f0aa5f4..33994c11e6 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_proc.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_proc.c @@ -1303,6 +1303,23 @@ pt_regstatus(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (pt_regs(addr, flags, argc, argv)); } +static void +pt_thread_name(mdb_tgt_t *t, mdb_tgt_tid_t tid, char *buf, size_t bufsize) +{ + char name[THREAD_NAME_MAX]; + + buf[0] = '\0'; + + if (t->t_pshandle == NULL || + Plwp_getname(t->t_pshandle, tid, name, sizeof (name)) != 0 || + name[0] == '\0') { + (void) mdb_snprintf(buf, bufsize, "%lu", tid); + return; + } + + (void) mdb_snprintf(buf, bufsize, "%lu [%s]", tid, name); +} + static int pt_findstack(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv) { @@ -1311,6 +1328,7 @@ pt_findstack(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv) int showargs = 0; int count; uintptr_t pc, sp; + char name[128]; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); @@ -1334,7 +1352,10 @@ pt_findstack(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv) #else sp = gregs.gregs[R_SP]; #endif - mdb_printf("stack pointer for thread %p: %p\n", tid, sp); + + pt_thread_name(t, tid, name, sizeof (name)); + + mdb_printf("stack pointer for thread %s: %p\n", name, sp); if (pc != 0) mdb_printf("[ %0?lr %a() ]\n", sp, pc); diff --git a/usr/src/cmd/mdb/common/modules/genunix/findstack.c b/usr/src/cmd/mdb/common/modules/genunix/findstack.c index 12b90b8f7d..fc8a4f874b 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/findstack.c +++ b/usr/src/cmd/mdb/common/modules/genunix/findstack.c @@ -22,6 +22,7 @@ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright 2018 Joyent, Inc. */ #include <mdb/mdb_modapi.h> @@ -38,6 +39,12 @@ #include "thread.h" #include "sobj.h" +/* + * Parts of this file are shared between targets, but this section is only + * used for KVM and KMDB. + */ +#ifdef _KERNEL + int findstack_debug_on = 0; /* @@ -48,6 +55,7 @@ print_stack(uintptr_t sp, uintptr_t pc, uintptr_t addr, int argc, const mdb_arg_t *argv, int free_state) { int showargs = 0, count, err; + char tdesc[128] = ""; count = mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &showargs, NULL); @@ -57,8 +65,10 @@ print_stack(uintptr_t sp, uintptr_t pc, uintptr_t addr, if (argc > 1 || (argc == 1 && argv->a_type != MDB_TYPE_STRING)) return (DCMD_USAGE); - mdb_printf("stack pointer for thread %p%s: %p\n", - addr, (free_state ? " (TS_FREE)" : ""), sp); + (void) thread_getdesc(addr, B_TRUE, tdesc, sizeof (tdesc)); + + mdb_printf("stack pointer for thread %p%s (%s): %p\n", + addr, (free_state ? " (TS_FREE)" : ""), tdesc, sp); if (pc != 0) mdb_printf("[ %0?lr %a() ]\n", sp, pc); @@ -108,6 +118,8 @@ findstack_debug(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *av) return (DCMD_OK); } +#endif /* _KERNEL */ + static void uppercase(char *p) { @@ -197,7 +209,7 @@ static stacks_entry_t **stacks_hash; static stacks_entry_t **stacks_array; static size_t stacks_array_size; -size_t +static size_t stacks_hash_entry(stacks_entry_t *sep) { size_t depth = sep->se_depth; @@ -224,7 +236,7 @@ stacks_hash_entry(stacks_entry_t *sep) * relative ordering, so we don't do the extra work of looking up symbols * for the stack addresses. */ -int +static int stacks_entry_comp_impl(stacks_entry_t *l, stacks_entry_t *r, uint_t forsort) { @@ -298,7 +310,7 @@ stacks_entry_comp_impl(stacks_entry_t *l, stacks_entry_t *r, return (0); } -int +static int stacks_entry_comp(const void *l_arg, const void *r_arg) { stacks_entry_t * const *lp = l_arg; @@ -368,7 +380,7 @@ stacks_cleanup(int force) } /*ARGSUSED*/ -int +static int stacks_thread_cb(uintptr_t addr, const void *ignored, void *cbarg) { stacks_info_t *sip = cbarg; @@ -421,7 +433,7 @@ stacks_thread_cb(uintptr_t addr, const void *ignored, void *cbarg) return (WALK_NEXT); } -int +static int stacks_run_tlist(mdb_pipe_t *tlist, stacks_info_t *si) { size_t idx; @@ -445,7 +457,7 @@ stacks_run_tlist(mdb_pipe_t *tlist, stacks_info_t *si) return (-1); } -int +static int stacks_run(int verbose, mdb_pipe_t *tlist) { stacks_info_t si; diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c index 425911d112..719206065b 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 @@ ps_threadprint(uintptr_t addr, const void *data, void *private) 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 @@ pflags(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) typedef struct mdb_ps_proc { char p_stat; - struct pid *p_pidp; - struct pid *p_pgidp; + struct pid *p_pidp; + struct pid *p_pgidp; struct cred *p_cred; struct sess *p_sessp; struct task *p_task; diff --git a/usr/src/cmd/mdb/common/modules/genunix/thread.c b/usr/src/cmd/mdb/common/modules/genunix/thread.c index 652e5af2d6..410f9973d8 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 @@ thread_help(void) } /* + * Return a string description of the thread, including the ID and the thread + * name. + * + * If ->t_name is NULL, and we're a system thread, we'll do a little more + * spelunking to find a useful string to return. + */ +int +thread_getdesc(uintptr_t addr, boolean_t include_comm, + char *buf, size_t bufsize) +{ + char name[THREAD_NAME_MAX] = ""; + kthread_t t; + proc_t p; + + bzero(buf, bufsize); + + if (mdb_vread(&t, sizeof (kthread_t), addr) == -1) { + mdb_warn("failed to read kthread_t at %p", addr); + return (-1); + } + + if (t.t_tid == 0) { + taskq_t tq; + + if (mdb_vread(&tq, sizeof (taskq_t), + (uintptr_t)t.t_taskq) == -1) + tq.tq_name[0] = '\0'; + + if (t.t_name != NULL) { + if (mdb_readstr(buf, bufsize, + (uintptr_t)t.t_name) == -1) { + mdb_warn("error reading thread name"); + } + } else if (tq.tq_name[0] != '\0') { + (void) mdb_snprintf(buf, bufsize, "tq:%s", tq.tq_name); + } else { + mdb_snprintf(buf, bufsize, "%a()", t.t_startpc); + } + + return (buf[0] == '\0' ? -1 : 0); + } + + if (include_comm && mdb_vread(&p, sizeof (proc_t), + (uintptr_t)t.t_procp) == -1) { + mdb_warn("failed to read proc at %p", t.t_procp); + return (-1); + } + + if (t.t_name != NULL) { + if (mdb_readstr(name, sizeof (name), (uintptr_t)t.t_name) == -1) + mdb_warn("error reading thread name"); + + /* + * Just to be safe -- if mdb_readstr() succeeds, it always NUL + * terminates the output, but is unclear what it does on + * failure. In that case we attempt to show any partial content + * w/ the warning in case it's useful, but explicitly + * NUL-terminate to be safe. + */ + buf[bufsize - 1] = '\0'; + } + + if (name[0] != '\0') { + if (include_comm) { + (void) mdb_snprintf(buf, bufsize, "%s/%u [%s]", + p.p_user.u_comm, t.t_tid, name); + } else { + (void) mdb_snprintf(buf, bufsize, "%u [%s]", + t.t_tid, name); + } + } else { + if (include_comm) { + (void) mdb_snprintf(buf, bufsize, "%s/%u", + p.p_user.u_comm, t.t_tid); + } else { + (void) mdb_snprintf(buf, bufsize, "%u", t.t_tid); + } + } + + return (buf[0] == '\0' ? -1 : 0); +} + +/* * List a combination of kthread_t and proc_t. Add stack traces in verbose mode. */ int @@ -571,8 +657,6 @@ threadlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) uint_t verbose = FALSE; uint_t notaskq = FALSE; kthread_t t; - taskq_t tq; - proc_t p; char cmd[80]; mdb_arg_t cmdarg; @@ -618,50 +702,32 @@ threadlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (t.t_state == TS_FREE) return (DCMD_OK); - if (mdb_vread(&p, sizeof (proc_t), (uintptr_t)t.t_procp) == -1) { - mdb_warn("failed to read proc at %p", t.t_procp); - return (DCMD_ERR); - } + if (!verbose) { + char desc[128]; + + if (thread_getdesc(addr, B_TRUE, desc, sizeof (desc)) == -1) + return (DCMD_ERR); - if (mdb_vread(&tq, sizeof (taskq_t), (uintptr_t)t.t_taskq) == -1) - tq.tq_name[0] = '\0'; + mdb_printf("%0?p %?p %?p %s\n", addr, t.t_procp, t.t_lwp, desc); + return (DCMD_OK); + } - if (verbose) { - mdb_printf("%0?p %?p %?p %3u %3d %?p\n", - addr, t.t_procp, t.t_lwp, t.t_cid, t.t_pri, t.t_wchan); + mdb_printf("%0?p %?p %?p %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", 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_printf("PC: %a\n", t.t_pc); - 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 @@ int stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { kthread_t t; - proc_t p; uint64_t *ptr; /* pattern pointer */ caddr_t start; /* kernel stack start */ caddr_t end; /* kernel stack end */ @@ -730,6 +795,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) int i = 0; unsigned int ukmem_stackinfo; uintptr_t allthreads; + char tdesc[128] = ""; /* handle options */ if (mdb_getopts(argc, argv, @@ -775,7 +841,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf("%<u>%?s%</u>", "THREAD"); mdb_printf(" %<u>%?s%</u>", "STACK"); - mdb_printf("%<u>%s%</u>", " SIZE MAX CMD/LWPID or STARTPC"); + mdb_printf("%<u>%s%</u>", " SIZE MAX LWP"); mdb_printf("\n"); usize = KMEM_STKINFO_LOG_SIZE * sizeof (kmem_stkinfo_t); log = (kmem_stkinfo_t *)mdb_alloc(usize, UM_SLEEP); @@ -798,18 +864,15 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (log[i].kthread == NULL) { continue; } - mdb_printf("%0?p %0?p %6x %3d%%", + + (void) thread_getdesc((uintptr_t)log[i].kthread, + B_TRUE, tdesc, sizeof (tdesc)); + + mdb_printf("%0?p %0?p %6x %3d%% %s\n", log[i].kthread, log[i].start, (uint_t)log[i].stksz, - (int)log[i].percent); - if (log[i].t_tid != 0) { - mdb_printf(" %s/%u\n", - log[i].cmd, log[i].t_tid); - } else { - mdb_printf(" %p (%a)\n", log[i].t_startpc, - log[i].t_startpc); - } + (int)log[i].percent, tdesc); } mdb_free((void *)log, usize); return (DCMD_OK); @@ -824,7 +887,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } mdb_printf("%<u>%?s%</u>", "THREAD"); mdb_printf(" %<u>%?s%</u>", "STACK"); - mdb_printf("%<u>%s%</u>", " SIZE CUR MAX CMD/LWPID"); + mdb_printf("%<u>%s%</u>", " SIZE CUR MAX LWP"); mdb_printf("\n"); } @@ -838,12 +901,6 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_OK); } - /* read proc */ - if (mdb_vread(&p, sizeof (proc_t), (uintptr_t)t.t_procp) == -1) { - mdb_warn("failed to read proc at %p\n", t.t_procp); - return (DCMD_ERR); - } - /* * Stack grows up or down, see thread_create(), * compute stack memory aera start and end (start < end). @@ -878,14 +935,10 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf(" %3d%%", percent); percent = 0; + (void) thread_getdesc(addr, B_TRUE, tdesc, sizeof (tdesc)); + if (ukmem_stackinfo == 0) { - mdb_printf(" n/a"); - if (t.t_tid == 0) { - mdb_printf(" %a()", t.t_startpc); - } else { - mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid); - } - mdb_printf("\n"); + mdb_printf(" n/a %s\n", tdesc); return (DCMD_OK); } @@ -958,12 +1011,9 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } else { mdb_printf(" n/a"); } - if (t.t_tid == 0) { - mdb_printf(" %a()", t.t_startpc); - } else { - mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid); - } - mdb_printf("\n"); + + mdb_printf(" %s\n", tdesc); + mdb_free((void *)ustack, usize + 8); return (DCMD_OK); } @@ -978,7 +1028,7 @@ stackinfo_help(void) "(an unsigned integer) is non zero at kthread creation time. "); mdb_printf("For example:\n"); mdb_printf( - " THREAD STACK SIZE CUR MAX CMD/LWPID\n"); + " THREAD STACK SIZE CUR MAX LWP\n"); mdb_printf( "ffffff014f5f2c20 ffffff0004153000 4f00 4%% 43%% init/1\n"); mdb_printf( @@ -1002,6 +1052,6 @@ stackinfo_help(void) "-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 18952fdc0a..901d962be8 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 @@ void thread_state_to_text(uint_t, char *, size_t); int thread_text_to_state(const char *, uint_t *); void thread_walk_states(void (*)(uint_t, const char *, void *), void *); +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 2ffb95c30d..288c6e767e 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 @@ init_cache_ctx(int i) { 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 @@ static void 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 @@ nsc_invalidate(nsc_ctx_t *ctx, char *dbname, nsc_ctx_t **ctxs) static void ctx_invalidate(nsc_ctx_t *ctx) { - int i; + int i; nsc_entry_t *entry; char *me = "ctx_invalidate"; @@ -2190,6 +2195,8 @@ reaper(nsc_ctx_t *ctx) 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 7ed5e71bca..134da3f280 100644 --- a/usr/src/cmd/nscd/nscd_frontend.c +++ b/usr/src/cmd/nscd/nscd_frontend.c @@ -22,6 +22,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. + * Copyright 2018 Joyent, Inc. */ #include <stdlib.h> @@ -89,6 +90,8 @@ server_tsd_bind(void *arg) { static void *value = 0; + (void) 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 @@ server_destroy(void *arg) * get clearance */ int -_nscd_get_clearance(sema_t *sema) { +_nscd_get_clearance(sema_t *sema) +{ if (sema_trywait(&common_sema) == 0) { (void) thr_setspecific(lookup_state_key, NULL); return (0); @@ -151,7 +155,8 @@ _nscd_get_clearance(sema_t *sema) { * release clearance */ int -_nscd_release_clearance(sema_t *sema) { +_nscd_release_clearance(sema_t *sema) +{ int which; (void) thr_getspecific(lookup_state_key, (void**)&which); @@ -197,7 +202,7 @@ _nscd_restart_if_cfgfile_changed() static timestruc_t last_nsswitch_modified = { 0 }; static timestruc_t last_resolv_modified = { -1, 0 }; static mutex_t restarting_lock = DEFAULTMUTEX; - static int restarting = 0; + static int restarting = 0; int restart = 0; time_t now = time(NULL); char *me = "_nscd_restart_if_cfgfile_changed"; @@ -1477,6 +1482,8 @@ rts_mon(void) struct ifa_msghdr *ifam = &mbuf.ifam; char *me = "rts_mon"; + (void) 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 2fed9a5c82..f4e6b89fbc 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 @@ reclaim_getent_ctx(void *arg) nss_getent_t nssctx = { 0 }; char *me = "reclaim_getent_ctx"; + (void) thr_setname(thr_self(), me); + /*CONSTCOND*/ while (1) { @@ -744,7 +748,8 @@ reclaim_getent_ctx(void *arg) } static nscd_rc_t -_nscd_init_getent_ctx_monitor() { +_nscd_init_getent_ctx_monitor() +{ int errnum; char *me = "_nscd_init_getent_ctx_monitor"; @@ -763,7 +768,7 @@ _nscd_init_getent_ctx_monitor() { * start a thread to reclaim unused getent contexts */ if (thr_create(NULL, NULL, reclaim_getent_ctx, - NULL, THR_DETACHED, NULL) != 0) { + NULL, THR_DETACHED, NULL) != 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR) (me, "thr_create: %s\n", strerror(errnum)); diff --git a/usr/src/cmd/nscd/nscd_selfcred.c b/usr/src/cmd/nscd/nscd_selfcred.c index df4d2a2c5b..b6cdba8c7a 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 @@ forker_monitor( 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 @@ check_uid(char *pid_name) static uid_t uid = 0; static uid_t euid = 0; int pfd; /* file descriptor for /proc/<pid>/psinfo */ - psinfo_t info; /* process information from /proc */ + psinfo_t info; /* process information from /proc */ if (uid == 0) { pid = getpid(); @@ -1466,6 +1469,8 @@ check_user_process(void *arg) 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 bd2ff958ba..c5d5731ecd 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 @@ set_smf_state(void *arg) 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 e317483142..96c1450b26 100644 --- a/usr/src/cmd/prstat/Makefile.com +++ b/usr/src/cmd/prstat/Makefile.com @@ -21,6 +21,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2018, Joyent, Inc. # # cmd/prstat/Makefile.com # @@ -31,6 +32,7 @@ SRCS = $(OBJS:%.o=../%.c) include ../../Makefile.cmd +CSTD = $(CSTD_GNU99) CFLAGS += $(CCVERBOSE) CERRWARN += -_gcc=-Wno-parentheses LDLIBS += -lcurses -lproject diff --git a/usr/src/cmd/prstat/prstat.c b/usr/src/cmd/prstat/prstat.c index fc16e435f6..0ff4f51bcd 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 prj_tbl = {0, 0, NULL}; /* selected projects */ static table_t tsk_tbl = {0, 0, NULL}; /* selected tasks */ static table_t lgr_tbl = {0, 0, NULL}; /* selected lgroups */ static zonetbl_t zone_tbl = {0, 0, NULL}; /* selected zones */ -static uidtbl_t euid_tbl = {0, 0, NULL}; /* selected effective users */ -static uidtbl_t ruid_tbl = {0, 0, NULL}; /* selected real users */ +static uidtbl_t euid_tbl = {0, 0, NULL}; /* selected effective users */ +static uidtbl_t ruid_tbl = {0, 0, NULL}; /* selected real users */ static uint_t total_procs; /* total number of procs */ static uint_t total_lwps; /* total number of lwps */ @@ -172,7 +173,7 @@ static long pagesize; /* default settings */ -static optdesc_t opts = { +optdesc_t opts = { 5, /* interval between updates, seconds */ 15, /* number of lines in top part */ 5, /* number of lines in bottom part */ @@ -361,11 +362,12 @@ list_print(list_t *list) char psize[6], prssize[6], pmem[6], pcpu[6], ptime[12]; char pstate[7], pnice[4], ppri[4]; char pname[LOGNAME_MAX+1]; + char name[PRFNSZ + THREAD_NAME_MAX + 2]; char projname[PROJNAME_MAX+1]; char zonename[ZONENAME_MAX+1]; float cpu, mem; double loadavg[3] = {0, 0, 0}; - int i, lwpid; + int i, n; if (list->l_size == 0) return; @@ -385,54 +387,59 @@ list_print(list_t *list) (void) putchar('\r'); (void) putp(t_ulon); + n = opts.o_cols; switch (list->l_type) { case LT_PROJECTS: if (opts.o_outpmode & OPT_LWPS) - (void) printf(PROJECT_HEADER_LWP); + n = printf(PROJECT_HEADER_LWP); else - (void) printf(PROJECT_HEADER_PROC); + n = printf(PROJECT_HEADER_PROC); break; case LT_TASKS: if (opts.o_outpmode & OPT_LWPS) - (void) printf(TASK_HEADER_LWP); + n = printf(TASK_HEADER_LWP); else - (void) printf(TASK_HEADER_PROC); + n = printf(TASK_HEADER_PROC); break; case LT_ZONES: if (opts.o_outpmode & OPT_LWPS) - (void) printf(ZONE_HEADER_LWP); + n = printf(ZONE_HEADER_LWP); else - (void) printf(ZONE_HEADER_PROC); + n = printf(ZONE_HEADER_PROC); break; case LT_USERS: if (opts.o_outpmode & OPT_LWPS) - (void) printf(USER_HEADER_LWP); + n = printf(USER_HEADER_LWP); else - (void) printf(USER_HEADER_PROC); + n = printf(USER_HEADER_PROC); break; case LT_LWPS: if (opts.o_outpmode & OPT_LWPS) { if (opts.o_outpmode & OPT_PSINFO) { if (opts.o_outpmode & OPT_LGRP) - (void) printf(PSINFO_HEADER_LWP_LGRP); + n = printf(PSINFO_HEADER_LWP_LGRP); else - (void) printf(PSINFO_HEADER_LWP); + n = printf(PSINFO_HEADER_LWP); } if (opts.o_outpmode & OPT_MSACCT) - (void) printf(USAGE_HEADER_LWP); + n = printf(USAGE_HEADER_LWP); } else { if (opts.o_outpmode & OPT_PSINFO) { if (opts.o_outpmode & OPT_LGRP) - (void) printf(PSINFO_HEADER_PROC_LGRP); + n = printf(PSINFO_HEADER_PROC_LGRP); else - (void) printf(PSINFO_HEADER_PROC); + n = printf(PSINFO_HEADER_PROC); } if (opts.o_outpmode & OPT_MSACCT) - (void) printf(USAGE_HEADER_PROC); + n = printf(USAGE_HEADER_PROC); } break; } + /* Pad out the header line so the underline spans the whole width */ + if ((opts.o_outpmode & OPT_TERMCAP) && n < opts.o_cols) + (void) printf("%*s", (int)(opts.o_cols - n), ""); + (void) putp(t_uloff); (void) putp(t_eol); (void) putchar('\n'); @@ -499,15 +506,14 @@ list_print(list_t *list) break; case LT_LWPS: lwp = list->l_ptrs[i]; - if (opts.o_outpmode & OPT_LWPS) - lwpid = lwp->li_info.pr_lwp.pr_lwpid; - else - lwpid = lwp->li_info.pr_nlwp + - lwp->li_info.pr_nzomb; + + format_name(lwp, name, sizeof (name)); + pwd_getname(lwp->li_info.pr_uid, pname, sizeof (pname), opts.o_outpmode & OPT_NORESOLVE, opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC), LOGIN_WIDTH); + if (opts.o_outpmode & OPT_PSINFO) { Format_size(psize, lwp->li_info.pr_size, 6); Format_size(prssize, lwp->li_info.pr_rssize, 6); @@ -536,21 +542,17 @@ list_print(list_t *list) lwp->li_info.pr_time.tv_sec, 10); if (opts.o_outpmode & OPT_TTY) (void) putchar('\r'); - stripfname(lwp->li_info.pr_fname); if (opts.o_outpmode & OPT_LGRP) { (void) printf(PSINFO_LINE_LGRP, (int)lwp->li_info.pr_pid, pname, psize, prssize, pstate, ppri, pnice, ptime, pcpu, - (int)lwp->li_info.pr_lwp.pr_lgrp, - lwp->li_info.pr_fname, lwpid); + lwp->li_info.pr_lwp.pr_lgrp, name); } else { (void) printf(PSINFO_LINE, (int)lwp->li_info.pr_pid, pname, - psize, prssize, - pstate, ppri, pnice, - ptime, pcpu, - lwp->li_info.pr_fname, lwpid); + psize, prssize, pstate, ppri, pnice, + ptime, pcpu, name); } (void) putp(t_eol); (void) putchar('\n'); @@ -570,12 +572,11 @@ list_print(list_t *list) Format_pct(lat, lwp->li_lat, 4); if (opts.o_outpmode & OPT_TTY) (void) putchar('\r'); - stripfname(lwp->li_info.pr_fname); (void) printf(USAGE_LINE, (int)lwp->li_info.pr_pid, pname, usr, sys, trp, tfl, dfl, lck, slp, lat, vcx, icx, scl, sig, - lwp->li_info.pr_fname, lwpid); + name); (void) putp(t_eol); (void) putchar('\n'); } @@ -877,6 +878,27 @@ add_proc(psinfo_t *psinfo) } static void +get_lwpname(pid_t pid, id_t lwpid, char *buf, size_t bufsize) +{ + char *path = NULL; + int fd; + + buf[0] = '\0'; + + if (asprintf(&path, "/proc/%d/lwp/%d/lwpname", + (int)pid, (int)lwpid) == -1) + return; + + if ((fd = open(path, O_RDONLY)) != -1) { + (void) read(fd, buf, bufsize); + buf[bufsize - 1] = '\0'; + (void) close(fd); + } + + free(path); +} + +static void add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags) { lwp_info_t *lwp; @@ -891,6 +913,7 @@ add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags) (void) memcpy(&lwp->li_info, psinfo, sizeof (psinfo_t) - sizeof (lwpsinfo_t)); (void) memcpy(&lwp->li_info.pr_lwp, lwpsinfo, sizeof (lwpsinfo_t)); + get_lwpname(pid, lwpid, lwp->li_lwpname, sizeof (lwp->li_lwpname)); } static void @@ -1113,7 +1136,7 @@ list_refresh(list_t *list) } static void -curses_on() +curses_on(void) { if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) { (void) initscr(); @@ -1124,7 +1147,7 @@ curses_on() } 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 @@ curses_off() } static int -nlines() +nlines(int *linesp, int *colsp) { struct winsize ws; char *envp; int n; + + *linesp = -1; + *colsp = -1; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) { if (ws.ws_row > 0) - return (ws.ws_row); + *linesp = ws.ws_row; + if (ws.ws_col > 0) + *colsp = ws.ws_col; + if (ws.ws_row > 0 && ws.ws_col > 0) + return (0); } - if (envp = getenv("LINES")) { + + if ((envp = getenv("LINES")) != NULL) { if ((n = Atoi(envp)) > 0) { opts.o_outpmode &= ~OPT_USEHOME; - return (n); + *linesp = n; + } + } + if ((envp = getenv("COLUMNS")) != NULL) { + if ((n = Atoi(envp)) > 0) { + *colsp = n; } } - return (-1); + + return ((*linesp > 0 && *colsp > 0) ? 0 : -1); } static void -setmovecur() +setmovecur(void) { int i, n; if ((opts.o_outpmode & OPT_FULLSCREEN) && @@ -1184,17 +1221,19 @@ setmovecur() } static int -setsize() +setsize(void) { static int oldn = 0; - int n; + int cols, n, ret; if (opts.o_outpmode & OPT_FULLSCREEN) { - n = nlines(); + ret = nlines(&n, &cols); + if (ret != -1) + opts.o_cols = cols; if (n == oldn) return (0); oldn = n; - if (n == -1) { + if (ret == -1) { opts.o_outpmode &= ~OPT_USEHOME; setmovecur(); /* set default window size */ return (1); diff --git a/usr/src/cmd/prstat/prstat.h b/usr/src/cmd/prstat/prstat.h index 293123c5b9..e205a98bd2 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 @@ typedef struct lwp_info { ulong_t li_icx; /* involuntary context switches */ ulong_t li_scl; /* system calls */ ulong_t li_sig; /* received signals */ + char li_lwpname[THREAD_NAME_MAX]; struct lwp_info *li_next; /* pointer to next lwp */ struct lwp_info *li_prev; /* pointer to previous lwp */ } lwp_info_t; @@ -167,8 +169,11 @@ typedef struct optdesc { int o_count; /* number of iterations */ int o_outpmode; /* selected output mode */ int o_sortorder; /* +1 ascending, -1 descending */ + int o_cols; /* number of columns */ } optdesc_t; +extern optdesc_t opts; + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/prstat/prutil.c b/usr/src/cmd/prstat/prutil.c index 0f9cbd6c4d..551c72cc8a 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 @@ getzonename(zoneid_t zoneid, char *str, size_t len, int trunc, size_t width) /* * Remove all unprintable characters from process name */ -void -stripfname(char *buf) +static void +stripfname(char *buf, size_t bufsize, const char *pname) { int bytesleft = PRFNSZ; wchar_t wchar; int length; char *cp; + (void) strlcpy(buf, pname, bufsize); + buf[bytesleft - 1] = '\0'; for (cp = buf; *cp != '\0'; cp += length) { @@ -351,3 +354,71 @@ stripfname(char *buf) bytesleft -= length; } } + + +/* + * prstat has always implicitly wanted a terminal width of at least 80 columns + * (when a TTY is present). If run in a terminal narrower than 80 columns, + * prstat output may wrap. For wider terminals, we allow the last column to use + * the additional space. + * + * We never truncate if using -c, or not outputting to a TTY. + */ +static int +format_namewidth(void) +{ + int prefixlen = 0; + + if (opts.o_cols == 0 || !(opts.o_outpmode & (OPT_TERMCAP | OPT_TRUNC))) + return (0); + + if (opts.o_outpmode & OPT_PSINFO) { + if (opts.o_outpmode & OPT_LGRP) + prefixlen = 64; + else + prefixlen = 59; + } else if (opts.o_outpmode & OPT_MSACCT) { + prefixlen = 64; + } + + return (opts.o_cols - prefixlen); +} + +void +format_name(lwp_info_t *lwp, char *buf, size_t buflen) +{ + int pname_width = PRFNSZ; + char nr_suffix[20]; + char pname[PRFNSZ]; + int width; + int n; + + stripfname(pname, sizeof (pname), lwp->li_info.pr_fname); + + if (opts.o_outpmode & OPT_LWPS) { + n = snprintf(nr_suffix, sizeof (nr_suffix), "%d", + lwp->li_info.pr_lwp.pr_lwpid); + } else { + n = snprintf(nr_suffix, sizeof (nr_suffix), "%d", + lwp->li_info.pr_nlwp + lwp->li_info.pr_nzomb); + } + + width = format_namewidth(); + + /* If we're over budget, truncate the process name not the LWP part. */ + if (strlen(pname) > (width - n - 1)) { + pname_width = width - n - 1; + pname[pname_width - 1] = '*'; + } + + if ((opts.o_outpmode & OPT_LWPS) && lwp->li_lwpname[0] != '\0') { + n = snprintf(buf, buflen, "%.*s/%s [%s]", pname_width, + pname, nr_suffix, lwp->li_lwpname); + } else { + n = snprintf(buf, buflen, "%.*s/%s", pname_width, + pname, nr_suffix); + } + + if (width > 0 && strlen(buf) > width) + buf[width] = '\0'; +} diff --git a/usr/src/cmd/prstat/prutil.h b/usr/src/cmd/prstat/prutil.h index cfa2133714..ae2dbe5a93 100644 --- a/usr/src/cmd/prstat/prutil.h +++ b/usr/src/cmd/prstat/prutil.h @@ -25,6 +25,7 @@ * Use is subject to license terms. * * Portions Copyright 2009 Chad Mynhier + * Copyright 2018, Joyent, Inc. */ #ifndef _PRUTIL_H @@ -54,7 +55,7 @@ extern int Setrlimit(); extern void Priocntl(char *); extern void getprojname(projid_t, char *, size_t, int, int, size_t); extern void getzonename(projid_t, char *, size_t, int, size_t); -extern void stripfname(char *); +extern void format_name(lwp_info_t *, char *, size_t); #ifdef __cplusplus } diff --git a/usr/src/cmd/ps/ps.c b/usr/src/cmd/ps/ps.c index 78dabbccfe..1a3e91689a 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 @@ enum fname { /* enumeration of field names */ F_SID, /* session id */ F_PSR, /* bound processor */ F_LWP, /* lwp-id */ + F_LWPNAME, /* lwp name */ F_NLWP, /* number of lwps */ F_OPRI, /* old priority (obsolete) */ F_PRI, /* new priority */ @@ -177,6 +178,7 @@ static struct def_field fname[] = { { "sid", "SID", 5, 5 }, { "psr", "PSR", 3, 2 }, { "lwp", "LWP", 6, 2 }, + { "lwpname", "LWPNAME", 32, 8 }, { "nlwp", "NLWP", 4, 2 }, { "opri", "PRI", 3, 2 }, { "pri", "PRI", 3, 2 }, @@ -211,8 +213,8 @@ static struct def_field fname[] = { { "zone", "ZONE", 8, 8 }, { "zoneid", "ZONEID", 5, 5 }, { "ctid", "CTID", 5, 5 }, - { "lgrp", "LGRP", 4, 2 }, - { "dmodel", "DMODEL", 6, 6 }, + { "lgrp", "LGRP", 4, 2 }, + { "dmodel", "DMODEL", 6, 6 }, }; #define NFIELDS (sizeof (fname) / sizeof (fname[0])) @@ -803,6 +805,7 @@ stdmain(int argc, char **argv) (void) printf("%-*s", f->width, f->header); break; + case F_LWPNAME: case F_FNAME: case F_COMM: case F_ARGS: @@ -1178,7 +1181,8 @@ parse_format(char *arg) } for (df = &fname[0]; df < &fname[NFIELDS]; df++) if (strcmp(name, df->fname) == 0) { - if (strcmp(name, "lwp") == 0) + if (strcmp(name, "lwp") == 0 || + strcmp(name, "lwpname") == 0) Lflg++; break; } @@ -1754,6 +1758,27 @@ print_field(psinfo_t *psinfo, struct field *f, const char *ttyp) case F_LWP: (void) printf("%*d", width, (int)psinfo->pr_lwp.pr_lwpid); break; + case F_LWPNAME: { + char lwpname[THREAD_NAME_MAX] = ""; + char *path = NULL; + int fd; + + if (asprintf(&path, "%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 @@ print_zombie_field(psinfo_t *psinfo, struct field *f, const char *ttyp) 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 @@ przom(psinfo_t *psinfo) } if (fflg) { int width = fname[F_STIME].width; - (void) printf(" %*.*s", width, width, "-"); /* STIME */ + (void) printf(" %*.*s", width, width, "-"); /* STIME */ } (void) printf(" %-8.14s", "?"); /* TTY */ @@ -2447,9 +2472,9 @@ delta_secs(const timestruc_t *start) /* * Returns the following: * - * 0 No error - * EINVAL Invalid number - * ERANGE Value exceeds (min, max) range + * 0 No error + * EINVAL Invalid number + * ERANGE Value exceeds (min, max) range */ static int str2id(const char *p, pid_t *val, long min, long max) @@ -2484,9 +2509,9 @@ str2id(const char *p, pid_t *val, long min, long max) /* * Returns the following: * - * 0 No error - * EINVAL Invalid number - * ERANGE Value exceeds (min, max) range + * 0 No error + * EINVAL Invalid number + * ERANGE Value exceeds (min, max) range */ static int str2uid(const char *p, uid_t *val, unsigned long min, unsigned long max) diff --git a/usr/src/cmd/ptools/pstack/pstack.c b/usr/src/cmd/ptools/pstack/pstack.c index 0515ff62d0..d1d55d2280 100644 --- a/usr/src/cmd/ptools/pstack/pstack.c +++ b/usr/src/cmd/ptools/pstack/pstack.c @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2018 Joyent, Inc. */ #include <sys/isa_defs.h> @@ -137,7 +139,7 @@ static int thr_stack(const td_thrhandle_t *, void *); static void free_threadinfo(void); static struct threadinfo *find_thread(id_t); static int all_call_stacks(pstack_handle_t *, int); -static void tlhead(id_t, id_t); +static void tlhead(id_t, id_t, const char *); static int print_frame(void *, prgregset_t, uint_t, const long *); static void print_zombie(struct ps_prochandle *, struct threadinfo *); static void print_syscall(const lwpstatus_t *, prgregset_t); @@ -380,6 +382,7 @@ static int thread_call_stack(void *data, const lwpstatus_t *psp, const lwpsinfo_t *pip) { + char lwpname[THREAD_NAME_MAX] = ""; pstack_handle_t *h = data; lwpstatus_t lwpstatus; struct threadinfo *tip; @@ -391,7 +394,10 @@ thread_call_stack(void *data, const lwpstatus_t *psp, if ((tip = find_thread(pip->pr_lwpid)) == NULL) return (0); - tlhead(tip->threadid, pip->pr_lwpid); + (void) Plwp_getname(h->proc, pip->pr_lwpid, + lwpname, sizeof (lwpname)); + + tlhead(tip->threadid, pip->pr_lwpid, lwpname); tip->threadid = 0; /* finish eliminating tid */ if (psp) call_stack(h, psp); @@ -410,15 +416,19 @@ thread_call_stack(void *data, const lwpstatus_t *psp, static int lwp_call_stack(void *data, - const lwpstatus_t *psp, const lwpsinfo_t *pip) + const lwpstatus_t *psp, const lwpsinfo_t *pip) { + char lwpname[THREAD_NAME_MAX] = ""; pstack_handle_t *h = data; if (!proc_lwp_in_set(h->lwps, pip->pr_lwpid)) return (0); h->count++; - tlhead(0, pip->pr_lwpid); + (void) Plwp_getname(h->proc, pip->pr_lwpid, + lwpname, sizeof (lwpname)); + + tlhead(0, pip->pr_lwpid, lwpname); if (psp) call_stack(h, psp); else @@ -462,7 +472,7 @@ all_call_stacks(pstack_handle_t *h, int dothreads) if ((tid = tip->threadid) != 0) { (void) memcpy(lwpstatus.pr_reg, tip->regs, sizeof (prgregset_t)); - tlhead(tid, tip->lwpid); + tlhead(tid, tip->lwpid, NULL); if (tip->state == TD_THR_ZOMBIE) print_zombie(Pr, tip); else @@ -475,23 +485,49 @@ all_call_stacks(pstack_handle_t *h, int dothreads) return (0); } +/* The width of the header */ +#define HEAD_WIDTH (62) static void -tlhead(id_t threadid, id_t lwpid) +tlhead(id_t threadid, id_t lwpid, const char *name) { + char buf[128] = { 0 }; + char num[16]; + ssize_t amt = 0; + int i; + if (threadid == 0 && lwpid == 0) return; - (void) printf("-----------------"); + if (lwpid > 0) { + (void) snprintf(num, sizeof (num), "%d", (int)lwpid); + (void) strlcat(buf, "thread# ", sizeof (buf)); + (void) strlcat(buf, num, sizeof (buf)); + } + + if (threadid > 0) { + (void) snprintf(num, sizeof (num), "%d", (int)threadid); + if (lwpid > 0) + (void) strlcat(buf, " / ", sizeof (buf)); + (void) strlcat(buf, "lwp# ", sizeof (buf)); + (void) strlcat(buf, num, sizeof (buf)); + } + + if (name != NULL && strlen(name) > 0) { + (void) strlcat(buf, " [", sizeof (buf)); + (void) strlcat(buf, name, sizeof (buf)); + (void) strlcat(buf, "]", sizeof (buf)); + } - if (threadid && lwpid) - (void) printf(" lwp# %d / thread# %d ", - (int)lwpid, (int)threadid); - else if (threadid) - (void) printf("--------- thread# %d ", (int)threadid); - else if (lwpid) - (void) printf(" lwp# %d ------------", (int)lwpid); + amt = (HEAD_WIDTH - strlen(buf) - 2); + if (amt < 4) + amt = 4; - (void) printf("--------------------\n"); + for (i = 0; i < amt / 2; i++) + (void) putc('-', stdout); + (void) printf(" %s ", buf); + for (i = 0; i < (amt / 2) + (amt % 2); i++) + (void) putc('-', stdout); + (void) putc('\n', stdout); } /*ARGSUSED*/ diff --git a/usr/src/cmd/sgs/elfdump/common/corenote.c b/usr/src/cmd/sgs/elfdump/common/corenote.c index 0777025523..a5ba4e31b8 100644 --- a/usr/src/cmd/sgs/elfdump/common/corenote.c +++ b/usr/src/cmd/sgs/elfdump/common/corenote.c @@ -1256,6 +1256,20 @@ dump_prstatus(note_state_t *state, const char *title) } +static void +dump_lwpname(note_state_t *state, const char *title) +{ + const sl_prlwpname_layout_t *layout = state->ns_arch->prlwpname; + + indent_enter(state, title, &layout->pr_lwpid); + + PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_LWPID), pr_lwpid); + PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_LWPNAME), pr_lwpname); + + indent_exit(state); +} + + /* * Print percent from 16-bit binary fraction [0 .. 1] * Round up .01 to .1 to indicate some small percentage (the 0x7000 below). @@ -1909,6 +1923,11 @@ corenote(Half mach, int do_swap, Word type, state.ns_v2col = 54; dump_secflags(&state, MSG_ORIG(MSG_CNOTE_DESC_PRSECFLAGS_T)); return (CORENOTE_R_OK); + + case NT_LWPNAME: + state.ns_vcol = 20; + dump_lwpname(&state, MSG_ORIG(MSG_CNOTE_DESC_PRLWPNAME_T)); + return (CORENOTE_R_OK); } return (CORENOTE_R_BADTYPE); diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg index e7488d5373..253ea4a788 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg @@ -22,6 +22,7 @@ # # Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2012 DEY Storage Systems, Inc. All rights reserved. +# Copyright 2018 Joyent, Inc. # @ _START_ @@ -469,6 +470,7 @@ @ MSG_CNOTE_DESC_STRUCT_UTSNAME "desc: (struct utsname)" @ MSG_CNOTE_DESC_PRFDINFO_T "desc: (prfdinfo_t)" @ MSG_CNOTE_DESC_PRSECFLAGS_T "desc: (prsecflags_t)" +@ MSG_CNOTE_DESC_PRLWPNAME_T "desc: (prlwpname_t)" @ MSG_CNOTE_FMT_LINE "%*s%-*s%s" @ MSG_CNOTE_FMT_LINE_2UP "%*s%-*s%-*s%-*s%s" @@ -535,6 +537,7 @@ @ MSG_CNOTE_T_PR_LWP "pr_lwp:" @ MSG_CNOTE_T_PR_LWPHOLD "pr_lwphold:" @ MSG_CNOTE_T_PR_LWPID "pr_lwpid:" +@ MSG_CNOTE_T_PR_LWPNAME "pr_lwpname:" @ MSG_CNOTE_T_PR_LWPPEND "pr_lwppend:" @ MSG_CNOTE_T_PR_NAME "pr_name:" @ MSG_CNOTE_T_PR_NGROUPS "pr_ngroups:" diff --git a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c index f7af1c1543..674972dc22 100644 --- a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c +++ b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c @@ -11,6 +11,7 @@ /* * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. */ /* @@ -58,3 +59,4 @@ timestruc_t ts; struct utsname uts; prfdinfo_t ptfd; prsecflags_t psf; +prlwpname_t psn; diff --git a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c index d90363c5de..522c974fbd 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 @@ gen_prsecflags(void) END; } +static void +gen_prlwpname(void) +{ + START(prlwpname, prlwpname_t); + SCALAR_FIELD(prlwpname_t, pr_lwpid, 0); + ARRAY_FIELD(prlwpname_t, pr_lwpname, 0); + END; +} + /*ARGSUSED*/ int main(int argc, char *argv[]) @@ -640,6 +650,7 @@ main(int argc, char *argv[]) gen_utsname(); gen_prfdinfo(); gen_prsecflags(); + gen_prlwpname(); /* * Generate the full arch_layout description @@ -668,6 +679,7 @@ main(int argc, char *argv[]) (void) printf(fmt, "utsname"); (void) printf(fmt, "prfdinfo"); (void) printf(fmt, "prsecflags"); + (void) printf(fmt, "prlwpname"); (void) printf("};\n"); /* diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout.h b/usr/src/cmd/sgs/elfdump/common/struct_layout.h index b0592d6909..022640e906 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 struct { */ typedef union { char sld_i8; - uchar_t sld_ui8; + uchar_t sld_ui8; short sld_i16; ushort_t sld_ui16; int32_t sld_i32; @@ -535,6 +536,12 @@ typedef struct { sl_field_t pr_upper; } sl_prsecflags_layout_t; +typedef struct { + sl_field_t sizeof_struct; + sl_field_t pr_lwpid; + sl_field_t pr_lwpname; +} sl_prlwpname_layout_t; + /* * This type collects all of the layout definitions for * a given architecture. @@ -561,6 +568,7 @@ typedef struct { const sl_utsname_layout_t *utsname; /* struct utsname */ const sl_prfdinfo_layout_t *prfdinfo; /* prdinfo_t */ const sl_prsecflags_layout_t *prsecflags; /* prsecflags_t */ + const sl_prlwpname_layout_t *prlwpname; /* prlwpname_t */ } sl_arch_layout_t; diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c index 2b9469a022..42260b1e43 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_prsecflags_layout_t prsecflags_layout = { }; +static const sl_prlwpname_layout_t prlwpname_layout = { + { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */ + { 0, 8, 0, 0 }, /* pr_lwpid */ + { 8, 1, 32, 0 }, /* pr_lwpname[] */ +}; + + static const sl_arch_layout_t layout_amd64 = { @@ -411,6 +419,7 @@ static const sl_arch_layout_t layout_amd64 = { &utsname_layout, &prfdinfo_layout, &prsecflags_layout, + &prlwpname_layout, }; diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c index 6a516bc225..de104e90ec 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_prsecflags_layout_t prsecflags_layout = { }; +static const sl_prlwpname_layout_t prlwpname_layout = { + { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */ + { 0, 8, 0, 0 }, /* pr_lwpid */ + { 8, 1, 32, 0 }, /* pr_lwpname[] */ +}; + + static const sl_arch_layout_t layout_i386 = { @@ -411,6 +419,7 @@ static const sl_arch_layout_t layout_i386 = { &utsname_layout, &prfdinfo_layout, &prsecflags_layout, + &prlwpname_layout, }; diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c index 94760c3d82..ead0ae6b7b 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_prsecflags_layout_t prsecflags_layout = { }; +static const sl_prlwpname_layout_t prlwpname_layout = { + { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */ + { 0, 8, 0, 0 }, /* pr_lwpid */ + { 8, 1, 32, 0 }, /* pr_lwpname[] */ +}; + + static const sl_arch_layout_t layout_sparc = { @@ -410,6 +419,7 @@ static const sl_arch_layout_t layout_sparc = { &utsname_layout, &prfdinfo_layout, &prsecflags_layout, + &prlwpname_layout, }; diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c index a194d8136a..00eaae9146 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_prsecflags_layout_t prsecflags_layout = { }; +static const sl_prlwpname_layout_t prlwpname_layout = { + { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */ + { 0, 8, 0, 0 }, /* pr_lwpid */ + { 8, 1, 32, 0 }, /* pr_lwpname[] */ +}; + + static const sl_arch_layout_t layout_sparcv9 = { @@ -411,6 +419,7 @@ static const sl_arch_layout_t layout_sparcv9 = { &utsname_layout, &prfdinfo_layout, &prsecflags_layout, + &prlwpname_layout, }; diff --git a/usr/src/cmd/sgs/libconv/Makefile.com b/usr/src/cmd/sgs/libconv/Makefile.com index c6287c433c..1bb482f706 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 @@ $(LINTOUT64) := LDLIBS += -ldemangle-sys 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 02b3e5d59b..dc9b8022f3 100644 --- a/usr/src/cmd/sgs/libconv/common/corenote.c +++ b/usr/src/cmd/sgs/libconv/common/corenote.c @@ -58,9 +58,10 @@ conv_cnote_type(Word type, Conv_fmt_flags_t fmt_flags, MSG_NT_LWPSINFO, MSG_NT_PRPRIV, MSG_NT_PRPRIVINFO, MSG_NT_CONTENT, MSG_NT_ZONENAME, MSG_NT_FDINFO, - MSG_NT_SPYMASTER, MSG_NT_SECFLAGS + MSG_NT_SPYMASTER, MSG_NT_SECFLAGS, + MSG_NT_LWPNAME, }; -#if NT_NUM != NT_SECFLAGS +#if NT_NUM != NT_LWPNAME #error "NT_NUM has grown. Update core note types[]" #endif static const conv_ds_msg_t ds_types = { diff --git a/usr/src/cmd/sgs/libconv/common/corenote.msg b/usr/src/cmd/sgs/libconv/common/corenote.msg index b55e67ec07..a36f2bddf7 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 62fbbf1514..0e5253a281 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 enum { typedef int (*graph_walk_cb_t)(graph_vertex_t *, void *); typedef struct graph_walk_info { - graph_walk_dir_t gi_dir; + graph_walk_dir_t gi_dir; uchar_t *gi_visited; /* vertex bitmap */ int (*gi_pre)(graph_vertex_t *, void *); void (*gi_post)(graph_vertex_t *, void *); @@ -3849,6 +3850,8 @@ run_sulogin(const char *msg) static void * sulogin_thread(void *unused) { + (void) pthread_setname_np(pthread_self(), "sulogin"); + MUTEX_LOCK(&dgraph_lock); assert(sulogin_thread_running); @@ -3876,6 +3879,8 @@ single_user_thread(void *unused) char *buf; int r; + (void) pthread_setname_np(pthread_self(), "single_user"); + MUTEX_LOCK(&single_user_thread_lock); single_user_thread_count++; @@ -5779,6 +5784,8 @@ graph_event_thread(void *unused) scf_handle_t *h; int err; + (void) pthread_setname_np(pthread_self(), "graph_event"); + h = libscf_handle_create_bound_loop(); /*CONSTCOND*/ @@ -6138,6 +6145,8 @@ graph_thread(void *arg) scf_handle_t *h; int err; + (void) pthread_setname_np(pthread_self(), "graph"); + h = libscf_handle_create_bound_loop(); if (st->st_initial) @@ -6794,6 +6803,8 @@ repository_event_thread(void *unused) 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 cc9ce6768c..bddae9b027 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 @@ method_thread(void *arg) boolean_t retryable; restarter_str_t reason; + (void) pthread_setname_np(pthread_self(), "method"); + assert(0 <= info->sf_method_type && info->sf_method_type <= 2); /* Get (and lock) the restarter_inst_t. */ diff --git a/usr/src/cmd/svc/startd/restarter.c b/usr/src/cmd/svc/startd/restarter.c index 676cded1c8..a98c863fb5 100644 --- a/usr/src/cmd/svc/startd/restarter.c +++ b/usr/src/cmd/svc/startd/restarter.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. */ /* @@ -994,6 +994,8 @@ restarter_post_fsminimal_thread(void *unused) scf_handle_t *h; int r; + (void) pthread_setname_np(pthread_self(), "restarter_post_fsmin"); + h = libscf_handle_create_bound_loop(); for (;;) { @@ -1771,6 +1773,8 @@ restarter_process_events(void *arg) char *fmri = (char *)arg; struct timespec to; + (void) pthread_setname_np(pthread_self(), "restarter_process_events"); + assert(fmri != NULL); h = libscf_handle_create_bound_loop(); @@ -1939,8 +1943,8 @@ out: } static int -is_admin_event(restarter_event_type_t t) { - +is_admin_event(restarter_event_type_t t) +{ switch (t) { case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON: case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE: @@ -1985,6 +1989,8 @@ restarter_event_thread(void *unused) { scf_handle_t *h; + (void) pthread_setname_np(pthread_self(), "restarter_event"); + /* * This is a new thread, and thus, gets its own handle * to the repository. @@ -2196,6 +2202,8 @@ restarter_contracts_event_thread(void *unused) int fd, err; scf_handle_t *local_handle; + (void) pthread_setname_np(pthread_self(), "restarter_contracts_event"); + /* * Await graph load completion. That is, stop here, until we've scanned * the repository for contract - instance associations. @@ -2545,6 +2553,8 @@ restarter_timeouts_event_thread(void *unused) * is not empty. */ + (void) pthread_setname_np(pthread_self(), "restarter_timeouts_event"); + /*CONSTCOND*/ while (1) { /* diff --git a/usr/src/cmd/svc/startd/wait.c b/usr/src/cmd/svc/startd/wait.c index ebd83be10e..12856ff639 100644 --- a/usr/src/cmd/svc/startd/wait.c +++ b/usr/src/cmd/svc/startd/wait.c @@ -21,7 +21,8 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2012, Joyent, Inc. All rights reserved. + * + * Copyright 2018 Joyent, Inc. */ /* @@ -252,6 +253,8 @@ wait_register(pid_t pid, const char *inst_fmri, int am_parent, int direct) void * wait_thread(void *args) { + (void) pthread_setname_np(pthread_self(), "wait"); + for (;;) { port_event_t pe; int fd; diff --git a/usr/src/head/pthread.h b/usr/src/head/pthread.h index 91d268a30d..490a93f1b2 100644 --- a/usr/src/head/pthread.h +++ b/usr/src/head/pthread.h @@ -21,7 +21,7 @@ /* * Copyright 2014 Garrett D'Amore <garrett@damore.org> - * Copyright 2016 Joyent, Inc. + * Copyright 2018 Joyent, Inc. * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -139,6 +139,9 @@ extern "C" { /* barriers */ #define PTHREAD_BARRIER_SERIAL_THREAD -2 +/* For pthread_{get,set}name_np(). */ +#define PTHREAD_MAX_NAMELEN_NP (32) + #ifndef _ASM /* @@ -209,6 +212,10 @@ extern int pthread_attr_setschedparam(pthread_attr_t *_RESTRICT_KYWD, const struct sched_param *_RESTRICT_KYWD); extern int pthread_attr_getschedparam(const pthread_attr_t *_RESTRICT_KYWD, struct sched_param *_RESTRICT_KYWD); +extern int pthread_attr_setname_np(pthread_attr_t *_RESTRICT_KYWD, + const char *_RESTRICT_KYWD); +extern int pthread_attr_getname_np(pthread_attr_t *_RESTRICT_KYWD, + char *_RESTRICT_KYWD, size_t); extern int pthread_create(pthread_t *_RESTRICT_KYWD, const pthread_attr_t *_RESTRICT_KYWD, void * (*)(void *), void *_RESTRICT_KYWD); @@ -231,6 +238,8 @@ extern int pthread_key_delete(pthread_key_t); extern int pthread_setspecific(pthread_key_t, const void *); extern void *pthread_getspecific(pthread_key_t); extern pthread_t pthread_self(void); +extern int pthread_setname_np(pthread_t, const char *); +extern int pthread_getname_np(pthread_t, char *, size_t); /* * function prototypes - synchronization related calls diff --git a/usr/src/head/thread.h b/usr/src/head/thread.h index d0b0b3ddeb..704174d411 100644 --- a/usr/src/head/thread.h +++ b/usr/src/head/thread.h @@ -24,6 +24,8 @@ * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2018 Joyent, Inc. */ #ifndef _THREAD_H @@ -87,6 +89,8 @@ extern int thr_keycreate_once(thread_key_t *, void(*)(void *)); extern int thr_setspecific(thread_key_t, void *); extern int thr_getspecific(thread_key_t, void **); extern size_t thr_min_stack(void); +extern int thr_getname(thread_t, char *, size_t); +extern int thr_setname(thread_t, const char *); #endif /* _ASM */ diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h index 81781fe04c..c9e2670cc4 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 @@ typedef struct _thrattr { int policy; int inherit; size_t guardsize; + char name[THREAD_NAME_MAX]; } thrattr_t; typedef struct _rwlattr { @@ -1492,7 +1494,7 @@ extern int rw_read_held(rwlock_t *); extern int rw_write_held(rwlock_t *); extern int _thrp_create(void *, size_t, void *(*)(void *), void *, long, - thread_t *, size_t); + thread_t *, size_t, const char *); extern int _thrp_suspend(thread_t, uchar_t); extern int _thrp_continue(thread_t, uchar_t); diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers index 953a08f833..ba79795325 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 @@ $if _x86 && _ELF64 $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 b04bcdba7c..7cfc970120 100644 --- a/usr/src/lib/libc/port/threads/pthr_attr.c +++ b/usr/src/lib/libc/port/threads/pthr_attr.c @@ -25,11 +25,13 @@ */ /* - * Copyright 2015, Joyent, Inc. + * Copyright 2018, Joyent, Inc. */ #include "lint.h" #include "thr_uberdata.h" +#include <sys/ctype.h> +#include <strings.h> #include <sched.h> /* @@ -48,7 +50,8 @@ def_thrattr(void) 0, /* prio */ SCHED_OTHER, /* policy */ PTHREAD_INHERIT_SCHED, /* inherit */ - 0 /* guardsize */ + 0, /* guardsize */ + { 0 } /* name */ }; if (thrattr.guardsize == 0) thrattr.guardsize = _sysconf(_SC_PAGESIZE); @@ -95,7 +98,7 @@ pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr) { thrattr_t *ap; const thrattr_t *old_ap = - old_attr? old_attr->__pthread_attrp : def_thrattr(); + old_attr ? old_attr->__pthread_attrp : def_thrattr(); if (old_ap == NULL) return (EINVAL); @@ -114,8 +117,8 @@ pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr) int pthread_attr_equal(const pthread_attr_t *attr1, const pthread_attr_t *attr2) { - const thrattr_t *ap1 = attr1? attr1->__pthread_attrp : def_thrattr(); - const thrattr_t *ap2 = attr2? attr2->__pthread_attrp : def_thrattr(); + const thrattr_t *ap1 = attr1 ? attr1->__pthread_attrp : def_thrattr(); + const thrattr_t *ap2 = attr2 ? attr2->__pthread_attrp : def_thrattr(); if (ap1 == NULL || ap2 == NULL) return (0); @@ -476,6 +479,53 @@ pthread_attr_getstack(const pthread_attr_t *attr, return (EINVAL); } +int +pthread_attr_setname_np(pthread_attr_t *attr, const char *name) +{ + thrattr_t *ap; + + if (attr == NULL || (ap = attr->__pthread_attrp) == NULL) + return (EINVAL); + + if (name == NULL) { + bzero(ap->name, sizeof (ap->name)); + return (0); + } + + if (strlen(name) >= sizeof (ap->name)) + return (ERANGE); + + /* + * We really want the ASCII version of isprint() here... + */ + for (size_t i = 0; name[i] != '\0'; i++) { + if (!ISPRINT(name[i])) + return (EINVAL); + } + + /* + * not having garbage after the end of the string simplifies attr + * comparison + */ + bzero(ap->name, sizeof (ap->name)); + (void) strlcpy(ap->name, name, sizeof (ap->name)); + return (0); +} + +int +pthread_attr_getname_np(pthread_attr_t *attr, char *buf, size_t len) +{ + thrattr_t *ap; + + if (buf == NULL || attr == NULL || + (ap = attr->__pthread_attrp) == NULL) + return (EINVAL); + + if (strlcpy(buf, ap->name, len) > len) + return (ERANGE); + return (0); +} + /* * This function is a common BSD extension to pthread which is used to obtain * the attributes of a thread that might have changed after its creation, for @@ -551,6 +601,7 @@ pthread_attr_get_np(pthread_t tid, pthread_attr_t *attr) ap->policy = target->ul_policy; ap->inherit = target->ul_ptinherit; ap->guardsize = target->ul_guardsize; + (void) pthread_getname_np(tid, ap->name, sizeof (ap->name)); ret = 0; out: diff --git a/usr/src/lib/libc/port/threads/pthread.c b/usr/src/lib/libc/port/threads/pthread.c index 6a22995639..34b4b4c73c 100644 --- a/usr/src/lib/libc/port/threads/pthread.c +++ b/usr/src/lib/libc/port/threads/pthread.c @@ -24,7 +24,7 @@ * Use is subject to license terms. */ /* - * Copyright 2016 Joyent, Inc. + * Copyright 2018 Joyent, Inc. */ #include "lint.h" @@ -128,7 +128,7 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, flag = ap->scope | ap->detachstate | ap->daemonstate | THR_SUSPENDED; error = _thrp_create(ap->stkaddr, ap->stksize, start_routine, arg, - flag, &tid, ap->guardsize); + flag, &tid, ap->guardsize, ap->name); if (error == 0) { /* * Record the original inheritence value for diff --git a/usr/src/lib/libc/port/threads/thr.c b/usr/src/lib/libc/port/threads/thr.c index 640c1c9645..e849b19e6d 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 @@ find_lwp(thread_t tid) int _thrp_create(void *stk, size_t stksize, void *(*func)(void *), void *arg, - long flags, thread_t *new_thread, size_t guardsize) + long flags, thread_t *new_thread, size_t guardsize, const char *name) { ulwp_t *self = curthread; uberdata_t *udp = self->ul_uberdata; @@ -715,6 +715,9 @@ _thrp_create(void *stk, size_t stksize, void *(*func)(void *), void *arg, exit_critical(self); + if (name != NULL) + (void) pthread_setname_np(tid, name); + if (!(flags & THR_SUSPENDED)) (void) _thrp_continue(tid, TSTP_REGULAR); @@ -725,7 +728,8 @@ int thr_create(void *stk, size_t stksize, void *(*func)(void *), void *arg, long flags, thread_t *new_thread) { - return (_thrp_create(stk, stksize, func, arg, flags, new_thread, 0)); + return (_thrp_create(stk, stksize, func, arg, flags, new_thread, 0, + NULL)); } /* @@ -2398,6 +2402,87 @@ __nthreads(void) 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 d6e90bd953..eb88f7e993 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 @@ const dt_version_t _dtrace_versions[] = { DT_VERS_1_12, /* D API 1.12 */ DT_VERS_1_12_1, /* D API 1.12.1 */ DT_VERS_1_13, /* D API 1.13 */ + DT_VERS_1_14, /* D API 1.14 */ 0 }; @@ -401,6 +403,8 @@ static const dt_ident_t _dtrace_globals[] = { &dt_idops_func, "void(@, ...)" }, { "this", DT_IDENT_PTR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "void" }, +{ "threadname", DT_IDENT_SCALAR, 0, DIF_VAR_THREADNAME, + DT_ATTR_STABCMN, DT_VERS_1_14, &dt_idops_type, "string" }, { "tid", DT_IDENT_SCALAR, 0, DIF_VAR_TID, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "id_t" }, { "timestamp", DT_IDENT_SCALAR, 0, DIF_VAR_TIMESTAMP, diff --git a/usr/src/lib/libfakekernel/common/sys/thread.h b/usr/src/lib/libfakekernel/common/sys/thread.h index 6213be2807..d6e05c691c 100644 --- a/usr/src/lib/libfakekernel/common/sys/thread.h +++ b/usr/src/lib/libfakekernel/common/sys/thread.h @@ -24,6 +24,7 @@ * Use is subject to license terms. * * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. */ #ifndef _SYS_THREAD_H @@ -82,6 +83,7 @@ extern kthread_t *_curthread(void); /* returns thread pointer */ #define _KTHREAD_INVALID ((void *)(uintptr_t)-1) +#define THREAD_NAME_MAX (32) struct proc; extern struct proc *_curproc(void); diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h index ce5063f621..e05ff8b430 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 @@ typedef struct lwp_info { /* per-lwp information from core file */ lwpid_t lwp_id; /* lwp identifier */ lwpsinfo_t lwp_psinfo; /* /proc/<pid>/lwp/<lwpid>/lwpsinfo data */ lwpstatus_t lwp_status; /* /proc/<pid>/lwp/<lwpid>/lwpstatus data */ + char lwp_name[THREAD_NAME_MAX]; #if defined(sparc) || defined(__sparc) gwindows_t *lwp_gwins; /* /proc/<pid>/lwp/<lwpid>/gwindows data */ prxregset_t *lwp_xregs; /* /proc/<pid>/lwp/<lwpid>/xregs data */ @@ -273,7 +275,7 @@ extern void optimize_symtab(sym_tbl_t *); extern void Pbuild_file_symtab(struct ps_prochandle *, file_info_t *); extern ctf_file_t *Pbuild_file_ctf(struct ps_prochandle *, file_info_t *); extern map_info_t *Paddr2mptr(struct ps_prochandle *, uintptr_t); -extern char *Pfindexec(struct ps_prochandle *, const char *, +extern char *Pfindexec(struct ps_prochandle *, const char *, int (*)(const char *, void *), void *); extern int getlwpstatus(struct ps_prochandle *, lwpid_t, lwpstatus_t *); int Pstopstatus(struct ps_prochandle *, long, uint32_t); diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c index afc5f459e7..37728190e3 100644 --- a/usr/src/lib/libproc/common/Pcore.c +++ b/usr/src/lib/libproc/common/Pcore.c @@ -24,7 +24,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. - * Copyright (c) 2014, Joyent, Inc. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2015 Gary Mills */ @@ -726,6 +726,32 @@ err: } static int +note_lwpname(struct ps_prochandle *P, size_t nbytes) +{ + prlwpname_t name; + lwp_info_t *lwp; + + if (nbytes != sizeof (name) || + read(P->asfd, &name, sizeof (name)) != sizeof (name)) + goto err; + + if ((lwp = lwpid2info(P, name.pr_lwpid)) == NULL) + goto err; + + if (strlcpy(lwp->lwp_name, name.pr_lwpname, + sizeof (lwp->lwp_name)) >= sizeof (lwp->lwp_name)) { + errno = ENAMETOOLONG; + goto err; + } + + return (0); + +err: + dprintf("Pgrab_core: failed to read NT_LWPNAME\n"); + return (-1); +} + +static int note_fdinfo(struct ps_prochandle *P, size_t nbytes) { prfdinfo_t prfd; @@ -1231,6 +1257,7 @@ static int (*nhdlrs[])(struct ps_prochandle *, size_t) = { note_fdinfo, /* 22 NT_FDINFO */ note_spymaster, /* 23 NT_SPYMASTER */ note_secflags, /* 24 NT_SECFLAGS */ + note_lwpname, /* 25 NT_LWPNAME */ }; static void diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c index 6ddf92ad2f..64ef98065b 100644 --- a/usr/src/lib/libproc/common/Pgcore.c +++ b/usr/src/lib/libproc/common/Pgcore.c @@ -25,7 +25,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. - * Copyright 2015 Joyent, Inc. + * Copyright 2018 Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. */ @@ -509,6 +509,7 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip) { pgcore_t *pgc = data; struct ps_prochandle *P = pgc->P; + prlwpname_t name = { 0, "" }; psinfo_t ps; /* @@ -577,6 +578,14 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip) #endif /* __sparcv9 */ #endif /* sparc */ + if (Plwp_getname(P, lsp->pr_lwpid, name.pr_lwpname, + sizeof (name.pr_lwpname)) == 0) { + name.pr_lwpid = lsp->pr_lwpid; + if (write_note(pgc->pgc_fd, NT_LWPNAME, &name, + sizeof (name), pgc->pgc_doff) != 0) + return (1); + } + if (!(lsp->pr_flags & PR_AGENT)) return (0); diff --git a/usr/src/lib/libproc/common/Plwpregs.c b/usr/src/lib/libproc/common/Plwpregs.c index c2b150000f..bf35c91ccf 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 @@ Plwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps) } int +Plwp_getname(struct ps_prochandle *P, lwpid_t lwpid, + char *buf, size_t bufsize) +{ + char lwpname[THREAD_NAME_MAX]; + char *from = NULL; + lwp_info_t *lwp; + + if (P->state == PS_IDLE) { + errno = ENODATA; + return (-1); + } + + if (P->state != PS_DEAD) { + if (getlwpfile(P, lwpid, "lwpname", + lwpname, sizeof (lwpname)) != 0) + return (-1); + from = lwpname; + } else { + if ((lwp = getlwpcore(P, lwpid)) == NULL) + return (-1); + from = lwp->lwp_name; + } + + if (strlcpy(buf, from, bufsize) >= bufsize) { + errno = ENAMETOOLONG; + return (-1); + } + + return (0); +} + +int Plwp_getspymaster(struct ps_prochandle *P, lwpid_t lwpid, psinfo_t *ps) { lwpstatus_t lps; diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h index d74c08e828..eb73039a21 100644 --- a/usr/src/lib/libproc/common/libproc.h +++ b/usr/src/lib/libproc/common/libproc.h @@ -25,7 +25,7 @@ * * Portions Copyright 2007 Chad Mynhier * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. - * Copyright 2015, Joyent, Inc. + * Copyright 2018, Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. */ @@ -436,6 +436,7 @@ extern int Pldt(struct ps_prochandle *, struct ssd *, int); extern int proc_get_ldt(pid_t, struct ssd *, int); #endif /* __i386 || __amd64 */ +extern int Plwp_getname(struct ps_prochandle *, lwpid_t, char *, size_t); extern int Plwp_getpsinfo(struct ps_prochandle *, lwpid_t, lwpsinfo_t *); extern int Plwp_getspymaster(struct ps_prochandle *, lwpid_t, psinfo_t *); diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers index b3f9df9d97..3b2fe58812 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 @@ SYMBOL_VERSION SUNWprivate_1.1 { Plookup_by_name; Plwp_alt_stack; Plwp_getfpregs; + Plwp_getname; Plwp_getpsinfo; Plwp_getregs; Plwp_getspymaster; diff --git a/usr/src/man/man1/ps.1 b/usr/src/man/man1/ps.1 index f0f01d4c54..3c838729fd 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 @@ is a version of the argument list as it was passed to the command when it 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 @@ one line to be printed for each lwp in the process. .sp .ne 2 .na +\fB\fBlwpname\fR\fR +.ad +.RS 11n +The name of the lwp, if set. Requesting this formatting option causes +one line to be printed for each lwp in the process. +.RE + +.sp +.ne 2 +.na \fB\fBnlwp\fR\fR .ad .RS 11n @@ -1173,8 +1183,8 @@ The data model of the process, printed in the same manner as via .sp .LP -Only \fBcomm\fR and \fBargs\fR are allowed to contain blank characters; all -others, including the Solaris implementation variables, are not. +Only \fBcomm\fR, \fBlwpname\fR, and \fBargs\fR are allowed to contain blank +characters; all others, including the 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 @@ group GROUP time TIME 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 @@ fname COMMAND rss RSS gid GID ruid RUID lgrp LGRP s S lwp LWP sid SID -nlwp NLWP stime STIME -opri PRI taskid TASKID -osz SZ uid UID -pmem %MEM wchan WCHAN -pri PRI zone ZONE -ctid CTID zoneid ZONEID +lwpname LWPNAME stime STIME +nlwp NLWP taskid TASKID +opri PRI uid UID +osz SZ wchan WCHAN +pmem %MEM zone ZONE +pri PRI zoneid ZONEID +ctid CTID .TE .SH EXAMPLES diff --git a/usr/src/man/man1m/prstat.1m b/usr/src/man/man1m/prstat.1m index a5f02621cf..d181c9a55f 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 @@ The name of the process (name of executed file). .sp .ne 2 .na -\fBLWPID\fR +\fBLWP\fR .ad .sp .6 .RS 4n -The \fBlwp\fR \fBID\fR of the \fBlwp\fR being reported. +The \fBlwp\fR \fBID\fR of the \fBlwp\fR being reported, as well as the LWP +name if any is set. .RE .sp diff --git a/usr/src/man/man3c/Makefile b/usr/src/man/man3c/Makefile index 2c890a7f47..9d1c679e65 100644 --- a/usr/src/man/man3c/Makefile +++ b/usr/src/man/man3c/Makefile @@ -307,6 +307,7 @@ MANFILES= __fbufsize.3c \ pthread_attr_getdetachstate.3c \ pthread_attr_getguardsize.3c \ pthread_attr_getinheritsched.3c \ + pthread_attr_getname_np.3c \ pthread_attr_getschedparam.3c \ pthread_attr_getschedpolicy.3c \ pthread_attr_getscope.3c \ @@ -332,6 +333,7 @@ MANFILES= __fbufsize.3c \ pthread_equal.3c \ pthread_exit.3c \ pthread_getconcurrency.3c \ + pthread_getname_np.3c \ pthread_getschedparam.3c \ pthread_getspecific.3c \ pthread_join.3c \ @@ -475,6 +477,7 @@ MANFILES= __fbufsize.3c \ termios.3c \ thr_create.3c \ thr_exit.3c \ + thr_getname.3c \ thr_getconcurrency.3c \ thr_getprio.3c \ thr_join.3c \ @@ -1092,6 +1095,7 @@ MANLINKS= FD_CLR.3c \ pthread_attr_setdetachstate.3c \ pthread_attr_setguardsize.3c \ pthread_attr_setinheritsched.3c \ + pthread_attr_setname_np.3c \ pthread_attr_setschedparam.3c \ pthread_attr_setschedpolicy.3c \ pthread_attr_setscope.3c \ @@ -1128,6 +1132,7 @@ MANLINKS= FD_CLR.3c \ pthread_rwlockattr_destroy.3c \ pthread_rwlockattr_setpshared.3c \ pthread_setconcurrency.3c \ + pthread_setname_np.3c \ pthread_setschedparam.3c \ pthread_setspecific.3c \ pthread_spin_init.3c \ @@ -1291,6 +1296,7 @@ MANLINKS= FD_CLR.3c \ thr_continue.3c \ thr_getspecific.3c \ thr_keycreate_once.3c \ + thr_setname.3c \ thr_setconcurrency.3c \ thr_setprio.3c \ thr_setspecific.3c \ @@ -2140,6 +2146,8 @@ pthread_attr_setguardsize.3c := LINKSRC = pthread_attr_getguardsize.3c pthread_attr_setinheritsched.3c := LINKSRC = pthread_attr_getinheritsched.3c +pthread_attr_setname_np.3c := LINKSRC = pthread_attr_getname_np.3c + pthread_attr_setschedparam.3c := LINKSRC = pthread_attr_getschedparam.3c pthread_attr_setschedpolicy.3c := LINKSRC = pthread_attr_getschedpolicy.3c @@ -2174,6 +2182,8 @@ pthread_condattr_destroy.3c := LINKSRC = pthread_condattr_init.3c pthread_setconcurrency.3c := LINKSRC = pthread_getconcurrency.3c +pthread_setname_np.3c := LINKSRC = pthread_getname_np.3c + pthread_setschedparam.3c := LINKSRC = pthread_getschedparam.3c pthread_setspecific.3c := LINKSRC = pthread_getspecific.3c @@ -2408,6 +2418,8 @@ thr_setspecific.3c := LINKSRC = thr_keycreate.3c thr_continue.3c := LINKSRC = thr_suspend.3c +thr_setname.3c := LINKSRC = thr_getname.3c + timegm.3c := LINKSRC = mktime.3c timer_getoverrun.3c := LINKSRC = timer_settime.3c diff --git a/usr/src/man/man3c/pthread_attr_getname_np.3c b/usr/src/man/man3c/pthread_attr_getname_np.3c new file mode 100644 index 0000000000..fbac370410 --- /dev/null +++ b/usr/src/man/man3c/pthread_attr_getname_np.3c @@ -0,0 +1,105 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2018 Joyent, Inc. +.\" +.Dd "August 22, 2018" +.Dt PTHREAD_ATTR_GETNAME_NP 3C +.Os +.Sh NAME +.Nm pthread_attr_getname_np , +.Nm pthread_attr_setname_np +.Nd get or set thread name attribute +.Sh SYNOPSIS +.In pthread.h +. +.Ft int +.Fo pthread_attr_getname_np +.Fa "pthread_attr_t *restrict attr" +.Fa "char *name" +.Fa "size_t len" +.Fc +. +.Ft int +.Fo pthread_attr_setname_np +.Fa "pthread_attr_t *restrict attr" +.Fa "const char *name" +.Fc +. +.Sh DESCRIPTION +The +.Fn pthread_attr_setname_np +and +.Fn pthread_attr_getname_np +functions, respectively, set and get the thread name attribute in +.Fa attr +to +.Fa name . +For +.Fn pthread_attr_getname_np , +.Fa len +is the size of +.Fa name . +Any threads created with +.Xr pthread_create 3c +using +.Fa attr +will have their name set to +.Fa name +upon creation. +.Pp +Thread names are limited to +.Dv PTHREAD_MAX_NAMELEN_NP +including the terminating NUL. +They may only contain printable ASCII characters. +.Sh RETURN VALUES +Upon successful completion, the +.Fn pthread_attr_getname_np +and +.Fn pthread_attr_setname_np +functions return +.Sy 0 . +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +The +.Fn pthread_attr_getname_np +function may fail with: +.Bl -tag -width Er +.It Er EINVAL +The +.Fa name +argument is +.Sy NULL . +.It Er ERANGE +The size of +.Fa name +as indicated by +.Fa len +is too small to contain the thread name. +The buffer may be over-written with partial contents of the thread name. +.El +.Pp +The +.Fn pthread_attr_setname_np +function may fail with: +.Bl -tag -width Er +.It Er ERANGE +The length of name given in +.Fa name +exceeds the maximum size allowed. +.El +.Sh INTERFACE STABILITY +.Sy Uncommitted +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr pthread_create 3c , +.Xr pthread_getname_np 3c diff --git a/usr/src/man/man3c/pthread_getname_np.3c b/usr/src/man/man3c/pthread_getname_np.3c new file mode 100644 index 0000000000..7404a4abfe --- /dev/null +++ b/usr/src/man/man3c/pthread_getname_np.3c @@ -0,0 +1,124 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2018 Joyent, Inc. +.\" +.Dd "August 22, 2018" +.Dt PTHREAD_GETNAME_NP 3C +.Os +.Sh NAME +.Nm pthread_getname_np , +.Nm pthread_setname_np +.Nd get or set the name of a thread +.Sh SYNOPSIS +.In pthread.h +. +.Ft int +.Fo pthread_getname_np +.Fa "pthread_t tid" +.Fa "char *name" +.Fa "size_t len" +.Fc +. +.Ft int +.Fo pthread_setname_np +.Fa "pthread_t tid" +.Fa "const char *name" +.Fc +. +.Sh DESCRIPTION +The +.Fn pthread_getname_np +and +.Fn pthread_setname_np +functions, respectively, get and set the names of the thread whose id is given +by the +.Fa tid +parameter. +For +.Fn pthread_getname_np , +.Fa len +indicates the size of +.Fa name . +.Pp +Thread names are limited to +.Dv PTHREAD_MAX_NAMELEN_NP +including the terminating NUL. +They may only contain printable ASCII characters. +.Pp +To clear a thread name, call +.Fn pthread_setname_np +with +.Sy NULL . +.Pp +Unlike some other systems, threads do not inherit the process name by default. +.Sh RETURN VALUES +Upon successful completion, the +.Fn pthread_getname_np +and +.Fn pthread_setname_np +functions return +.Sy 0 . +Otherwise, an error number is returned to indicate the error. +If the thread identified by +.Fa tid +does not have a name set, +.Fa pthread_getname_np +will be set to an empty string (length = 0). +.Sh ERRORS +On failure, the contents of the buffer are undefined. +Errors from +.Xr open 2 , +.Xr read 2 , +or +.Xr write 2 +are possible. +In addition, the +.Fn pthread_getname_np +function will fail with: +.Bl -tag -width Er +.It Er EINVAL +The +.Fa name +argument is +.Sy NULL . +.It Er ERANGE +The size of +.Fa name +as given by +.Fa len +was not large enough to contain the name of the thread. +.It Er ESRCH +The thread +.Fa tid +was not found. +.El +.Pp +The +.Fn pthread_setname_np +function will fail with: +.Bl -tag -width Er +.It Er ERANGE +The length of +.Fa name +exceeds the maximum allowed size. +.It Er ESRCH +The thread +.Fa tid +was not found. +.El +.Sh INTERFACE STABILITY +.Sy Uncommitted +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr pthread_attr_getname_np 3c , +.Xr pthread_create 3c diff --git a/usr/src/man/man3c/thr_getname.3c b/usr/src/man/man3c/thr_getname.3c new file mode 100644 index 0000000000..551e620d46 --- /dev/null +++ b/usr/src/man/man3c/thr_getname.3c @@ -0,0 +1,124 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2018 Joyent, Inc. +.\" +.Dd "August 22, 2018" +.Dt THR_GETNAME 3C +.Os +.Sh NAME +.Nm thr_getname , +.Nm thr_setname +.Nd get or set the name of a thread +.Sh SYNOPSIS +.In thread.h +. +.Ft int +.Fo thr_getname +.Fa "thread_t tid" +.Fa "char *name" +.Fa "size_t len" +.Fc +. +.Ft int +.Fo thr_setname +.Fa "thread_t tid" +.Fa "const char *name" +.Fc +. +.Sh DESCRIPTION +The +.Fn thr_getname +and +.Fn thr_setname +functions, respectively, get and set the names of the thread whose id is given +by the +.Fa tid +parameter. +For +.Fn thr_getname , +.Fa len +indicates the size of +.Fa name . +.Pp +Thread names are limited to +.Dv THREAD_NAME_MAX +including the terminating NUL. +They may only contain printable ASCII characters. +.Pp +To clear a thread name, call +.Fn thr_setname +with +.Sy NULL . +.Pp +Unlike some other systems, threads do not inherit the process name by default. +.Sh RETURN VALUES +Upon successful completion, the +.Fn thr_getname +and +.Fn thr_setname +functions return +.Sy 0 . +Otherwise, an error number is returned to indicate the error. +If the thread identified by +.Fa tid +does not have a name set, +.Fa thr_getname +will be set to an empty string (length = 0). +.Sh ERRORS +On failure, the contents of the buffer are undefined. +Errors from +.Xr open 2 , +.Xr read 2 , +or +.Xr write 2 +are possible. +In addition, the +.Fn thr_getname +function will fail with: +.Bl -tag -width Er +.It Er EINVAL +The +.Fa name +argument is +.Sy NULL . +.It Er ERANGE +The size of +.Fa name +as given by +.Fa len +was not large enough to contain the name of the thread. +.It Er ESRCH +The thread +.Fa tid +was not found. +.El +.Pp +The +.Fn thr_setname +function will fail with: +.Bl -tag -width Er +.It Er ERANGE +The length of +.Fa name +exceeds the maximum allowed size. +.It Er ESRCH +The thread +.Fa tid +was not found. +.El +.Sh INTERFACE STABILITY +.Sy Uncommitted +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr pthread_setname_np 3c , +.Xr thr_create 3c diff --git a/usr/src/man/man3lib/libproc.3lib b/usr/src/man/man3lib/libproc.3lib index 915febee0b..6b1e26eaf8 100644 --- a/usr/src/man/man3lib/libproc.3lib +++ b/usr/src/man/man3lib/libproc.3lib @@ -9,9 +9,9 @@ .\" http://www.illumos.org/license/CDDL. .\" .\" -.\" Copyright 2015 Joyent, Inc. +.\" Copyright 2018 Joyent, Inc. .\" -.Dd June 06, 2016 +.Dd August 31, 2018 .Dt LIBPROC 3LIB .Os .Sh NAME @@ -217,34 +217,34 @@ manipulation of the process itself. .It Sy Plmid_to_loadobj Ta Sy Plmid_to_map .It Sy Plookup_by_addr Ta Sy Plookup_by_name .It Sy Plwp_alt_stack Ta Sy Plwp_getfpregs -.It Sy Plwp_getpsinfo Ta Sy Plwp_getregs -.It Sy Plwp_getspymaster Ta Sy Plwp_main_stack -.It Sy Plwp_setfpregs Ta Sy Plwp_setregs -.It Sy Plwp_stack Ta Sy Pname_to_ctf -.It Sy Pname_to_loadobj Ta Sy Pname_to_map -.It Sy Pobjname Ta Sy Pobjname_resolved -.It Sy Pplatform Ta Sy Ppltdest -.It Sy Ppriv Ta Sy Ppsinfo -.It Sy Pputareg Ta Sy Prd_agent -.It Sy Pread Ta Sy Pread_string -.It Sy Preset_maps Ta Sy Psetbkpt -.It Sy Psecflags Ta Sy Psetcred -.It Sy Psetfault Ta Sy Psetflags -.It Sy Psetpriv Ta Sy Psetrun -.It Sy Psetsignal Ta Sy Psetsysentry -.It Sy Psetsysexit Ta Sy Psetwapt -.It Sy Psetzoneid Ta Sy Psignal -.It Sy Pstate Ta Sy Pstatus -.It Sy Pstop Ta Sy Pstopstatus -.It Sy Psync Ta Sy Psysentry -.It Sy Psysexit Ta Sy Puname -.It Sy Punsetflags Ta Sy Pupdate_maps -.It Sy Pupdate_syms Ta Sy Pwait -.It Sy Pwrite Ta Sy Pxecbkpt -.It Sy Pxecwapt Ta Sy Pxlookup_by_addr -.It Sy Pxlookup_by_addr_resolved Ta Sy Pxlookup_by_name -.It Sy Pzonename Ta Sy Pzonepath -.It Sy Pzoneroot Ta +.It Sy Plwp_getname Ta Sy Plwp_getpsinfo +.It Sy Plwp_getregs Ta Sy Plwp_getspymaster +.It Sy Plwp_main_stack Ta Sy Plwp_setfpregs +.It Sy Plwp_setregs Ta Sy Plwp_stack +.It Sy Pname_to_ctf Ta Sy Pname_to_loadobj +.It Sy Pname_to_map Ta Sy Pobjname +.It Sy Pobjname_resolved Ta Sy Pplatform +.It Sy Ppltdest Ta Sy Ppriv +.It Sy Ppsinfo Ta Sy Pputareg +.It Sy Prd_agent Ta Sy Pread +.It Sy Pread_string Ta Sy Preset_maps +.It Sy Psetbkpt Ta Sy Psecflags +.It Sy Psetcred Ta Sy Psetfault +.It Sy Psetflags Ta Sy Psetpriv +.It Sy Psetrun Ta Sy Psetsignal +.It Sy Psetsysentry Ta Sy Psetsysexit +.It Sy Psetwapt Ta Sy Psetzoneid +.It Sy Psignal Ta Sy Pstate +.It Sy Pstatus Ta Sy Pstop +.It Sy Pstopstatus Ta Sy Psync +.It Sy Psysentry Ta Sy Psysexit +.It Sy Puname Ta Sy Punsetflags +.It Sy Pupdate_maps Ta Sy Pupdate_syms +.It Sy Pwait Ta Sy Pwrite +.It Sy Pxecbkpt Ta Sy Pxecwapt +.It Sy Pxlookup_by_addr Ta Sy Pxlookup_by_addr_resolved +.It Sy Pxlookup_by_name Ta Sy Pzonename +.It Sy Pzonepath Ta Sy Pzoneroot Ta .El .Ss Thread interrogation and manipulation The following routines obtain information about a thread and allow diff --git a/usr/src/man/man3proc/Makefile b/usr/src/man/man3proc/Makefile index 0984b6871f..e59e81fbf3 100644 --- a/usr/src/man/man3proc/Makefile +++ b/usr/src/man/man3proc/Makefile @@ -12,12 +12,12 @@ # # Copyright 2011, Richard Lowe # Copyright 2013 Nexenta Systems, Inc. All rights reserved. -# Copyright 2015 Joyent, Inc. +# Copyright 2018 Joyent, Inc. # include $(SRC)/Makefile.master -MANSECT= 3proc +MANSECT= 3proc MANFILES= \ Lctlfd.3proc \ @@ -64,6 +64,7 @@ MANFILES= \ Plookup_by_addr.3proc \ Plwp_getasrs.3proc \ Plwp_getgwindows.3proc \ + Plwp_getname.3proc \ Plwp_getpsinfo.3proc \ Plwp_getregs.3proc \ Plwp_getspymaster.3proc \ @@ -160,10 +161,10 @@ MANFILES= \ Pwrite.3proc \ Pxecbkpt.3proc \ Pzonename.3proc \ - ps_lgetregs.3proc \ - ps_pglobal_lookup.3proc \ - ps_pread.3proc \ - ps_pstop.3proc + ps_lgetregs.3proc \ + ps_pglobal_lookup.3proc \ + ps_pread.3proc \ + ps_pstop.3proc MANLINKS= \ @@ -265,7 +266,7 @@ MANLINKS= \ Pxlookup_by_name.3proc \ Pxsymbol_iter.3proc \ Pzonepath.3proc \ - Pzoneroot.3proc + Pzoneroot.3proc ps_lgetfpregs.3proc := LINKSRC = ps_lgetregs.3proc diff --git a/usr/src/man/man3proc/Paddr_to_ctf.3proc b/usr/src/man/man3proc/Paddr_to_ctf.3proc index 5eb4183a23..0364940975 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 6430d8eae4..54f129e110 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 d49067ee65..f9fcd6bc80 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 a5ae8a9dc4..501d006de4 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 0c1f7ed862..744b43f566 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 577fcf9359..23f81df918 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 27d9d6742a..5ea261d53f 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 6185e60d23..94552a1034 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 a421938e06..d492b38d51 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 73a2538ec8..647294ef82 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 bec0030fd4..a71ea1c16e 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 66679f5aea..7a51968201 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 e00c5f7684..15e04a8f08 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 4a3d23d4e9..38bd63cb24 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 30c677204e..9d683a9b91 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 8dc616ee0f..658154d2ba 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 f7560c7396..e6c205a421 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 7c1d8ed99e..cb106a4d19 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 055355e00c..cb03a77f48 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 1904ea73a0..e141b878fb 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 2d6122bfe7..5a4abadf0a 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 348e01ea15..58801051a0 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 bb34119e6a..b72eea536c 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 a6df2614e1..67109a85e2 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 2b864bd563..9cb01133dd 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 01be5d1ccf..0c22aaaaf3 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 fa3e3b31a9..1db5929459 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 18aef39e5a..74d9d15428 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 58b4d36950..2628b1fd90 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 c39a0b6371..e702875c48 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 ecb9a9a00c..fb54231c1e 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 b84879671d..d1b1593326 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 85fa41e910..ea0fa5d2fc 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 0000000000..961cc5257d --- /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 4d7d64fca7..53b01ea1c2 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 5d4e7766f7..e11f4f5fa2 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 8b7adbf418..762485ddda 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 e1801eedda..f1c191f99f 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 15de2f12ea..487190b539 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 2cf3303ed2..77d84664c2 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 7f2fb46124..6d43906ad4 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 4b75abb31a..300d4fa9dd 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 c17f9aabe9..82ff02bf3f 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 56eea82f85..98dd3e9dfe 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 f7adf48756..7f698f4db0 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 7032494b06..f3151c1789 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 1fdc63ee6a..2de9dd3759 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 5a1e449c31..89c6cd1758 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 3d66a0d560..61fe282162 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 088480ab57..01beb6c0af 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 c842757319..2e110af1ee 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 4f4b342146..9eaf3515d3 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 430063ef1e..8ebdbe2cf9 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 afc0ce65d6..15865707be 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 7cb467c402..fff818b333 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 a91126442b..0affa7ab01 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 4d327280e4..bfaece0206 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 68b6f92ebd..b21179156e 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 58745ffaa7..ae390200ca 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 4c7cce76f4..5367d3f717 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 4ef992cb77..e119d90841 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 7a83fc54fa..ef25c5d3b1 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 1ff90096f6..b4f1fe0b20 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 bd3da0d7cd..bcb116dc27 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 9ec03c0c83..b91696c761 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 7a917ee5a0..8f9b24de53 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 8ce88fb7a4..15f9f417f6 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 2378a19b9b..69e893a330 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 cc5637eedc..be7fa46d71 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 fa7999e311..ca0a92369a 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 ba0779fdd4..f6134de653 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 7fb482eae2..0f81eb30e2 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 9e6e819aa5..ee7fdb7b6e 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 411dbb8aae..a98f02cd21 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 0dc78d5959..828e107b98 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 59fd43f9a0..61279bdc75 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 @@ typedef struct psinfo { uintptr_t pr_argv; /* address of initial argument vector */ uintptr_t pr_envp; /* address of initial environment vector */ char pr_dmodel; /* data model of the process */ - lwpsinfo_t pr_lwp; /* information for representative lwp */ taskid_t pr_taskid; /* task id */ projid_t pr_projid; /* project id */ poolid_t pr_poolid; /* pool id */ zoneid_t pr_zoneid; /* zone id */ ctid_t pr_contract; /* process contract id */ + lwpsinfo_t pr_lwp; /* information for representative lwp */ } psinfo_t; .fi .in -2 @@ -1484,6 +1484,14 @@ following entries: 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 4dee59e903..a8f0f92d5c 100644 --- a/usr/src/pkg/manifests/system-dtrace-tests.mf +++ b/usr/src/pkg/manifests/system-dtrace-tests.mf @@ -22,6 +22,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# Copyright 2018 Joyent, Inc. # set name=pkg.fmri value=pkg:/system/dtrace/tests@$(PKGVERS) @@ -115,6 +116,7 @@ dir path=opt/SUNWdtrt/tst/common/struct dir path=opt/SUNWdtrt/tst/common/sugar dir path=opt/SUNWdtrt/tst/common/syscall dir path=opt/SUNWdtrt/tst/common/sysevent +dir path=opt/SUNWdtrt/tst/common/threadname dir path=opt/SUNWdtrt/tst/common/tick-n dir path=opt/SUNWdtrt/tst/common/trace dir path=opt/SUNWdtrt/tst/common/tracemem @@ -1846,6 +1848,8 @@ file path=opt/SUNWdtrt/tst/common/sysevent/tst.post.d mode=0444 file path=opt/SUNWdtrt/tst/common/sysevent/tst.post.exe mode=0555 file path=opt/SUNWdtrt/tst/common/sysevent/tst.post_chan.d mode=0444 file path=opt/SUNWdtrt/tst/common/sysevent/tst.post_chan.exe mode=0555 +file path=opt/SUNWdtrt/tst/common/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 06f6fe8e7c..846ed5bf99 100644 --- a/usr/src/pkg/manifests/system-library.man3c.inc +++ b/usr/src/pkg/manifests/system-library.man3c.inc @@ -303,6 +303,7 @@ file path=usr/share/man/man3c/pthread_attr_get_np.3c file path=usr/share/man/man3c/pthread_attr_getdetachstate.3c file path=usr/share/man/man3c/pthread_attr_getguardsize.3c file path=usr/share/man/man3c/pthread_attr_getinheritsched.3c +file path=usr/share/man/man3c/pthread_attr_getname_np.3c file path=usr/share/man/man3c/pthread_attr_getschedparam.3c file path=usr/share/man/man3c/pthread_attr_getschedpolicy.3c file path=usr/share/man/man3c/pthread_attr_getscope.3c @@ -328,6 +329,7 @@ file path=usr/share/man/man3c/pthread_detach.3c file path=usr/share/man/man3c/pthread_equal.3c file path=usr/share/man/man3c/pthread_exit.3c file path=usr/share/man/man3c/pthread_getconcurrency.3c +file path=usr/share/man/man3c/pthread_getname_np.3c file path=usr/share/man/man3c/pthread_getschedparam.3c file path=usr/share/man/man3c/pthread_getspecific.3c file path=usr/share/man/man3c/pthread_join.3c @@ -472,6 +474,7 @@ file path=usr/share/man/man3c/termios.3c file path=usr/share/man/man3c/thr_create.3c file path=usr/share/man/man3c/thr_exit.3c file path=usr/share/man/man3c/thr_getconcurrency.3c +file path=usr/share/man/man3c/thr_getname.3c file path=usr/share/man/man3c/thr_getprio.3c file path=usr/share/man/man3c/thr_join.3c file path=usr/share/man/man3c/thr_keycreate.3c @@ -1109,6 +1112,8 @@ link path=usr/share/man/man3c/pthread_attr_setguardsize.3c \ target=pthread_attr_getguardsize.3c link path=usr/share/man/man3c/pthread_attr_setinheritsched.3c \ target=pthread_attr_getinheritsched.3c +link path=usr/share/man/man3c/pthread_attr_setname_np.3c \ + target=pthread_attr_getname_np.3c link path=usr/share/man/man3c/pthread_attr_setschedparam.3c \ target=pthread_attr_getschedparam.3c link path=usr/share/man/man3c/pthread_attr_setschedpolicy.3c \ @@ -1181,6 +1186,8 @@ link path=usr/share/man/man3c/pthread_rwlockattr_setpshared.3c \ target=pthread_rwlockattr_getpshared.3c link path=usr/share/man/man3c/pthread_setconcurrency.3c \ target=pthread_getconcurrency.3c +link path=usr/share/man/man3c/pthread_setname_np.3c \ + target=pthread_getname_np.3c link path=usr/share/man/man3c/pthread_setschedparam.3c \ target=pthread_getschedparam.3c link path=usr/share/man/man3c/pthread_setspecific.3c \ @@ -1365,6 +1372,8 @@ link path=usr/share/man/man3c/thr_getspecific.3c target=thr_keycreate.3c link path=usr/share/man/man3c/thr_keycreate_once.3c target=thr_keycreate.3c link path=usr/share/man/man3c/thr_setconcurrency.3c \ target=thr_getconcurrency.3c +link path=usr/share/man/man3c/thr_setname.3c \ + target=thr_getname.3c link path=usr/share/man/man3c/thr_setprio.3c target=thr_getprio.3c link path=usr/share/man/man3c/thr_setspecific.3c target=thr_keycreate.3c link path=usr/share/man/man3c/thrd_sleep.3c target=nanosleep.3c diff --git a/usr/src/pkg/manifests/system-library.man3proc.inc b/usr/src/pkg/manifests/system-library.man3proc.inc index d7eeb3e42f..8528acca7b 100644 --- a/usr/src/pkg/manifests/system-library.man3proc.inc +++ b/usr/src/pkg/manifests/system-library.man3proc.inc @@ -10,7 +10,7 @@ # # -# Copyright 2015 Joyent, Inc. +# Copyright 2018 Joyent, Inc. # file path=usr/share/man/man3proc/proc_service.3proc @@ -81,6 +81,7 @@ file path=usr/share/man/man3proc/Plmid.3proc file path=usr/share/man/man3proc/Plookup_by_addr.3proc file path=usr/share/man/man3proc/Plwp_getasrs.3proc file path=usr/share/man/man3proc/Plwp_getgwindows.3proc +file path=usr/share/man/man3proc/Plwp_getname.3proc file path=usr/share/man/man3proc/Plwp_getpsinfo.3proc file path=usr/share/man/man3proc/Plwp_getregs.3proc file path=usr/share/man/man3proc/Plwp_getspymaster.3proc diff --git a/usr/src/pkg/manifests/system-test-libctest.mf b/usr/src/pkg/manifests/system-test-libctest.mf index 135822a5fd..f01471e5bf 100644 --- a/usr/src/pkg/manifests/system-test-libctest.mf +++ b/usr/src/pkg/manifests/system-test-libctest.mf @@ -13,6 +13,7 @@ # Copyright (c) 2012 by Delphix. All rights reserved. # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2015 Garrett D'Amore <garrett@damore.org> +# Copyright 2018 Joyent, Inc. # set name=pkg.fmri value=pkg:/system/test/libctest@$(PKGVERS) @@ -158,6 +159,7 @@ file path=opt/libc-tests/tests/strerror mode=0555 file path=opt/libc-tests/tests/symbols/setup mode=0555 file path=opt/libc-tests/tests/symbols/symbols_test.$(ARCH) mode=0555 file path=opt/libc-tests/tests/symbols/symbols_test.$(ARCH64) mode=0555 +file path=opt/libc-tests/tests/thread_name mode=0555 file path=opt/libc-tests/tests/timespec_get.32 mode=0555 file path=opt/libc-tests/tests/timespec_get.64 mode=0555 file path=opt/libc-tests/tests/wcsncasecmp-7344.32 mode=0555 diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run index 9c7e893cf6..cde5a5f8c8 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 @@ timeout = 600 [/opt/libc-tests/tests/set_constraint_handler_s.32] [/opt/libc-tests/tests/set_constraint_handler_s.64] [/opt/libc-tests/tests/strerror] +[/opt/libc-tests/tests/thread_name] [/opt/libc-tests/tests/timespec_get.32] [/opt/libc-tests/tests/timespec_get.64] diff --git a/usr/src/test/libc-tests/tests/threads/Makefile b/usr/src/test/libc-tests/tests/threads/Makefile index 1e73e7b8c7..31cb1ddefe 100644 --- a/usr/src/test/libc-tests/tests/threads/Makefile +++ b/usr/src/test/libc-tests/tests/threads/Makefile @@ -10,7 +10,7 @@ # # -# Copyright 2016 Joyent, Inc. +# Copyright 2018 Joyent, Inc. # include $(SRC)/Makefile.master @@ -18,7 +18,7 @@ include $(SRC)/Makefile.master ROOTOPTPKG = $(ROOT)/opt/libc-tests TESTDIR = $(ROOTOPTPKG)/tests -PROGS = pthread_attr_get_np +PROGS = pthread_attr_get_np thread_name include $(SRC)/cmd/Makefile.cmd include $(SRC)/test/Makefile.com diff --git a/usr/src/test/libc-tests/tests/threads/thread_name.c b/usr/src/test/libc-tests/tests/threads/thread_name.c new file mode 100644 index 0000000000..b164272644 --- /dev/null +++ b/usr/src/test/libc-tests/tests/threads/thread_name.c @@ -0,0 +1,278 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2018 Joyent, Inc. + */ + +/* + * Some basic pthread name API tests. + */ + +#include <sys/stat.h> +#include <pthread.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <thread.h> +#include <fcntl.h> +#include <stdio.h> +#include <errno.h> +#include <err.h> + + +/*ARGSUSED*/ +static void * +thr(void *unused) +{ + (void) sleep(100); + return (NULL); +} + +/*ARGSUSED*/ +int +main(int argc, char *argv[]) +{ + char name[PTHREAD_MAX_NAMELEN_NP]; + pthread_attr_t attr; + char path[PATH_MAX]; + pthread_t tid; + ssize_t n; + int test; + int rc; + int fd; + + /* Default thread name is empty string. */ + test = 1; + + rc = pthread_getname_np(pthread_self(), name, sizeof (name)); + + if (rc != 0 || strcmp(name, "") != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* Can set name. */ + test = 2; + + (void) strlcpy(name, "main", sizeof (name)); + rc = pthread_setname_np(pthread_self(), name); + + if (rc != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_getname_np(pthread_self(), name, sizeof (name)); + + if (rc != 0 || strcmp(name, "main") != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* ERANGE check. */ + test = 3; + + rc = pthread_getname_np(pthread_self(), name, 2); + + if (rc != ERANGE) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* EINVAL check. */ + test = 4; + + rc = pthread_getname_np(pthread_self(), NULL, sizeof (name)); + + if (rc != EINVAL) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* can clear thread name. */ + test = 5; + + rc = pthread_setname_np(pthread_self(), NULL); + + if (rc != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_getname_np(pthread_self(), name, sizeof (name)); + + if (rc != 0 || strcmp(name, "") != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* non-existent thread check. */ + test = 6; + + rc = pthread_getname_np(808, name, sizeof (name)); + + if (rc != ESRCH) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_setname_np(808, "state"); + + if (rc != ESRCH) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* too long a name. */ + test = 7; + + rc = pthread_setname_np(pthread_self(), + "12345678901234567890123456789012"); + + if (rc != ERANGE) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* can name another thread. */ + test = 8; + + rc = pthread_create(&tid, NULL, thr, NULL); + + if (rc != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_setname_np(tid, "otherthread"); + + if (rc != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* attr tests. */ + test = 9; + + (void) pthread_attr_init(&attr); + + rc = pthread_attr_setname_np(&attr, + "12345678901234567890123456789012"); + + if (rc != ERANGE) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_attr_setname_np(&attr, "thread2"); + + if (rc != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_attr_getname_np(&attr, NULL, sizeof (name)); + + if (rc != EINVAL) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_attr_getname_np(&attr, name, 2); + + if (rc != ERANGE) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* does the attr actually apply? */ + test = 10; + + rc = pthread_create(&tid, &attr, thr, NULL); + + if (rc != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_getname_np(tid, name, sizeof (name)); + + if (rc != 0 || strcmp(name, "thread2") != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* proc read tests */ + test = 11; + + (void) snprintf(path, sizeof (path), + "/proc/self/lwp/%d/lwpname", (int)tid); + + fd = open(path, O_RDWR); + + if (fd == -1) + errx(EXIT_FAILURE, "test %d failed with %d", test, errno); + + n = read(fd, name, sizeof (name)); + + if (n != sizeof (name) || strcmp(name, "thread2") != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + if (lseek(fd, 0, SEEK_SET) != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, errno); + + n = read(fd, name, PTHREAD_MAX_NAMELEN_NP * 2); + + if (n != sizeof (name) || strcmp(name, "thread2") != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + if (lseek(fd, 0, SEEK_SET) != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, errno); + + n = read(fd, name, 4); + + if (n != 4 || strncmp(name, "thre", 4) != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* proc write tests */ + test = 12; + + if (lseek(fd, 0, SEEK_SET) != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, errno); + + n = write(fd, "1234567890123456789012345678901", + PTHREAD_MAX_NAMELEN_NP); + + if (n != PTHREAD_MAX_NAMELEN_NP) + errx(EXIT_FAILURE, "test %d failed with %d", test, errno); + + if (lseek(fd, 0, SEEK_SET) != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, errno); + + n = write(fd, "foo", sizeof ("foo")); + + if (n != sizeof ("foo")) + errx(EXIT_FAILURE, "test %d failed with %d", test, errno); + + if (lseek(fd, 0, SEEK_SET) != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, errno); + + n = read(fd, name, sizeof (name)); + + if (n != sizeof (name) || strcmp(name, "foo") != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + (void) close(fd); + + /* thr_* API. */ + test = 13; + + rc = thr_setname(thr_self(), "main"); + + if (rc != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = thr_getname(thr_self(), name, sizeof (name)); + + if (rc != 0 || strcmp(name, "main") != 0) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + /* badness */ + test = 14; + + rc = thr_setname(thr_self(), "\033]0;messeduptitle\a"); + + if (rc != EINVAL) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = thr_setname(thr_self(), "ab\177\177\n"); + + if (rc != EINVAL) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_attr_setname_np(&attr, "\033]0;messeduptitle\a"); + + if (rc != EINVAL) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + rc = pthread_attr_setname_np(&attr, "ab\177\177\n"); + + if (rc != EINVAL) + errx(EXIT_FAILURE, "test %d failed with %d", test, rc); + + return (EXIT_SUCCESS); +} diff --git a/usr/src/uts/common/disp/thread.c b/usr/src/uts/common/disp/thread.c index f2685af534..854b33798d 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 @@ thread_free(kthread_t *t) 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 @@ stkinfo_percent(caddr_t t_stk, caddr_t t_stkbase, caddr_t sp) } 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 b1685f42fc..6267faa7c0 100644 --- a/usr/src/uts/common/dtrace/dtrace.c +++ b/usr/src/uts/common/dtrace/dtrace.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2017, Joyent, Inc. + * Copyright (c) 2018, Joyent, Inc. * Copyright (c) 2012, 2014 by Delphix. All rights reserved. */ @@ -3539,6 +3539,25 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v, return ((uint64_t)lwp->lwp_errno); } + + case DIF_VAR_THREADNAME: + /* + * See comment in DIF_VAR_PID. + */ + if (DTRACE_ANCHORED(mstate->dtms_probe) && CPU_ON_INTR(CPU)) + return (0); + + if (curthread->t_name == NULL) + return (0); + + /* + * Once set, ->t_name itself is never changed: any updates are + * made to the same buffer that we are pointing out. So we are + * safe to dereference it here. + */ + return (dtrace_dif_varstr((uintptr_t)curthread->t_name, + state, mstate)); + default: DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); return (0); @@ -5563,7 +5582,7 @@ next: * Stringify using RFC 1884 convention 2 - 16 bit * hexadecimal values with a zero-run compression. * Lower case hexadecimal digits are used. - * eg, fe80::214:4fff:fe0b:76c8. + * eg, fe80::214:4fff:fe0b:76c8. * The IPv4 embedded form is returned for inet_ntop, * just the IPv4 string is returned for inet_ntoa6. */ @@ -5747,7 +5766,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, */ mstate->dtms_difo = difo; - regs[DIF_REG_R0] = 0; /* %r0 is fixed at zero */ + regs[DIF_REG_R0] = 0; /* %r0 is fixed at zero */ while (pc < textlen && !(*flags & CPU_DTRACE_FAULT)) { opc = pc; diff --git a/usr/src/uts/common/exec/elf/elf_notes.c b/usr/src/uts/common/exec/elf/elf_notes.c index 4037507dda..fbc87fea66 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 @@ setup_note_header(Phdr *v, proc_t *p) v[0].p_type = PT_NOTE; v[0].p_flags = PF_R; - v[0].p_filesz = (sizeof (Note) * (10 + 2 * nlwp + nzomb + nfd)) + v[0].p_filesz = (sizeof (Note) * (10 + 3 * nlwp + nzomb + nfd)) + roundup(sizeof (psinfo_t), sizeof (Word)) + roundup(sizeof (pstatus_t), sizeof (Word)) + roundup(prgetprivsize(), sizeof (Word)) @@ -107,6 +107,7 @@ setup_note_header(Phdr *v, proc_t *p) + roundup(sizeof (prsecflags_t), sizeof (Word)) + (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word)) + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word)) + + nlwp * roundup(sizeof (prlwpname_t), sizeof (Word)) + nfd * roundup(sizeof (prfdinfo_t), sizeof (Word)); if (curproc->p_agenttp != NULL) { @@ -456,6 +457,7 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, nzomb = p->p_zombcnt; /* for each entry in the lwp directory ... */ for (ldp = p->p_lwpdir; nlwp + nzomb != 0; ldp++) { + prlwpname_t name = { 0, }; if ((lep = ldp->ld_entry) == NULL) /* empty slot */ continue; @@ -466,6 +468,10 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, lwp = ttolwp(t); mutex_enter(&p->p_lock); prgetlwpsinfo(t, &bigwad->lwpsinfo); + if (t->t_name != NULL) { + (void) strlcpy(name.pr_lwpname, t->t_name, + sizeof (name.pr_lwpname)); + } mutex_exit(&p->p_lock); } else { /* zombie lwp */ ASSERT(nzomb != 0); @@ -476,11 +482,15 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, bigwad->lwpsinfo.pr_sname = 'Z'; bigwad->lwpsinfo.pr_start.tv_sec = lep->le_start; } + + name.pr_lwpid = bigwad->lwpsinfo.pr_lwpid; + error = elfnote(vp, &offset, NT_LWPSINFO, sizeof (bigwad->lwpsinfo), (caddr_t)&bigwad->lwpsinfo, rlimit, credp); if (error) goto done; + if (t == NULL) /* nothing more to do for a zombie */ continue; @@ -514,6 +524,11 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, if (error) goto done; + if ((error = elfnote(vp, &offset, NT_LWPNAME, sizeof (name), + (caddr_t)&name, rlimit, credp)) != 0) + goto done; + + #if defined(__sparc) /* * Unspilled SPARC register windows. diff --git a/usr/src/uts/common/fs/proc/prdata.h b/usr/src/uts/common/fs/proc/prdata.h index 70daaf8767..de816d49e7 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 @@ typedef enum prnodetype { PR_LWPDIR, /* /proc/<pid>/lwp */ PR_LWPIDDIR, /* /proc/<pid>/lwp/<lwpid> */ PR_LWPCTL, /* /proc/<pid>/lwp/<lwpid>/lwpctl */ + PR_LWPNAME, /* /proc/<pid>/lwp/<lwpid>/lwpname */ PR_LWPSTATUS, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */ PR_LWPSINFO, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */ PR_LWPUSAGE, /* /proc/<pid>/lwp/<lwpid>/lwpusage */ @@ -360,7 +361,7 @@ extern void prgetaction(proc_t *, user_t *, uint_t, struct sigaction *); extern void prgetusage(kthread_t *, struct prhusage *); extern void praddusage(kthread_t *, struct prhusage *); extern void prcvtusage(struct prhusage *, prusage_t *); -extern void prscaleusage(prhusage_t *); +extern void prscaleusage(prhusage_t *); extern kthread_t *prchoose(proc_t *); extern void allsetrun(proc_t *); extern int setisempty(uint32_t *, uint_t); diff --git a/usr/src/uts/common/fs/proc/prvnops.c b/usr/src/uts/common/fs/proc/prvnops.c index fdef53dc2e..2cf007c42c 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 @@ static prdirent_t lwpiddir[] = { ".." }, { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t), "lwpctl" }, - { PR_LWPSTATUS, 4 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_LWPNAME, 4 * sizeof (prdirent_t), sizeof (prdirent_t), + "lwpname" }, + { PR_LWPSTATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t), "lwpstatus" }, - { PR_LWPSINFO, 5 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_LWPSINFO, 6 * sizeof (prdirent_t), sizeof (prdirent_t), "lwpsinfo" }, - { PR_LWPUSAGE, 6 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_LWPUSAGE, 7 * sizeof (prdirent_t), sizeof (prdirent_t), "lwpusage" }, - { PR_XREGS, 7 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_XREGS, 8 * sizeof (prdirent_t), sizeof (prdirent_t), "xregs" }, - { PR_TMPLDIR, 8 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_TMPLDIR, 9 * sizeof (prdirent_t), sizeof (prdirent_t), "templates" }, - { PR_SPYMASTER, 9 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_SPYMASTER, 10 * sizeof (prdirent_t), sizeof (prdirent_t), "spymaster" }, #if defined(__sparc) - { PR_GWINDOWS, 10 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_GWINDOWS, 11 * sizeof (prdirent_t), sizeof (prdirent_t), "gwindows" }, - { PR_ASRS, 11 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_ASRS, 12 * sizeof (prdirent_t), sizeof (prdirent_t), "asrs" }, #endif }; @@ -587,7 +590,8 @@ static int pr_read_inval(), pr_read_as(), pr_read_status(), #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 @@ static int (*pr_read_function[PR_NFILES])() = { pr_read_inval, /* /proc/<pid>/lwp */ pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */ pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */ + pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */ pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */ pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */ pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */ @@ -1073,7 +1078,7 @@ pr_read_auxv(prnode_t *pnp, uio_t *uiop) * we have two kinds of LDT structures to export -- one for compatibility * mode, and one for long mode, sigh. * - * For now lets just have a ldt of size 0 for 64-bit processes. + * For now let's just have a ldt of size 0 for 64-bit processes. */ static int pr_read_ldt(prnode_t *pnp, uio_t *uiop) @@ -1538,6 +1543,33 @@ out: return (error); } +static int +pr_read_lwpname(prnode_t *pnp, uio_t *uiop) +{ + char lwpname[THREAD_NAME_MAX]; + kthread_t *t; + int error; + + ASSERT(pnp->pr_type == PR_LWPNAME); + + if (uiop->uio_offset >= THREAD_NAME_MAX) + return (0); + + if ((error = prlock(pnp, ZNO)) != 0) + return (error); + + bzero(lwpname, sizeof (lwpname)); + + t = pnp->pr_common->prc_thread; + + if (t->t_name != NULL) + (void) strlcpy(lwpname, t->t_name, sizeof (lwpname)); + + prunlock(pnp); + + return (pr_uioread(lwpname, sizeof (lwpname), uiop)); +} + /* ARGSUSED */ static int pr_read_xregs(prnode_t *pnp, uio_t *uiop) @@ -1808,6 +1840,7 @@ static int (*pr_read_function_32[PR_NFILES])() = { pr_read_inval, /* /proc/<pid>/lwp */ pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */ pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */ + pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */ pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */ pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */ pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */ @@ -2720,6 +2753,54 @@ prread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct) #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 @@ prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct) 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 @@ static vnode_t *(*pr_lookup_function[PR_NFILES])() = { pr_lookup_lwpdir, /* /proc/<pid>/lwp */ pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */ pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */ + pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */ pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */ pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */ pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */ @@ -4621,6 +4706,10 @@ prgetnode(vnode_t *dp, prnodetype_t type) 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 @@ static int (*pr_readdir_function[PR_NFILES])() = { pr_readdir_lwpdir, /* /proc/<pid>/lwp */ pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */ pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */ + pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */ pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */ pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */ pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */ diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h index 44ca7d8ae7..ab6d4c4445 100644 --- a/usr/src/uts/common/sys/dtrace.h +++ b/usr/src/uts/common/sys/dtrace.h @@ -25,7 +25,7 @@ */ /* - * Copyright 2017 Joyent, Inc. + * Copyright 2018 Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. */ @@ -242,6 +242,7 @@ typedef enum dtrace_probespec { #define DIF_VAR_UID 0x011e /* process user ID */ #define DIF_VAR_GID 0x011f /* process group ID */ #define DIF_VAR_ERRNO 0x0120 /* thread errno */ +#define DIF_VAR_THREADNAME 0x0121 /* thread name */ #define DIF_SUBR_RAND 0 #define DIF_SUBR_MUTEX_OWNED 1 @@ -2212,8 +2213,8 @@ extern void dtrace_probe(dtrace_id_t, uintptr_t arg0, uintptr_t arg1, */ typedef struct dtrace_helper_probedesc { char *dthpb_mod; /* probe module */ - char *dthpb_func; /* probe function */ - char *dthpb_name; /* probe name */ + char *dthpb_func; /* probe function */ + char *dthpb_name; /* probe name */ uint64_t dthpb_base; /* base address */ uint32_t *dthpb_offs; /* offsets array */ uint32_t *dthpb_enoffs; /* is-enabled offsets array */ diff --git a/usr/src/uts/common/sys/elf.h b/usr/src/uts/common/sys/elf.h index ab768ef19c..4bd884e9c2 100644 --- a/usr/src/uts/common/sys/elf.h +++ b/usr/src/uts/common/sys/elf.h @@ -429,10 +429,10 @@ typedef struct { #define ELFOSABI_OPENVMS 13 /* Open VMS */ #define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ #define ELFOSABI_AROS 15 /* Amiga Research OS */ -#define ELFOSABI_FENIXOS 16 /* The FenixOS highly scalable */ +#define ELFOSABI_FENIXOS 16 /* The FenixOS highly scalable */ /* multi-core OS */ -#define ELFOSABI_CLOUDABI 17 /* Nuxi CloudABI */ -#define ELFOSABI_OPENVOS 18 /* Stratus Technologies OpenVOS */ +#define ELFOSABI_CLOUDABI 17 /* Nuxi CloudABI */ +#define ELFOSABI_OPENVOS 18 /* Stratus Technologies OpenVOS */ #define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* standalone (embedded) application */ @@ -776,7 +776,7 @@ typedef struct { #define ELF32_R_INFO(sym, type) (((sym)<<8)+(unsigned char)(type)) #define ELF64_R_SYM(info) ((info)>>32) -#define ELF64_R_TYPE(info) ((Elf64_Word)(info)) +#define ELF64_R_TYPE(info) ((Elf64_Word)(info)) #define ELF64_R_INFO(sym, type) (((Elf64_Xword)(sym)<<32)+(Elf64_Xword)(type)) @@ -823,7 +823,7 @@ typedef struct { #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf32_Lword m_value; /* symbol value */ - Elf32_Word m_info; /* size + index */ + Elf32_Word m_info; /* size + index */ Elf32_Word m_poffset; /* symbol offset */ Elf32_Half m_repeat; /* repeat count */ Elf32_Half m_stride; /* stride info */ @@ -842,7 +842,7 @@ typedef struct { typedef struct { Elf64_Lword m_value; /* symbol value */ - Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_info; /* size + index */ Elf64_Xword m_poffset; /* symbol offset */ Elf64_Half m_repeat; /* repeat count */ Elf64_Half m_stride; /* stride info */ @@ -901,7 +901,7 @@ typedef Elf64_Word Elf64_Capchain; * info = ELF64_C_INFO(sym, grp) */ #define ELF64_C_SYM(info) ((info)>>32) -#define ELF64_C_GROUP(info) ((Elf64_Word)(info)) +#define ELF64_C_GROUP(info) ((Elf64_Word)(info)) #define ELF64_C_INFO(sym, grp) (((Elf64_Xword)(sym)<<32)+(Elf64_Xword)(grp)) #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ @@ -970,10 +970,11 @@ typedef Elf64_Word Elf64_Capchain; #define NT_PRPRIVINFO 19 /* priv_impl_info_t <sys/priv.h> */ #define NT_CONTENT 20 /* core_content_t <sys/corectl.h> */ #define NT_ZONENAME 21 /* string from getzonenamebyid(3C) */ -#define NT_FDINFO 22 /* open fd info */ +#define NT_FDINFO 22 /* open fd info */ #define NT_SPYMASTER 23 /* psinfo_t for agent LWP spymaster */ #define NT_SECFLAGS 24 /* process security-flags */ -#define NT_NUM 24 +#define NT_LWPNAME 25 /* prlwpname_t */ +#define NT_NUM 25 #ifdef _KERNEL diff --git a/usr/src/uts/common/sys/procfs.h b/usr/src/uts/common/sys/procfs.h index 6bf2e4ddb0..dfb54eaef5 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 @@ extern "C" { #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 @@ typedef struct prxmap { int pr_shmid; /* SysV shmid, -1 if not SysV shared memory */ dev_t pr_dev; /* st_dev from stat64() of mapped object, or PRNODEV */ uint64_t pr_ino; /* st_ino from stat64() of mapped object, if any */ - size_t pr_rss; /* pages of resident memory */ + size_t pr_rss; /* pages of resident memory */ size_t pr_anon; /* pages of resident anonymous memory */ size_t pr_locked; /* pages of locked memory */ size_t pr_pad; /* currently unused */ @@ -535,6 +537,16 @@ typedef struct prfdinfo { } prfdinfo_t; /* + * Representation of LWP name in core files. In /proc, we use a simple char + * array, but in core files we need to make it easy to correlate the note back + * to the right LWP. For simplicity, we'll use 32/64 consistent types. + */ +typedef struct prlwpname { + uint64_t pr_lwpid; + char pr_lwpname[THREAD_NAME_MAX]; +} prlwpname_t; + +/* * Header for /proc/<pid>/lstatus /proc/<pid>/lpsinfo /proc/<pid>/lusage */ typedef struct prheader { diff --git a/usr/src/uts/common/sys/thread.h b/usr/src/uts/common/sys/thread.h index d917944edf..f9f1d6462b 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 @@ typedef struct _kthread { 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 @@ extern disp_lock_t stop_lock; /* lock protecting stopped threads */ 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 |