summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/Makefile.ctf (renamed from usr/src/cmd/svc/Makefile.ctf)14
-rw-r--r--usr/src/cmd/cmd-inet/usr.lib/inetd/Makefile10
-rw-r--r--usr/src/cmd/cmd-inet/usr.lib/inetd/req.flg10
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_cmds.c3
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_ctf.c17
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_print.c259
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_print.h10
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/Makefile.files1
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/findstack.c88
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/genunix.c128
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/taskq.c483
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/taskq.h49
-rw-r--r--usr/src/cmd/svc/configd/Makefile6
-rw-r--r--usr/src/cmd/svc/prophist/Makefile14
-rw-r--r--usr/src/cmd/svc/req.flg11
-rw-r--r--usr/src/cmd/svc/servinfo/Makefile4
-rw-r--r--usr/src/cmd/svc/startd/Makefile4
-rw-r--r--usr/src/cmd/svc/svccfg/Makefile10
-rw-r--r--usr/src/cmd/svc/svcprop/Makefile12
-rw-r--r--usr/src/cmd/svc/svcs/Makefile12
-rw-r--r--usr/src/cmd/zdb/Makefile.com1
-rw-r--r--usr/src/cmd/zfs/Makefile1
-rw-r--r--usr/src/cmd/zpool/Makefile1
-rw-r--r--usr/src/cmd/ztest/Makefile.com21
-rw-r--r--usr/src/uts/common/os/taskq.c42
25 files changed, 914 insertions, 297 deletions
diff --git a/usr/src/cmd/svc/Makefile.ctf b/usr/src/cmd/Makefile.ctf
index 2c4c1fa3fc..8665fe237a 100644
--- a/usr/src/cmd/svc/Makefile.ctf
+++ b/usr/src/cmd/Makefile.ctf
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,14 +19,13 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
-CTFMERGE_HOOK = && $(CTFMERGE) -L VERSION -o $@ $(OBJS)
-CTFCONVERT_HOOK = && $(CTFCONVERT_O)
+POST_PROCESS += ; $(CTFMERGE) -L VERSION -o $@ $(OBJS)
+POST_PROCESS_O += ; $(CTFCONVERT_O)
+
CFLAGS += $(CTF_FLAGS)
CFLAGS64 += $(CTF_FLAGS)
NATIVE_CFLAGS += $(CTF_FLAGS)
diff --git a/usr/src/cmd/cmd-inet/usr.lib/inetd/Makefile b/usr/src/cmd/cmd-inet/usr.lib/inetd/Makefile
index b322b74013..69a32aa834 100644
--- a/usr/src/cmd/cmd-inet/usr.lib/inetd/Makefile
+++ b/usr/src/cmd/cmd-inet/usr.lib/inetd/Makefile
@@ -19,13 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
-# cmd/cmd-inet/usr.lib/inetd/%M%
-#
PROG = inetd
MANIFEST= inetd.xml inetd-upgrade.xml
@@ -36,7 +32,7 @@ SRCS = $(OBJS:%.o=%.c)
include ../../../Makefile.cmd
include ../../Makefile.cmd-inet
-include ../../../svc/Makefile.ctf
+include ../../../Makefile.ctf
ROOTMANIFESTDIR= $(ROOTSVCNETWORK)
@@ -58,7 +54,7 @@ lint_SRCS := LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2
all: $(PROG) $(SVCMETHOD)
$(PROG): $(OBJS)
- $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(CTFMERGE_HOOK)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
$(POST_PROCESS)
include ../Makefile.lib
diff --git a/usr/src/cmd/cmd-inet/usr.lib/inetd/req.flg b/usr/src/cmd/cmd-inet/usr.lib/inetd/req.flg
index d31375e098..fac25a8680 100644
--- a/usr/src/cmd/cmd-inet/usr.lib/inetd/req.flg
+++ b/usr/src/cmd/cmd-inet/usr.lib/inetd/req.flg
@@ -3,9 +3,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -21,9 +20,8 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
-echo_file usr/src/cmd/svc/Makefile.ctf
+echo_file usr/src/cmd/Makefile.ctf
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c
index a9fe1ed8ae..46b16b820f 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c
@@ -2906,7 +2906,8 @@ const mdb_dcmd_t mdb_dcmd_builtins[] = {
{ "dump", "?[-eqrstu] [-f|-p] [-g bytes] [-w paragraphs]",
"dump memory from specified address", cmd_dump, dump_help },
{ "echo", "args ...", "echo arguments", cmd_echo },
- { "enum", "?[-x] enum [name]", "print an enumeration", cmd_enum },
+ { "enum", "?[-ex] enum [name]", "print an enumeration", cmd_enum,
+ enum_help },
{ "eval", "command", "evaluate the specified command", cmd_eval },
{ "events", "[-av]", "list traced software events",
cmd_events, events_help },
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
index 55186aeb57..099f259b62 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
@@ -446,6 +446,10 @@ mdb_ctf_type_size(mdb_ctf_id_t id)
mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
ssize_t ret;
+ /* resolve the type in case there's a forward declaration */
+ if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
+ return (ret);
+
if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR)
return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
@@ -586,6 +590,10 @@ mdb_ctf_enum_name(mdb_ctf_id_t id, int value)
mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
const char *ret;
+ /* resolve the type in case there's a forward declaration */
+ if (mdb_ctf_type_resolve(id, &id) != 0)
+ return (NULL);
+
if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL)
(void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
@@ -613,6 +621,10 @@ mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data)
member_iter_t mi;
int ret;
+ /* resolve the type in case there's a forward declaration */
+ if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
+ return (ret);
+
mi.mi_cb = cb;
mi.mi_arg = data;
mi.mi_fp = idp->mci_fp;
@@ -629,6 +641,11 @@ int
mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data)
{
mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
+ int ret;
+
+ /* resolve the type in case there's a forward declaration */
+ if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
+ return (ret);
return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data));
}
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_print.c b/usr/src/cmd/mdb/common/mdb/mdb_print.c
index 1350cf25fe..24ae11b7bb 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_print.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_print.c
@@ -217,6 +217,7 @@ cmd_offsetof(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_ctf_id_t id;
ulong_t off;
char tn[MDB_SYM_NAMLEN];
+ ssize_t sz;
int ret;
if (flags & DCMD_ADDRSPEC)
@@ -235,35 +236,82 @@ cmd_offsetof(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
member = argv[1].a_un.a_str;
- if (mdb_ctf_offsetof(id, member, &off) != 0) {
+ if (mdb_ctf_member_info(id, member, &off, &id) != 0) {
mdb_warn("failed to find member %s of type %s", member, tn);
return (DCMD_ERR);
}
- if (off % NBBY == 0)
- mdb_printf("offsetof (%s, %s) = %#lr\n",
- tn, member, off / NBBY);
- else
- mdb_printf("offsetof (%s, %s) = %#lr bits\n",
- tn, member, off);
+ if (flags & DCMD_PIPE_OUT) {
+ if (off % NBBY != 0) {
+ mdb_warn("member %s of type %s is not byte-aligned\n",
+ member, tn);
+ return (DCMD_ERR);
+ }
+ mdb_printf("%#lr", off / NBBY);
+ return (DCMD_OK);
+ }
+
+ mdb_printf("offsetof (%s, %s) = %#lr",
+ tn, member, off / NBBY);
+ if (off % NBBY != 0)
+ mdb_printf(".%lr", off % NBBY);
+
+ if ((sz = mdb_ctf_type_size(id)) > 0)
+ mdb_printf(", sizeof (...->%s) = %#lr", member, sz);
+
+ mdb_printf("\n");
return (DCMD_OK);
}
+/*ARGSUSED*/
+static int
+enum_prefix_scan_cb(const char *name, int value, void *arg)
+{
+ char *str = arg;
+
+ /*
+ * This function is called with every name in the enum. We make
+ * "arg" be the common prefix, if any.
+ */
+ if (str[0] == 0) {
+ if (strlcpy(arg, name, MDB_SYM_NAMLEN) >= MDB_SYM_NAMLEN)
+ return (1);
+ return (0);
+ }
+
+ while (*name == *str) {
+ if (*str == 0) {
+ if (str != arg) {
+ str--; /* don't smother a name completely */
+ }
+ break;
+ }
+ name++;
+ str++;
+ }
+ *str = 0;
+
+ return (str == arg); /* only continue if prefix is non-empty */
+}
+
struct enum_p2_info {
- int e_value;
- char *e_buf;
- size_t e_size;
- uint_t e_bits;
- uint8_t e_found;
- uint8_t e_zero;
+ intmax_t e_value; /* value we're processing */
+ char *e_buf; /* buffer for holding names */
+ size_t e_size; /* size of buffer */
+ size_t e_prefix; /* length of initial prefix */
+ uint_t e_allprefix; /* apply prefix to first guy, too */
+ uint_t e_bits; /* bits seen */
+ uint8_t e_found; /* have we seen anything? */
+ uint8_t e_first; /* does buf contain the first one? */
+ uint8_t e_zero; /* have we seen a zero value? */
};
static int
enum_p2_cb(const char *name, int bit_arg, void *arg)
{
struct enum_p2_info *eiip = arg;
- uint_t bit = bit_arg;
+ uintmax_t bit = bit_arg;
if (bit != 0 && !ISP2(bit))
return (1); /* non-power-of-2; abort processing */
@@ -279,47 +327,84 @@ enum_p2_cb(const char *name, int bit_arg, void *arg)
eiip->e_bits |= bit;
if (eiip->e_buf != NULL && (eiip->e_value & bit) != 0) {
- if (eiip->e_found)
- (void) strlcat(eiip->e_buf, "|", eiip->e_size);
+ char *buf = eiip->e_buf;
+ size_t prefix = eiip->e_prefix;
+
+ if (eiip->e_found) {
+ (void) strlcat(buf, "|", eiip->e_size);
+
+ if (eiip->e_first && !eiip->e_allprefix && prefix > 0) {
+ char c1 = buf[prefix];
+ char c2 = buf[prefix + 1];
+ buf[prefix] = '{';
+ buf[prefix + 1] = 0;
+ mdb_printf("%s", buf);
+ buf[prefix] = c1;
+ buf[prefix + 1] = c2;
+ mdb_printf("%s", buf + prefix);
+ } else {
+ mdb_printf("%s", buf);
+ }
- if (strlcat(eiip->e_buf, name, eiip->e_size) >=
- eiip->e_size)
- return (1); /* overflowed */
+ }
+ /* skip the common prefix as necessary */
+ if ((eiip->e_found || eiip->e_allprefix) &&
+ strlen(name) > prefix)
+ name += prefix;
+ (void) strlcpy(eiip->e_buf, name, eiip->e_size);
+ eiip->e_first = !eiip->e_found;
eiip->e_found = 1;
}
return (0);
}
static int
-enum_value_to_name_p2(mdb_ctf_id_t id, int v, char *buf, size_t size)
+enum_is_p2(mdb_ctf_id_t id)
{
struct enum_p2_info eii;
+ bzero(&eii, sizeof (eii));
+
+ return (mdb_ctf_type_kind(id) == CTF_K_ENUM &&
+ mdb_ctf_enum_iter(id, enum_p2_cb, &eii) == 0 &&
+ eii.e_bits != 0);
+}
+
+static int
+enum_value_print_p2(mdb_ctf_id_t id, intmax_t value, uint_t allprefix)
+{
+ struct enum_p2_info eii;
+ char prefix[MDB_SYM_NAMLEN + 2];
+ intmax_t missed;
bzero(&eii, sizeof (eii));
- eii.e_value = v;
- eii.e_buf = buf;
- eii.e_size = size;
+ eii.e_value = value;
+ eii.e_buf = prefix;
+ eii.e_size = sizeof (prefix);
+ eii.e_allprefix = allprefix;
- if (buf != NULL && size > 0)
- buf[0] = '\0';
+ prefix[0] = 0;
+ if (mdb_ctf_enum_iter(id, enum_prefix_scan_cb, prefix) == 0)
+ eii.e_prefix = strlen(prefix);
- if (mdb_ctf_type_kind(id) != CTF_K_ENUM ||
- mdb_ctf_enum_iter(id, enum_p2_cb, &eii) != 0 ||
- eii.e_bits == 0)
+ if (mdb_ctf_enum_iter(id, enum_p2_cb, &eii) != 0 || eii.e_bits == 0)
return (-1);
- if (buf != NULL && (!eii.e_found || (v & ~eii.e_bits) != 0)) {
- char val[16];
+ missed = (value & ~(intmax_t)eii.e_bits);
- (void) mdb_snprintf(val, sizeof (val),
- "0x%x", (v & ~eii.e_bits));
+ if (eii.e_found) {
+ /* push out any final value, with a | if we missed anything */
+ if (!eii.e_first)
+ (void) strlcat(prefix, "}", sizeof (prefix));
+ if (missed != 0)
+ (void) strlcat(prefix, "|", sizeof (prefix));
- if (eii.e_found)
- (void) strlcat(buf, "|", size);
- if (strlcat(buf, val, size) >= size)
- return (-1);
+ mdb_printf("%s", prefix);
+ }
+
+ if (!eii.e_found || missed) {
+ mdb_printf("%#llx", missed);
}
return (0);
@@ -328,24 +413,39 @@ enum_value_to_name_p2(mdb_ctf_id_t id, int v, char *buf, size_t size)
struct enum_cbinfo {
uint_t e_flags;
const char *e_string; /* NULL for value searches */
- int e_value;
+ size_t e_prefix;
+ intmax_t e_value;
uint_t e_found;
+ mdb_ctf_id_t e_id;
};
-#define E_PRETTY 0x1
-#define E_HEX 0x2
-#define E_SEARCH_STRING 0x4
-#define E_SEARCH_VALUE 0x8
+#define E_PRETTY 0x01
+#define E_HEX 0x02
+#define E_SEARCH_STRING 0x04
+#define E_SEARCH_VALUE 0x08
+#define E_ELIDE_PREFIX 0x10
static void
enum_print(struct enum_cbinfo *info, const char *name, int value)
{
uint_t flags = info->e_flags;
+ uint_t elide_prefix = (info->e_flags & E_ELIDE_PREFIX);
+
+ if (name != NULL && info->e_prefix && strlen(name) > info->e_prefix)
+ name += info->e_prefix;
if (flags & E_PRETTY) {
- if (flags & E_HEX)
- mdb_printf("%-8x %s\n", value, name);
- else
- mdb_printf("%-11d %s\n", value, name);
+ uint_t indent = 5 + ((flags & E_HEX) ? 8 : 11);
+
+ mdb_printf((flags & E_HEX)? "%8x " : "%11d ", value);
+ (void) mdb_inc_indent(indent);
+ if (name != NULL) {
+ mdb_iob_puts(mdb.m_out, name);
+ } else {
+ (void) enum_value_print_p2(info->e_id, value,
+ elide_prefix);
+ }
+ (void) mdb_dec_indent(indent);
+ mdb_printf("\n");
} else {
mdb_printf("%#r\n", value);
}
@@ -372,6 +472,23 @@ enum_cb(const char *name, int value, void *arg)
return (0);
}
+void
+enum_help(void)
+{
+ mdb_printf("%s",
+"Without an address and name, print all values for the enumeration \"enum\".\n"
+"With an address, look up a particular value in \"enum\". With a name, look\n"
+"up a particular name in \"enum\".\n");
+
+ (void) mdb_dec_indent(2);
+ mdb_printf("\n%<b>OPTIONS%</b>\n");
+ (void) mdb_inc_indent(2);
+
+ mdb_printf("%s",
+" -e remove common prefixes from enum names\n"
+" -x report enum values in hexadecimal\n");
+}
+
/*ARGSUSED*/
int
cmd_enum(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
@@ -380,11 +497,13 @@ cmd_enum(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
char type[MDB_SYM_NAMLEN + sizeof ("enum ")];
char tn2[MDB_SYM_NAMLEN + sizeof ("enum ")];
+ char prefix[MDB_SYM_NAMLEN];
mdb_ctf_id_t id;
mdb_ctf_id_t idr;
int i;
intmax_t search;
+ uint_t isp2;
info.e_flags = (flags & DCMD_PIPE_OUT)? 0 : E_PRETTY;
info.e_string = NULL;
@@ -392,6 +511,7 @@ cmd_enum(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
info.e_found = 0;
i = mdb_getopts(argc, argv,
+ 'e', MDB_OPT_SETBITS, E_ELIDE_PREFIX, &info.e_flags,
'x', MDB_OPT_SETBITS, E_HEX, &info.e_flags,
NULL);
@@ -433,6 +553,8 @@ cmd_enum(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_ERR);
}
+ info.e_id = idr;
+
if (argc > 2)
return (DCMD_USAGE);
@@ -462,25 +584,32 @@ cmd_enum(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if ((int)search != search) {
mdb_warn("value '%lld' out of enumeration range\n",
search);
- return (DCMD_ERR);
}
info.e_value = search;
}
+ isp2 = enum_is_p2(idr);
+ if (isp2)
+ info.e_flags |= E_HEX;
+
if (DCMD_HDRSPEC(flags) && (info.e_flags & E_PRETTY)) {
if (info.e_flags & E_HEX)
- mdb_printf("%<b>%-8s %s%</b>\n", "VALUE", "NAME");
+ mdb_printf("%<u>%8s %-64s%</u>\n", "VALUE", "NAME");
else
- mdb_printf("%<b>%-11s %s%</b>\n", "VALUE", "NAME");
+ mdb_printf("%<u>%11s %-64s%</u>\n", "VALUE", "NAME");
}
/* if the enum is a power-of-two one, process it that way */
- if ((info.e_flags & E_SEARCH_VALUE) &&
- enum_value_to_name_p2(idr, info.e_value, tn2, sizeof (tn2)) == 0) {
- enum_print(&info, tn2, info.e_value);
+ if ((info.e_flags & E_SEARCH_VALUE) && isp2) {
+ enum_print(&info, NULL, info.e_value);
return (DCMD_OK);
}
+ prefix[0] = 0;
+ if ((info.e_flags & E_ELIDE_PREFIX) &&
+ mdb_ctf_enum_iter(id, enum_prefix_scan_cb, prefix) == 0)
+ info.e_prefix = strlen(prefix);
+
if (mdb_ctf_enum_iter(idr, enum_cb, &info) == -1) {
mdb_warn("cannot walk '%s' as enum", type);
return (DCMD_ERR);
@@ -492,7 +621,8 @@ cmd_enum(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_warn("name \"%s\" not in '%s'\n", info.e_string,
type);
else
- mdb_warn("value %#d not in '%s'\n", info.e_value, type);
+ mdb_warn("value %#lld not in '%s'\n", info.e_value,
+ type);
return (DCMD_ERR);
}
@@ -1153,11 +1283,12 @@ print_enum(const char *type, const char *name, mdb_ctf_id_t id,
mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
{
mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
- char vname[MDB_SYM_NAMLEN];
const char *ename;
int value;
+ int isp2 = enum_is_p2(base);
+ int flags = pap->pa_flags | (isp2 ? PA_INTHEX : 0);
- if (!(pap->pa_flags & PA_SHOWVAL))
+ if (!(flags & PA_SHOWVAL))
return (0);
if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as,
@@ -1166,19 +1297,23 @@ print_enum(const char *type, const char *name, mdb_ctf_id_t id,
return (1);
}
- if (pap->pa_flags & PA_INTHEX)
+ if (flags & PA_INTHEX)
mdb_printf("%#x", value);
else
mdb_printf("%#d", value);
- ename = mdb_ctf_enum_name(base, value);
+ (void) mdb_inc_indent(8);
+ mdb_printf(" (");
- /* If it wasn't an exact match, check if we can do P2 matching */
- if (ename == NULL &&
- enum_value_to_name_p2(base, value, vname, sizeof (vname)) == 0)
- ename = vname;
-
- mdb_printf(" (%s)", (ename != NULL)? ename : "???");
+ if (!isp2 || enum_value_print_p2(base, value, 0) != 0) {
+ ename = mdb_ctf_enum_name(base, value);
+ if (ename == NULL) {
+ ename = "???";
+ }
+ mdb_printf("%s", ename);
+ }
+ mdb_printf(")");
+ (void) mdb_dec_indent(8);
return (0);
}
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_print.h b/usr/src/cmd/mdb/common/mdb/mdb_print.h
index a9a7a4ac65..2e7a23918c 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_print.h
+++ b/usr/src/cmd/mdb/common/mdb/mdb_print.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _MDB_PRINT_H
#define _MDB_PRINT_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -36,6 +33,7 @@ extern "C" {
#ifdef _MDB
extern int cmd_enum(uintptr_t, uint_t, int, const mdb_arg_t *);
+extern void enum_help(void);
extern int cmd_sizeof(uintptr_t, uint_t, int, const mdb_arg_t *);
extern int cmd_offsetof(uintptr_t, uint_t, int, const mdb_arg_t *);
extern int cmd_list(uintptr_t, uint_t, int, const mdb_arg_t *);
diff --git a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
index 1d45564e4b..b52992c8d0 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
+++ b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
@@ -66,6 +66,7 @@ GENUNIX_SRCS = \
sobj.c \
streams.c \
sysevent.c \
+ taskq.c \
thread.c \
tsd.c \
tsol.c \
diff --git a/usr/src/cmd/mdb/common/modules/genunix/findstack.c b/usr/src/cmd/mdb/common/modules/genunix/findstack.c
index 655451f780..ccb50ae26e 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/findstack.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/findstack.c
@@ -690,7 +690,36 @@ stacks_thread_cb(uintptr_t addr, const void *ignored, void *cbarg)
}
int
-stacks_run(int verbose)
+stacks_run_tlist(mdb_pipe_t *tlist, stacks_info_t *si)
+{
+ size_t idx;
+ size_t found = 0;
+ kthread_t kt;
+ int ret;
+
+ for (idx = 0; idx < tlist->pipe_len; idx++) {
+ uintptr_t addr = tlist->pipe_data[idx];
+
+ if (mdb_vread(&kt, sizeof (kt), addr) == -1) {
+ mdb_warn("unable to read kthread_t at %p", addr);
+ continue;
+ }
+ found++;
+
+ ret = stacks_thread_cb(addr, &kt, si);
+ if (ret == WALK_DONE)
+ break;
+ if (ret != WALK_NEXT)
+ return (-1);
+ }
+
+ if (found)
+ return (0);
+ return (-1);
+}
+
+int
+stacks_run(int verbose, mdb_pipe_t *tlist)
{
stacks_info_t si;
findstack_info_t *fsip = &si.si_fsi;
@@ -714,9 +743,14 @@ stacks_run(int verbose)
if (verbose)
mdb_warn("stacks: processing kernel threads\n");
- if (mdb_walk("thread", stacks_thread_cb, &si) != 0) {
- mdb_warn("cannot walk \"thread\"");
- return (DCMD_ERR);
+ if (tlist != NULL) {
+ if (stacks_run_tlist(tlist, &si))
+ return (DCMD_ERR);
+ } else {
+ if (mdb_walk("thread", stacks_thread_cb, &si) != 0) {
+ mdb_warn("cannot walk \"thread\"");
+ return (DCMD_ERR);
+ }
}
if (verbose)
@@ -745,7 +779,8 @@ stacks_run(int verbose)
stacks_hash = NULL;
mdb_free(si.si_hash, STACKS_HSIZE * sizeof (*si.si_hash));
- stacks_state = STACKS_STATE_DONE;
+ if (tlist == NULL)
+ stacks_state = STACKS_STATE_DONE;
if (verbose)
mdb_warn("stacks: done\n");
@@ -959,6 +994,7 @@ stacks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
const char *excl_tstate_str = NULL;
uint_t tstate = -1U;
uint_t excl_tstate = -1U;
+ uint_t printed = 0;
uint_t all = 0;
uint_t force = 0;
@@ -1066,27 +1102,6 @@ stacks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
/*
- * Force a cleanup if we're connected to a live system. Never
- * do a cleanup after the first invocation around the loop.
- */
- force |= (mdb_get_state() == MDB_STATE_RUNNING);
- if (force && (flags & (DCMD_LOOPFIRST|DCMD_LOOP)) == DCMD_LOOP)
- force = 0;
-
- stacks_cleanup(force);
-
- if (stacks_state == STACKS_STATE_CLEAN) {
- int res = stacks_run(verbose);
- if (res != DCMD_OK)
- return (res);
- }
-
- if (!all && DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
- mdb_printf("%<u>%-?s %-8s %-?s %8s%</u>\n",
- "THREAD", "STATE", "SOBJ", "COUNT");
- }
-
- /*
* If there's an address specified, we're going to further filter
* to only entries which have an address in the input. To reduce
* overhead (and make the sorted output come out right), we
@@ -1120,6 +1135,22 @@ stacks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
seen = mdb_zalloc(p.pipe_len, UM_SLEEP | UM_GC);
}
+ /*
+ * Force a cleanup if we're connected to a live system. Never
+ * do a cleanup after the first invocation around the loop.
+ */
+ force |= (mdb_get_state() == MDB_STATE_RUNNING);
+ if (force && (flags & (DCMD_LOOPFIRST|DCMD_LOOP)) == DCMD_LOOP)
+ force = 0;
+
+ stacks_cleanup(force);
+
+ if (stacks_state == STACKS_STATE_CLEAN) {
+ int res = stacks_run(verbose, addrspec ? &p : NULL);
+ if (res != DCMD_OK)
+ return (res);
+ }
+
for (idx = 0; idx < stacks_array_size; idx++) {
stacks_entry_t *sep = stacks_array[idx];
stacks_entry_t *cur = sep;
@@ -1209,9 +1240,10 @@ stacks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
continue;
}
- if (all) {
+ if (all || !printed) {
mdb_printf("%<u>%-?s %-8s %-?s %8s%</u>\n",
- "THREAD", "STATE", "SOBJTYPE", "COUNT");
+ "THREAD", "STATE", "SOBJ", "COUNT");
+ printed = 1;
}
do {
diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
index 912d5f7ce7..f27684baf6 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
@@ -58,8 +58,6 @@
#include <sys/sysconf.h>
#include <sys/task.h>
#include <sys/project.h>
-#include <sys/taskq.h>
-#include <sys/taskq_impl.h>
#include <sys/errorq_impl.h>
#include <sys/cred_impl.h>
#include <sys/zone.h>
@@ -101,6 +99,7 @@
#include "sobj.h"
#include "streams.h"
#include "sysevent.h"
+#include "taskq.h"
#include "thread.h"
#include "tsd.h"
#include "tsol.h"
@@ -3853,115 +3852,6 @@ sysfile(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
-/*
- * Dump a taskq_ent_t given its address.
- */
-/*ARGSUSED*/
-int
-taskq_ent(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- taskq_ent_t taskq_ent;
- GElf_Sym sym;
- char buf[MDB_SYM_NAMLEN+1];
-
-
- if (!(flags & DCMD_ADDRSPEC)) {
- mdb_warn("expected explicit taskq_ent_t address before ::\n");
- return (DCMD_USAGE);
- }
-
- if (mdb_vread(&taskq_ent, sizeof (taskq_ent_t), addr) == -1) {
- mdb_warn("failed to read taskq_ent_t at %p", addr);
- return (DCMD_ERR);
- }
-
- if (DCMD_HDRSPEC(flags)) {
- mdb_printf("%<u>%-?s %-?s %-s%</u>\n",
- "ENTRY", "ARG", "FUNCTION");
- }
-
- if (mdb_lookup_by_addr((uintptr_t)taskq_ent.tqent_func, MDB_SYM_EXACT,
- buf, sizeof (buf), &sym) == -1) {
- (void) strcpy(buf, "????");
- }
-
- mdb_printf("%-?p %-?p %s\n", addr, taskq_ent.tqent_arg, buf);
-
- return (DCMD_OK);
-}
-
-/*
- * Given the address of the (taskq_t) task queue head, walk the queue listing
- * the address of every taskq_ent_t.
- */
-int
-taskq_walk_init(mdb_walk_state_t *wsp)
-{
- taskq_t tq_head;
-
-
- if (wsp->walk_addr == NULL) {
- mdb_warn("start address required\n");
- return (WALK_ERR);
- }
-
-
- /*
- * Save the address of the list head entry. This terminates the list.
- */
- wsp->walk_data = (void *)
- ((size_t)wsp->walk_addr + offsetof(taskq_t, tq_task));
-
-
- /*
- * Read in taskq head, set walk_addr to point to first taskq_ent_t.
- */
- if (mdb_vread((void *)&tq_head, sizeof (taskq_t), wsp->walk_addr) ==
- -1) {
- mdb_warn("failed to read taskq list head at %p",
- wsp->walk_addr);
- }
- wsp->walk_addr = (uintptr_t)tq_head.tq_task.tqent_next;
-
-
- /*
- * Check for null list (next=head)
- */
- if (wsp->walk_addr == (uintptr_t)wsp->walk_data) {
- return (WALK_DONE);
- }
-
- return (WALK_NEXT);
-}
-
-
-int
-taskq_walk_step(mdb_walk_state_t *wsp)
-{
- taskq_ent_t tq_ent;
- int status;
-
-
- if (mdb_vread((void *)&tq_ent, sizeof (taskq_ent_t), wsp->walk_addr) ==
- -1) {
- mdb_warn("failed to read taskq_ent_t at %p", wsp->walk_addr);
- return (DCMD_ERR);
- }
-
- status = wsp->walk_callback(wsp->walk_addr, (void *)&tq_ent,
- wsp->walk_cbdata);
-
- wsp->walk_addr = (uintptr_t)tq_ent.tqent_next;
-
-
- /* Check if we're at the last element (next=head) */
- if (wsp->walk_addr == (uintptr_t)wsp->walk_data) {
- return (WALK_DONE);
- }
-
- return (status);
-}
-
int
didmatch(uintptr_t addr, const kthread_t *thr, kt_did_t *didp)
{
@@ -4325,7 +4215,6 @@ static const mdb_dcmd_t dcmds[] = {
"print sysevent subclass list", sysevent_subclass_list},
{ "system", NULL, "print contents of /etc/system file", sysfile },
{ "task", NULL, "display kernel task(s)", task },
- { "taskq_entry", ":", "display a taskq_ent_t", taskq_ent },
{ "vnode2path", ":[-F]", "vnode address to pathname", vnode2path },
{ "vnode2smap", ":[offset]", "translate vnode to smap", vnode2smap },
{ "whereopen", ":", "given a vnode, dumps procs which have it open",
@@ -4571,6 +4460,11 @@ static const mdb_dcmd_t dcmds[] = {
"filter and display STREAM sync queue", syncq, syncq_help },
{ "syncq2q", ":", "print queue for a given syncq", syncq2q },
+ /* from taskq.c */
+ { "taskq", ":[-atT] [-m min_maxq] [-n name]",
+ "display a taskq", taskq, taskq_help },
+ { "taskq_entry", ":", "display a taskq_ent_t", taskq_ent },
+
/* from thread.c */
{ "thread", "?[-bdfimps]", "display a summarized kthread_t", thread,
thread_help },
@@ -4672,8 +4566,6 @@ static const mdb_walker_t walkers[] = {
sysevent_subclass_list_walk_fini},
{ "task", "given a task pointer, walk its processes",
task_walk_init, task_walk_step, NULL },
- { "taskq_entry", "given a taskq_t*, list all taskq_ent_t in the list",
- taskq_walk_init, taskq_walk_step, NULL, NULL },
/* from avl.c */
{ AVL_WALK_NAME, AVL_WALK_DESC,
@@ -4929,6 +4821,14 @@ static const mdb_walker_t walkers[] = {
{ "writeq", "walk write queue side of stdata",
str_walk_init, strw_walk_step, str_walk_fini },
+ /* from taskq.c */
+ { "taskq_thread", "given a taskq_t, list all of its threads",
+ taskq_thread_walk_init,
+ taskq_thread_walk_step,
+ taskq_thread_walk_fini },
+ { "taskq_entry", "given a taskq_t*, list all taskq_ent_t in the list",
+ taskq_ent_walk_init, taskq_ent_walk_step, NULL },
+
/* from thread.c */
{ "deathrow", "walk threads on both lwp_ and thread_deathrow",
deathrow_walk_init, deathrow_walk_step, NULL },
diff --git a/usr/src/cmd/mdb/common/modules/genunix/taskq.c b/usr/src/cmd/mdb/common/modules/genunix/taskq.c
new file mode 100644
index 0000000000..03e199cc3b
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/genunix/taskq.c
@@ -0,0 +1,483 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <mdb/mdb_param.h>
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
+#include <sys/taskq.h>
+#include <sys/taskq_impl.h>
+
+#include "taskq.h"
+
+typedef struct tqarray_ent {
+ uintptr_t tq_addr;
+ char tq_name[TASKQ_NAMELEN + 1];
+ int tq_instance;
+ uint_t tq_flags;
+} tqarray_ent_t;
+
+typedef struct tq_info {
+ tqarray_ent_t *tqi_array;
+ size_t tqi_count;
+ size_t tqi_size;
+} tq_info_t;
+
+/*
+ * We sort taskqs as follows:
+ *
+ * DYNAMIC last
+ * NOINSTANCE first
+ * within NOINSTANCE, sort by order of creation (instance #)
+ * within non-NOINSTANCE, sort by name (case-insensitive) then instance #
+ */
+int
+tqcmp(const void *lhs, const void *rhs)
+{
+ const tqarray_ent_t *l = lhs;
+ const tqarray_ent_t *r = rhs;
+ uint_t lflags = l->tq_flags;
+ uint_t rflags = r->tq_flags;
+ int ret;
+
+ if ((lflags & TASKQ_DYNAMIC) && !(rflags & TASKQ_DYNAMIC))
+ return (1);
+ if (!(lflags & TASKQ_DYNAMIC) && (rflags & TASKQ_DYNAMIC))
+ return (-1);
+
+ if ((lflags & TASKQ_NOINSTANCE) && !(rflags & TASKQ_NOINSTANCE))
+ return (-1);
+ if (!(lflags & TASKQ_NOINSTANCE) && (rflags & TASKQ_NOINSTANCE))
+ return (1);
+
+ if (!(lflags & TASKQ_NOINSTANCE) &&
+ (ret = strcasecmp(l->tq_name, r->tq_name)) != 0)
+ return (ret);
+
+ if (l->tq_instance < r->tq_instance)
+ return (-1);
+ if (l->tq_instance > r->tq_instance)
+ return (1);
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+tq_count(uintptr_t addr, const void *ignored, void *arg)
+{
+ tq_info_t *ti = arg;
+
+ ti->tqi_size++;
+ return (WALK_NEXT);
+}
+
+/*ARGSUSED*/
+int
+tq_fill(uintptr_t addr, const void *ignored, tq_info_t *ti)
+{
+ int idx = ti->tqi_count;
+ taskq_t tq;
+ tqarray_ent_t *tqe = &ti->tqi_array[idx];
+
+ if (idx == ti->tqi_size) {
+ mdb_warn("taskq: inadequate slop\n");
+ return (WALK_ERR);
+ }
+ if (mdb_vread(&tq, sizeof (tq), addr) == -1) {
+ mdb_warn("unable to read taskq_t at %p", addr);
+ return (WALK_NEXT);
+ }
+
+ ti->tqi_count++;
+ tqe->tq_addr = addr;
+ strncpy(tqe->tq_name, tq.tq_name, TASKQ_NAMELEN);
+ tqe->tq_instance = tq.tq_instance;
+ tqe->tq_flags = tq.tq_flags;
+
+ return (WALK_NEXT);
+}
+
+void
+taskq_help(void)
+{
+ mdb_printf("%s",
+ " -a Only show taskqs with active threads.\n"
+ " -t Display active thread stacks in each taskq.\n"
+ " -T Display all thread stacks in each taskq.\n"
+ " -m min_maxq\n"
+ " Only show Dynamic taskqs and taskqs with a MAXQ of at\n"
+ " least min_maxq.\n"
+ " -n name\n"
+ " Only show taskqs which contain name somewhere in their\n"
+ " name.\n");
+}
+
+int
+taskq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ taskq_t tq;
+
+ const char *name = NULL;
+ uintptr_t minmaxq = 0;
+ uint_t active = FALSE;
+ uint_t print_threads = FALSE;
+ uint_t print_threads_all = FALSE;
+
+ size_t tact, tcount, queued, maxq;
+
+ if (mdb_getopts(argc, argv,
+ 'a', MDB_OPT_SETBITS, TRUE, &active,
+ 'm', MDB_OPT_UINTPTR, &minmaxq,
+ 'n', MDB_OPT_STR, &name,
+ 't', MDB_OPT_SETBITS, TRUE, &print_threads,
+ 'T', MDB_OPT_SETBITS, TRUE, &print_threads_all,
+ NULL) != argc)
+ return (DCMD_USAGE);
+
+ if (!(flags & DCMD_ADDRSPEC)) {
+ size_t idx;
+ tq_info_t tqi;
+
+ bzero(&tqi, sizeof (tqi));
+
+ if (mdb_walk("taskq_cache", tq_count, &tqi) == -1) {
+ mdb_warn("unable to walk taskq_cache");
+ return (DCMD_ERR);
+ }
+ tqi.tqi_size += 10; /* slop */
+ tqi.tqi_array = mdb_zalloc(
+ sizeof (*tqi.tqi_array) * tqi.tqi_size, UM_SLEEP|UM_GC);
+
+ if (mdb_walk("taskq_cache", (mdb_walk_cb_t)tq_fill,
+ &tqi) == -1) {
+ mdb_warn("unable to walk taskq_cache");
+ return (DCMD_ERR);
+ }
+ qsort(tqi.tqi_array, tqi.tqi_count, sizeof (*tqi.tqi_array),
+ tqcmp);
+
+ flags &= ~DCMD_PIPE;
+ flags |= DCMD_LOOP | DCMD_LOOPFIRST | DCMD_ADDRSPEC;
+ for (idx = 0; idx < tqi.tqi_count; idx++) {
+ int ret = taskq(tqi.tqi_array[idx].tq_addr, flags,
+ argc, argv);
+ if (ret != DCMD_OK)
+ return (ret);
+ flags &= ~DCMD_LOOPFIRST;
+ }
+
+ return (DCMD_OK);
+ }
+
+ if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
+ mdb_printf("%<u>%-?s %-31s %4s/%4s %4s %5s %4s%</u>\n",
+ "ADDR", "NAME", "ACT", "THDS",
+ "Q'ED", "MAXQ", "INST");
+ }
+
+ if (mdb_vread(&tq, sizeof (tq), addr) == -1) {
+ mdb_warn("failed to read taskq_t at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ /* terminate the name, just in case */
+ tq.tq_name[sizeof (tq.tq_name) - 1] = 0;
+
+ tact = tq.tq_active;
+ tcount = tq.tq_nthreads;
+ queued = tq.tq_tasks - tq.tq_executed;
+ maxq = tq.tq_maxtasks;
+
+ if (tq.tq_flags & TASKQ_DYNAMIC) {
+ size_t bsize = tq.tq_nbuckets * sizeof (*tq.tq_buckets);
+ size_t idx;
+ taskq_bucket_t *b = mdb_zalloc(bsize, UM_SLEEP | UM_GC);
+
+ if (mdb_vread(b, bsize, (uintptr_t)tq.tq_buckets) == -1) {
+ mdb_warn("unable to read buckets for taskq %p", addr);
+ return (DCMD_ERR);
+ }
+
+ tcount += (tq.tq_tcreates - tq.tq_tdeaths);
+
+ for (idx = 0; idx < tq.tq_nbuckets; idx++) {
+ tact += b[idx].tqbucket_nalloc;
+ }
+ }
+
+ /* filter out taskqs that aren't of interest. */
+ if (name != NULL && strstr(tq.tq_name, name) == NULL)
+ return (DCMD_OK);
+ if (active && tact == 0 && queued == 0)
+ return (DCMD_OK);
+ if (!(tq.tq_flags & TASKQ_DYNAMIC) && maxq < minmaxq)
+ return (DCMD_OK);
+
+ if (flags & DCMD_PIPE_OUT) {
+ mdb_printf("%#lr\n", addr);
+ return (DCMD_OK);
+ }
+
+ mdb_printf("%?p %-31s %4d/%4d %4d ",
+ addr, tq.tq_name, tact, tcount, queued);
+
+ if (tq.tq_flags & TASKQ_DYNAMIC)
+ mdb_printf("%5s ", "-");
+ else
+ mdb_printf("%5d ", maxq);
+
+ if (tq.tq_flags & TASKQ_NOINSTANCE)
+ mdb_printf("%4s", "-");
+ else
+ mdb_printf("%4x", tq.tq_instance);
+
+ mdb_printf("\n");
+
+ if (print_threads || print_threads_all) {
+ int ret;
+ char strbuf[128];
+ const char *arg =
+ print_threads_all ? "" : "-C \"taskq_thread_wait\"";
+
+ /*
+ * We can't use mdb_pwalk_dcmd() here, because ::stacks needs
+ * to get the full pipeline.
+ */
+ mdb_snprintf(strbuf, sizeof (strbuf),
+ "%p::walk taskq_thread | ::stacks -a %s",
+ addr, arg);
+
+ (void) mdb_inc_indent(4);
+ ret = mdb_eval(strbuf);
+ (void) mdb_dec_indent(4);
+
+ /* abort, since they could have control-Ced the eval */
+ if (ret == -1)
+ return (DCMD_ABORT);
+ }
+
+ return (DCMD_OK);
+}
+
+/*
+ * Dump a taskq_ent_t given its address.
+ */
+/*ARGSUSED*/
+int
+taskq_ent(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ taskq_ent_t taskq_ent;
+
+ if (!(flags & DCMD_ADDRSPEC)) {
+ return (DCMD_USAGE);
+ }
+
+ if (mdb_vread(&taskq_ent, sizeof (taskq_ent_t), addr) == -1) {
+ mdb_warn("failed to read taskq_ent_t at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ if (DCMD_HDRSPEC(flags)) {
+ mdb_printf("%<u>%-?s %-?s %-s%</u>\n",
+ "ENTRY", "ARG", "FUNCTION");
+ }
+
+ mdb_printf("%-?p %-?p %a\n", addr, taskq_ent.tqent_arg,
+ taskq_ent.tqent_func);
+
+ return (DCMD_OK);
+}
+
+
+/*
+ * Given the address of the (taskq_t) task queue head, walk the queue listing
+ * the address of every taskq_ent_t.
+ */
+int
+taskq_ent_walk_init(mdb_walk_state_t *wsp)
+{
+ taskq_t tq_head;
+
+
+ if (wsp->walk_addr == NULL) {
+ mdb_warn("start address required\n");
+ return (WALK_ERR);
+ }
+
+
+ /*
+ * Save the address of the list head entry. This terminates the list.
+ */
+ wsp->walk_data = (void *)
+ ((size_t)wsp->walk_addr + OFFSETOF(taskq_t, tq_task));
+
+
+ /*
+ * Read in taskq head, set walk_addr to point to first taskq_ent_t.
+ */
+ if (mdb_vread((void *)&tq_head, sizeof (taskq_t), wsp->walk_addr) ==
+ -1) {
+ mdb_warn("failed to read taskq list head at %p",
+ wsp->walk_addr);
+ }
+ wsp->walk_addr = (uintptr_t)tq_head.tq_task.tqent_next;
+
+
+ /*
+ * Check for null list (next=head)
+ */
+ if (wsp->walk_addr == (uintptr_t)wsp->walk_data) {
+ return (WALK_DONE);
+ }
+
+ return (WALK_NEXT);
+}
+
+
+int
+taskq_ent_walk_step(mdb_walk_state_t *wsp)
+{
+ taskq_ent_t tq_ent;
+ int status;
+
+
+ if (mdb_vread((void *)&tq_ent, sizeof (taskq_ent_t), wsp->walk_addr) ==
+ -1) {
+ mdb_warn("failed to read taskq_ent_t at %p", wsp->walk_addr);
+ return (DCMD_ERR);
+ }
+
+ status = wsp->walk_callback(wsp->walk_addr, (void *)&tq_ent,
+ wsp->walk_cbdata);
+
+ wsp->walk_addr = (uintptr_t)tq_ent.tqent_next;
+
+
+ /* Check if we're at the last element (next=head) */
+ if (wsp->walk_addr == (uintptr_t)wsp->walk_data) {
+ return (WALK_DONE);
+ }
+
+ return (status);
+}
+
+typedef struct taskq_thread_info {
+ uintptr_t tti_addr;
+ uintptr_t *tti_tlist;
+ size_t tti_nthreads;
+ size_t tti_idx;
+
+ kthread_t tti_thread;
+} taskq_thread_info_t;
+
+int
+taskq_thread_walk_init(mdb_walk_state_t *wsp)
+{
+ taskq_thread_info_t *tti;
+ taskq_t tq;
+ uintptr_t *tlist;
+ size_t nthreads;
+
+ tti = wsp->walk_data = mdb_zalloc(sizeof (*tti), UM_SLEEP);
+ tti->tti_addr = wsp->walk_addr;
+
+ if (wsp->walk_addr != NULL &&
+ mdb_vread(&tq, sizeof (tq), wsp->walk_addr) != -1 &&
+ !(tq.tq_flags & TASKQ_DYNAMIC)) {
+
+ nthreads = tq.tq_nthreads;
+ tlist = mdb_alloc(nthreads * sizeof (*tlist), UM_SLEEP);
+ if (tq.tq_nthreads_max == 1) {
+ tlist[0] = (uintptr_t)tq.tq_thread;
+
+ } else if (mdb_vread(tlist, nthreads * sizeof (*tlist),
+ (uintptr_t)tq.tq_threadlist) == -1) {
+ mdb_warn("unable to read threadlist for taskq_t %p",
+ wsp->walk_addr);
+ mdb_free(tlist, nthreads * sizeof (*tlist));
+ return (WALK_ERR);
+ }
+
+ tti->tti_tlist = tlist;
+ tti->tti_nthreads = nthreads;
+ return (WALK_NEXT);
+ }
+
+ wsp->walk_addr = 0;
+ if (mdb_layered_walk("thread", wsp) == -1) {
+ mdb_warn("can't walk \"thread\"");
+ return (WALK_ERR);
+ }
+ return (0);
+}
+
+int
+taskq_thread_walk_step(mdb_walk_state_t *wsp)
+{
+ taskq_thread_info_t *tti = wsp->walk_data;
+
+ const kthread_t *kt = wsp->walk_layer;
+ taskq_t *tq = (taskq_t *)tti->tti_addr;
+
+ if (kt == NULL) {
+ uintptr_t addr;
+
+ if (tti->tti_idx >= tti->tti_nthreads)
+ return (WALK_DONE);
+
+ addr = tti->tti_tlist[tti->tti_idx];
+ tti->tti_idx++;
+
+ if (addr == NULL)
+ return (WALK_NEXT);
+
+ if (mdb_vread(&tti->tti_thread, sizeof (kthread_t),
+ addr) == -1) {
+ mdb_warn("unable to read kthread_t at %p", addr);
+ return (WALK_ERR);
+ }
+ return (wsp->walk_callback(addr, &tti->tti_thread,
+ wsp->walk_cbdata));
+ }
+
+ if (kt->t_taskq == NULL)
+ return (WALK_NEXT);
+
+ if (tq != NULL && kt->t_taskq != tq)
+ return (WALK_NEXT);
+
+ return (wsp->walk_callback(wsp->walk_addr, kt, wsp->walk_cbdata));
+}
+
+void
+taskq_thread_walk_fini(mdb_walk_state_t *wsp)
+{
+ taskq_thread_info_t *tti = wsp->walk_data;
+
+ if (tti->tti_nthreads > 0) {
+ mdb_free(tti->tti_tlist,
+ tti->tti_nthreads * sizeof (*tti->tti_tlist));
+ }
+ mdb_free(tti, sizeof (*tti));
+}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/taskq.h b/usr/src/cmd/mdb/common/modules/genunix/taskq.h
new file mode 100644
index 0000000000..dfa2c9e8bd
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/genunix/taskq.h
@@ -0,0 +1,49 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _TASKQ_H
+#define _TASKQ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int taskq(uintptr_t, uint_t, int, const mdb_arg_t *);
+extern void taskq_help(void);
+
+extern int taskq_ent(uintptr_t, uint_t, int, const mdb_arg_t *);
+
+extern int taskq_ent_walk_init(mdb_walk_state_t *);
+extern int taskq_ent_walk_step(mdb_walk_state_t *);
+
+extern int taskq_thread_walk_init(mdb_walk_state_t *);
+extern int taskq_thread_walk_step(mdb_walk_state_t *);
+extern void taskq_thread_walk_fini(mdb_walk_state_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TASKQ_H */
diff --git a/usr/src/cmd/svc/configd/Makefile b/usr/src/cmd/svc/configd/Makefile
index 1633687fe9..2a03c20f7b 100644
--- a/usr/src/cmd/svc/configd/Makefile
+++ b/usr/src/cmd/svc/configd/Makefile
@@ -40,7 +40,7 @@ OBJS = $(MYOBJS)
SRCS = $(MYOBJS:%.o=%.c)
include ../../Makefile.cmd
-include ../Makefile.ctf
+include ../../Makefile.ctf
NATIVE_BUILD=$(POUND_SIGN)
$(NATIVE_BUILD)PROG = $(MYPROG:%=%-native)
@@ -95,11 +95,11 @@ native: FRC
@NATIVE_BUILD= $(MAKE) $(MFLAGS) all
$(PROG): $(OBJS)
- $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(CTFMERGE_HOOK)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
%-native.o: %.c
- $(COMPILE.c) -o $@ $< $(CTFCONVERT_HOOK)
+ $(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
$(ROOTCMDDIR)/%: %.sh
diff --git a/usr/src/cmd/svc/prophist/Makefile b/usr/src/cmd/svc/prophist/Makefile
index 93289e9904..cffc97f298 100644
--- a/usr/src/cmd/svc/prophist/Makefile
+++ b/usr/src/cmd/svc/prophist/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
PROG = prophist
OBJS = prophist.o \
@@ -37,7 +35,7 @@ SRCS = prophist.c \
POFILES = $(OBJS:.o=.po)
include ../../Makefile.cmd
-include ../Makefile.ctf
+include ../../Makefile.ctf
ROOTCMDDIR= $(ROOT)/lib/svc/bin
@@ -56,7 +54,7 @@ lint := LINTFLAGS = -mux
all: $(PROG)
$(PROG): $(OBJS)
- $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(CTFMERGE_HOOK)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
install: all $(ROOTCMD) $(ROOTPROPHIST)
@@ -68,7 +66,7 @@ lint: $(LNTS)
$(LINT.c) $(LINTFLAGS) $(LNTS) $(LDLIBS)
%.o: ../common/%.c
- $(COMPILE.c) $(OUTPUT_OPTION) $< $(CTFCONVERT_HOOK)
+ $(COMPILE.c) $(OUTPUT_OPTION) $<
$(POST_PROCESS_O)
%.ln: ../common/%.c
diff --git a/usr/src/cmd/svc/req.flg b/usr/src/cmd/svc/req.flg
index ef651ef257..ad9eba8364 100644
--- a/usr/src/cmd/svc/req.flg
+++ b/usr/src/cmd/svc/req.flg
@@ -3,9 +3,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -21,13 +20,11 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
-echo_file usr/src/cmd/svc/Makefile.ctf
+echo_file usr/src/cmd/Makefile.ctf
find_files "s.*" \
usr/src/cmd/svc/common \
usr/src/common/svc \
diff --git a/usr/src/cmd/svc/servinfo/Makefile b/usr/src/cmd/svc/servinfo/Makefile
index 43bcfedb6f..76f86f5d72 100644
--- a/usr/src/cmd/svc/servinfo/Makefile
+++ b/usr/src/cmd/svc/servinfo/Makefile
@@ -29,7 +29,7 @@ SRCS = $(OBJS:%.o=%.c)
POFILES = $(OBJS:.o=.po)
include ../../Makefile.cmd
-include ../Makefile.ctf
+include ../../Makefile.ctf
LDLIBS += -lnsl -lsocket
@@ -40,7 +40,7 @@ lint := LINTFLAGS = -ux
all: $(PROG)
$(PROG): $(OBJS)
- $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(CTFMERGE_HOOK)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
install: all $(ROOTLIBPROG)
diff --git a/usr/src/cmd/svc/startd/Makefile b/usr/src/cmd/svc/startd/Makefile
index 00ada48f5b..f20283e974 100644
--- a/usr/src/cmd/svc/startd/Makefile
+++ b/usr/src/cmd/svc/startd/Makefile
@@ -52,7 +52,7 @@ SRCS = $(OBJS:%.o=%.c)
POFILES = $(ALLOBJS:%.o=%.po)
include ../../Makefile.cmd
-include ../Makefile.ctf
+include ../../Makefile.ctf
ROOTCMDDIR= $(ROOT)/lib/svc/bin
@@ -93,7 +93,7 @@ lint_SRCS := CPPFLAGS += \
all: $(PROG)
$(PROG): $(ALLOBJS)
- $(LINK.c) -o $@ $(ALLOBJS) $(LDLIBS) $(CTFMERGE_HOOK)
+ $(LINK.c) -o $@ $(ALLOBJS) $(LDLIBS)
$(POST_PROCESS)
$(POFILE): $(POFILES)
diff --git a/usr/src/cmd/svc/svccfg/Makefile b/usr/src/cmd/svc/svccfg/Makefile
index 5f0925d3e4..b0c9b8deac 100644
--- a/usr/src/cmd/svc/svccfg/Makefile
+++ b/usr/src/cmd/svc/svccfg/Makefile
@@ -50,7 +50,7 @@ POFILES = $(SRCS:%.c=%.po) \
../common/manifest_hash.po
include ../../Makefile.cmd
-include ../Makefile.ctf
+include ../../Makefile.ctf
POFILE = $(PROG)_all.po
@@ -120,7 +120,7 @@ native: FRC
@NATIVE_BUILD= $(MAKE) $(MFLAGS) all
$(PROG): $(OBJS) $(MAPFILES)
- $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(CTFMERGE_HOOK)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
$(POFILE): $(POFILES)
@@ -146,15 +146,15 @@ lint: $(LNTS)
$(LINT.c) $(LINTFLAGS) $(LNTS) $(LDLIBS)
%-native.o: %.c
- $(COMPILE.c) -o $@ $< $(CTFCONVERT_HOOK)
+ $(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
%-native.o: ../common/%.c
- $(COMPILE.c) -o $@ $< $(CTFCONVERT_HOOK)
+ $(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
%.o: ../common/%.c
- $(COMPILE.c) $(OUTPUT_OPTION) $< $(CTFCONVERT_HOOK)
+ $(COMPILE.c) $(OUTPUT_OPTION) $<
$(POST_PROCESS_O)
%.ln: ../common/%.c
diff --git a/usr/src/cmd/svc/svcprop/Makefile b/usr/src/cmd/svc/svcprop/Makefile
index 6c454aad37..af09f6555d 100644
--- a/usr/src/cmd/svc/svcprop/Makefile
+++ b/usr/src/cmd/svc/svcprop/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
PROG = svcprop
OBJS = svcprop.o
@@ -31,7 +29,7 @@ SRCS = $(OBJS:%.o=%.c)
POFILES = $(OBJS:.o=.po)
include ../../Makefile.cmd
-include ../Makefile.ctf
+include ../../Makefile.ctf
LDLIBS += -lscf -luutil
@@ -42,7 +40,7 @@ lint := LINTFLAGS = -ux
all: $(PROG)
$(PROG): $(OBJS)
- $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(CTFMERGE_HOOK)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
install: all $(ROOTPROG)
diff --git a/usr/src/cmd/svc/svcs/Makefile b/usr/src/cmd/svc/svcs/Makefile
index a59857ef69..40cac2b232 100644
--- a/usr/src/cmd/svc/svcs/Makefile
+++ b/usr/src/cmd/svc/svcs/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
PROG = svcs
OBJS = svcs.o explain.o
@@ -31,7 +29,7 @@ SRCS = $(OBJS:%.o=%.c)
POFILES = $(OBJS:.o=.po)
include ../../Makefile.cmd
-include ../Makefile.ctf
+include ../../Makefile.ctf
POFILE = $(PROG)_all.po
LDLIBS += -lcontract -lscf -luutil -lumem
@@ -43,7 +41,7 @@ lint := LINTFLAGS = -ux
all: $(PROG)
$(PROG): $(OBJS)
- $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(CTFMERGE_HOOK)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
$(POFILE): $(POFILES)
diff --git a/usr/src/cmd/zdb/Makefile.com b/usr/src/cmd/zdb/Makefile.com
index de7f5a4a24..cd9dfb3bb3 100644
--- a/usr/src/cmd/zdb/Makefile.com
+++ b/usr/src/cmd/zdb/Makefile.com
@@ -29,6 +29,7 @@ SRCS= ../$(PROG).c ../zdb_il.c
OBJS= $(PROG).o zdb_il.o
include ../../Makefile.cmd
+include ../../Makefile.ctf
INCS += -I../../../lib/libzpool/common
INCS += -I../../../uts/common/fs/zfs
diff --git a/usr/src/cmd/zfs/Makefile b/usr/src/cmd/zfs/Makefile
index 3bd8a95242..ddebcb36db 100644
--- a/usr/src/cmd/zfs/Makefile
+++ b/usr/src/cmd/zfs/Makefile
@@ -30,6 +30,7 @@ POFILES= zfs_main.po zfs_iter.po
POFILE= zfs.po
include ../Makefile.cmd
+include ../Makefile.ctf
FSTYPE= zfs
LINKPROGS= mount umount
diff --git a/usr/src/cmd/zpool/Makefile b/usr/src/cmd/zpool/Makefile
index 9b2d4e3d07..728fdbe03b 100644
--- a/usr/src/cmd/zpool/Makefile
+++ b/usr/src/cmd/zpool/Makefile
@@ -30,6 +30,7 @@ POFILES=$(OBJS:%.o=%.po)
POFILE= zpool.po
include ../Makefile.cmd
+include ../Makefile.ctf
STATCOMMONDIR = $(SRC)/cmd/stat/common
diff --git a/usr/src/cmd/ztest/Makefile.com b/usr/src/cmd/ztest/Makefile.com
index c5695f0037..166d94edc8 100644
--- a/usr/src/cmd/ztest/Makefile.com
+++ b/usr/src/cmd/ztest/Makefile.com
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# 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.
@@ -20,16 +19,16 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
PROG= ztest
-SRCS= ../$(PROG).c
+OBJS= $(PROG).o
+SRCS= $(OBJS:%.o=../%.c)
include ../../Makefile.cmd
+include ../../Makefile.ctf
INCS += -I../../../lib/libzpool/common
INCS += -I../../../uts/common/fs/zfs
@@ -50,8 +49,8 @@ LINTFLAGS64 += -xerroff=E_NAME_DEF_NOT_USED2
all: $(PROG)
-$(PROG): $(SRCS)
- $(LINK.c) -o $(PROG) $(SRCS) $(LDLIBS)
+$(PROG): $(OBJS)
+ $(LINK.c) -o $(PROG) $(OBJS) $(LDLIBS)
$(POST_PROCESS)
clean:
@@ -59,3 +58,7 @@ clean:
lint: lint_SRCS
include ../../Makefile.targ
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/uts/common/os/taskq.c b/usr/src/uts/common/os/taskq.c
index 613d6a873c..93faf53dbc 100644
--- a/usr/src/uts/common/os/taskq.c
+++ b/usr/src/uts/common/os/taskq.c
@@ -203,7 +203,7 @@
*
* taskq:
* +-------------+
- * |tq_lock | +---< taskq_ent_free()
+ * | tq_lock | +---< taskq_ent_free()
* +-------------+ |
* |... | | tqent: tqent:
* +-------------+ | +------------+ +------------+
@@ -1238,16 +1238,29 @@ taskq_thread_create(taskq_t *tq)
t->t_taskq = tq;
}
-static void
-taskq_thread_wait(taskq_t *tq, kcondvar_t *cv, callb_cpr_t *cprinfo)
+/*
+ * Common "sleep taskq thread" function, which handles CPR stuff, as well
+ * as giving a nice common point for debuggers to find inactive threads.
+ */
+static clock_t
+taskq_thread_wait(taskq_t *tq, kmutex_t *mx, kcondvar_t *cv,
+ callb_cpr_t *cprinfo, clock_t timeout)
{
- if (tq->tq_flags & TASKQ_CPR_SAFE) {
- cv_wait(cv, &tq->tq_lock);
- } else {
+ clock_t ret = 0;
+
+ if (!(tq->tq_flags & TASKQ_CPR_SAFE)) {
CALLB_CPR_SAFE_BEGIN(cprinfo);
- cv_wait(cv, &tq->tq_lock);
- CALLB_CPR_SAFE_END(cprinfo, &tq->tq_lock);
}
+ if (timeout < 0)
+ cv_wait(cv, mx);
+ else
+ ret = cv_timedwait(cv, mx, lbolt + timeout);
+
+ if (!(tq->tq_flags & TASKQ_CPR_SAFE)) {
+ CALLB_CPR_SAFE_END(cprinfo, mx);
+ }
+
+ return (ret);
}
/*
@@ -1312,15 +1325,16 @@ taskq_thread(void *arg)
break;
/* Wait for higher thread_ids to exit */
- taskq_thread_wait(tq, &tq->tq_exit_cv,
- &cprinfo);
+ (void) taskq_thread_wait(tq, &tq->tq_lock,
+ &tq->tq_exit_cv, &cprinfo, -1);
continue;
}
}
if ((tqe = tq->tq_task.tqent_next) == &tq->tq_task) {
if (--tq->tq_active == 0)
cv_broadcast(&tq->tq_wait_cv);
- taskq_thread_wait(tq, &tq->tq_dispatch_cv, &cprinfo);
+ (void) taskq_thread_wait(tq, &tq->tq_lock,
+ &tq->tq_dispatch_cv, &cprinfo, -1);
tq->tq_active++;
continue;
}
@@ -1441,10 +1455,8 @@ taskq_d_thread(taskq_ent_t *tqe)
* If a thread is sleeping too long, it dies.
*/
if (! (bucket->tqbucket_flags & TQBUCKET_CLOSE)) {
- CALLB_CPR_SAFE_BEGIN(&cprinfo);
- w = cv_timedwait(cv, lock, lbolt +
- taskq_thread_timeout * hz);
- CALLB_CPR_SAFE_END(&cprinfo, lock);
+ w = taskq_thread_wait(tq, lock, cv,
+ &cprinfo, taskq_thread_timeout * hz);
}
/*