/*
* 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
* 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 <sys/taskq_impl.h>
#include "taskq.h"
typedef struct tqarray_ent {
int tq_instance;
typedef struct tq_info {
} 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
{
const tqarray_ent_t *l = lhs;
const tqarray_ent_t *r = rhs;
int ret;
return (1);
return (-1);
return (-1);
return (1);
if (!(lflags & TASKQ_NOINSTANCE) &&
return (ret);
if (l->tq_instance < r->tq_instance)
return (-1);
if (l->tq_instance > r->tq_instance)
return (1);
return (0);
}
/*ARGSUSED*/
int
{
return (WALK_NEXT);
}
/*ARGSUSED*/
int
{
mdb_warn("taskq: inadequate slop\n");
return (WALK_ERR);
}
return (WALK_NEXT);
}
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
{
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("unable to walk taskq_cache");
return (DCMD_ERR);
}
&tqi) == -1) {
mdb_warn("unable to walk taskq_cache");
return (DCMD_ERR);
}
tqcmp);
return (ret);
flags &= ~DCMD_LOOPFIRST;
}
return (DCMD_OK);
}
mdb_printf("%<u>%-?s %-31s %4s/%4s %4s %5s %4s%</u>\n",
"ADDR", "NAME", "ACT", "THDS",
"Q'ED", "MAXQ", "INST");
}
return (DCMD_ERR);
}
/* terminate the name, just in case */
return (DCMD_ERR);
}
}
}
/* filter out taskqs that aren't of interest. */
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
if (flags & DCMD_PIPE_OUT) {
return (DCMD_OK);
}
mdb_printf("%?p %-31s %4d/%4d %4d ",
else
else
mdb_printf("\n");
if (print_threads || print_threads_all) {
int ret;
const char *arg =
/*
* We can't use mdb_pwalk_dcmd() here, because ::stacks needs
* to get the full pipeline.
*/
"%p::walk taskq_thread | ::stacks -a %s",
(void) mdb_inc_indent(4);
(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
{
if (!(flags & DCMD_ADDRSPEC)) {
return (DCMD_USAGE);
}
return (DCMD_ERR);
}
if (DCMD_HDRSPEC(flags)) {
mdb_printf("%<u>%-?s %-?s %-s%</u>\n",
"ENTRY", "ARG", "FUNCTION");
}
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
{
mdb_warn("start address required\n");
return (WALK_ERR);
}
/*
* Save the address of the list head entry. This terminates the list.
*/
/*
* Read in taskq head, set walk_addr to point to first taskq_ent_t.
*/
-1) {
mdb_warn("failed to read taskq list head at %p",
}
/*
* Check for null list (next=head)
*/
return (WALK_DONE);
}
return (WALK_NEXT);
}
int
{
int status;
-1) {
return (DCMD_ERR);
}
wsp->walk_cbdata);
/* Check if we're at the last element (next=head) */
return (WALK_DONE);
}
return (status);
}
typedef struct taskq_thread_info {
int
{
mdb_warn("unable to read threadlist for taskq_t %p",
return (WALK_ERR);
}
return (WALK_NEXT);
}
mdb_warn("can't walk \"thread\"");
return (WALK_ERR);
}
return (0);
}
int
{
return (WALK_DONE);
return (WALK_NEXT);
addr) == -1) {
return (WALK_ERR);
}
wsp->walk_cbdata));
}
return (WALK_NEXT);
return (WALK_NEXT);
}
void
{
if (tti->tti_nthreads > 0) {
}
}