/*
* 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.
*
* 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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <mdb/mdb_modapi.h>
static int
{
char *priv;
{ NULL, 0, 0 }
};
switch (val->rcv_privilege) {
case (RCPRIV_BASIC):
priv = "basic";
break;
case (RCPRIV_PRIVILEGED):
priv = "privileged";
break;
case (RCPRIV_SYSTEM):
priv = "system";
break;
default:
priv = "???";
break;
};
mdb_printf("%-#18llx %11s\tflags=<%b>\n",
return (WALK_NEXT);
}
int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
if (argc != 0) {
else
return (DCMD_OK);
}
mdb_warn("failed to read dict entry for rctl_t %p at %p",
return (DCMD_ERR);
}
return (DCMD_ERR);
}
addr) == -1) {
return (DCMD_ERR);
}
return (DCMD_OK);
}
int
{
if (!(flags & DCMD_ADDRSPEC)) {
argv) == -1) {
mdb_warn("failed to walk 'rctl_dict_list'");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (DCMD_HDRSPEC(flags))
mdb_printf("%<u>%2s %-27s %?s %7s %s%</u>\n",
"ID", "NAME", "ADDR", "TYPE", "GLOBAL_FLAGS");
return (DCMD_ERR);
}
return (DCMD_ERR);
}
switch (dict.rcd_entity) {
case RCENTITY_PROCESS:
type = "process";
break;
case RCENTITY_TASK:
type = "task";
break;
case RCENTITY_PROJECT:
type = "project";
break;
case RCENTITY_ZONE:
type = "zone";
break;
default:
type = "unknown";
break;
}
return (DCMD_OK);
}
typedef struct dict_data {
} dict_data_t;
static int
{
return (WALK_DONE);
}
return (WALK_NEXT);
}
/*
* Print out all project, task, and process rctls for a given process.
* If a handle is specified, print only the rctl matching that handle
* for the process.
*/
int
{
int i;
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
if (argc == 0)
else if (argc == 1) {
/*
* User specified a handle. Go find the rctl_dict_entity_t
* structure so we know what type of rctl to look for.
*/
else
&rdict) == -1) {
mdb_warn("failed to walk rctl_dict_list");
return (DCMD_ERR);
}
/* Couldn't find a rctl_dict_entry_t for this handle */
return (DCMD_ERR);
} else
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_ERR);
}
return (DCMD_ERR);
}
return (DCMD_ERR);
}
for (i = 0; i <= RC_MAX_ENTITY; i++) {
/*
* If user didn't specify a handle, print rctls for all
* types. Otherwise, we can walk the rctl_set for only the
* entity specified by the handle.
*/
continue;
switch (i) {
case (RCENTITY_PROCESS):
break;
case (RCENTITY_TASK):
break;
case (RCENTITY_PROJECT):
break;
case (RCENTITY_ZONE):
break;
default:
mdb_warn("Unknown rctl type %d", i);
return (DCMD_ERR);
}
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
typedef struct dict_walk_data {
int num_dicts;
int num_cur;
int
{
int nlists;
mdb_warn("failed to find 'rctl_lists'\n");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int status;
mdb_warn("failed to read rctl_dict_entry_t structure "
"at %p", dp);
return (WALK_ERR);
}
return (status);
}
return (WALK_DONE);
return (WALK_NEXT);
}
void
{
}
typedef struct set_walk_data {
int hashcur;
void **hashloc;
int
{
return (WALK_ERR);
}
mdb_warn("rctl_set_size not found or invalid");
return (WALK_ERR);
}
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int status;
return (WALK_DONE);
break;
}
}
return (WALK_DONE);
}
return (WALK_ERR);
}
return (status);
}
void
{
}
int
{
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int status;
return (WALK_DONE);
}
return (WALK_DONE);
return (status);
}
typedef struct rctl_val_seen {
typedef struct rctl_validate_data {
int v_bad_rctl;
int v_cursor_valid;
/*
* rctl_val_validate()
* Do validation on an individual rctl_val_t. This function is called
* as part of the rctl_val walker, and helps perform the checks described
* in the ::rctl_validate dcmd.
*/
static int
{
int i;
data->v_cursor_valid++;
if (data->v_bad_rctl++ == 0)
mdb_printf("/ uninitialized or previously "
"freed link at %p ", addr);
}
if (data->v_seen_cnt == 0) {
if (data->v_bad_rctl++ == 0)
mdb_printf("/ bad prev pointer at "
"head ");
}
} else {
if (data->v_bad_rctl++ == 0)
mdb_printf("/ bad prev pointer at %p ",
addr);
}
if (data->v_bad_rctl++ == 0)
mdb_printf("/ ordering error at %p ",
addr);
}
}
for (i = data->v_seen_cnt; i >= 0; i--) {
if (data->v_bad_rctl++ == 0)
mdb_printf("/ circular next pointer "
"at %p ", addr);
break;
}
}
if (data->v_circularity_detected)
return (WALK_DONE);
data->v_seen_cnt++;
sizeof (rctl_val_seen_t));
}
return (WALK_NEXT);
}
/*
* Validate a rctl pointer by checking:
* - rctl_val_t's for that rctl form an ordered, non-circular list
* - the cursor points to a rctl_val_t within that list
* - there are no more than UINT64_MAX (or # specified by -n)
* rctl_val_t's in the list
*/
int
{
rctl_t r;
/* Initialize validate data structure */
data.v_bad_rctl = 0;
data.v_seen_cnt = 0;
data.v_cursor_valid = 0;
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_USAGE);
return (DCMD_ERR);
}
if (data.v_bad_rctl++ == 0)
mdb_printf("/ NULL cursor seen ");
if (data.v_bad_rctl++ == 0)
mdb_printf("/ uninitialized cursor seen ");
}
/* Walk through each val in this rctl for individual validation. */
addr) == -1) {
return (DCMD_ERR);
}
if (data.v_bad_rctl++ == 0)
mdb_printf("/ sequence length = %d ",
}
if (!data.v_cursor_valid) {
if (data.v_bad_rctl++ == 0)
mdb_printf("/ cursor outside sequence");
}
if (data.v_bad_rctl)
mdb_printf("\n");
mdb_warn("circular list implies possible memory leak; "
"recommend invoking ::findleaks");
return (DCMD_OK);
}