1*6712Stomee /* 2*6712Stomee * CDDL HEADER START 3*6712Stomee * 4*6712Stomee * The contents of this file are subject to the terms of the 5*6712Stomee * Common Development and Distribution License (the "License"). 6*6712Stomee * You may not use this file except in compliance with the License. 7*6712Stomee * 8*6712Stomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6712Stomee * or http://www.opensolaris.org/os/licensing. 10*6712Stomee * See the License for the specific language governing permissions 11*6712Stomee * and limitations under the License. 12*6712Stomee * 13*6712Stomee * When distributing Covered Code, include this CDDL HEADER in each 14*6712Stomee * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6712Stomee * If applicable, add the following below this CDDL HEADER, with the 16*6712Stomee * fields enclosed by brackets "[]" replaced with your own identifying 17*6712Stomee * information: Portions Copyright [yyyy] [name of copyright owner] 18*6712Stomee * 19*6712Stomee * CDDL HEADER END 20*6712Stomee */ 21*6712Stomee /* 22*6712Stomee * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*6712Stomee * Use is subject to license terms. 24*6712Stomee */ 25*6712Stomee 26*6712Stomee #pragma ident "%Z%%M% %I% %E% SMI" 27*6712Stomee 28*6712Stomee #include <mdb/mdb_modapi.h> 29*6712Stomee 30*6712Stomee typedef struct combined_walk { 31*6712Stomee int (*cw_init)(mdb_walk_state_t *); 32*6712Stomee int (*cw_step)(mdb_walk_state_t *); 33*6712Stomee void (*cw_fini)(mdb_walk_state_t *); 34*6712Stomee struct combined_walk *cw_next; 35*6712Stomee void *cw_data; 36*6712Stomee boolean_t cw_initialized; 37*6712Stomee } combined_walk_t; 38*6712Stomee 39*6712Stomee typedef struct combined_walk_data { 40*6712Stomee uintptr_t cwd_initial_walk_addr; /* to init each walk */ 41*6712Stomee combined_walk_t *cwd_current_walk; 42*6712Stomee combined_walk_t *cwd_final_walk; /* tail pointer */ 43*6712Stomee } combined_walk_data_t; 44*6712Stomee 45*6712Stomee /* 46*6712Stomee * Initialize a combined walk to 47*6712Stomee * A) present a single concatenated series of elements from different 48*6712Stomee * structures, or 49*6712Stomee * B) select from several possible walks at runtime. 50*6712Stomee * Multiple walks are done in the same order passed to combined_walk_add(). Each 51*6712Stomee * walk is initialized with the same wsp->walk_addr. 52*6712Stomee */ 53*6712Stomee void 54*6712Stomee combined_walk_init(mdb_walk_state_t *wsp) 55*6712Stomee { 56*6712Stomee combined_walk_data_t *cwd; 57*6712Stomee 58*6712Stomee cwd = mdb_alloc(sizeof (combined_walk_data_t), UM_SLEEP); 59*6712Stomee 60*6712Stomee cwd->cwd_initial_walk_addr = wsp->walk_addr; 61*6712Stomee cwd->cwd_current_walk = cwd->cwd_final_walk = NULL; 62*6712Stomee wsp->walk_data = cwd; 63*6712Stomee } 64*6712Stomee 65*6712Stomee static void 66*6712Stomee combined_walk_append(combined_walk_data_t *cwd, combined_walk_t *cw) 67*6712Stomee { 68*6712Stomee if (cwd->cwd_final_walk == NULL) { 69*6712Stomee cwd->cwd_current_walk = cwd->cwd_final_walk = cw; 70*6712Stomee } else { 71*6712Stomee cwd->cwd_final_walk->cw_next = cw; 72*6712Stomee cwd->cwd_final_walk = cw; 73*6712Stomee } 74*6712Stomee } 75*6712Stomee 76*6712Stomee static combined_walk_t * 77*6712Stomee combined_walk_remove_current(combined_walk_data_t *cwd) 78*6712Stomee { 79*6712Stomee combined_walk_t *cw = cwd->cwd_current_walk; 80*6712Stomee if (cw == NULL) { 81*6712Stomee return (NULL); 82*6712Stomee } 83*6712Stomee if (cw == cwd->cwd_final_walk) { 84*6712Stomee cwd->cwd_final_walk = cw->cw_next; 85*6712Stomee } 86*6712Stomee cwd->cwd_current_walk = cw->cw_next; 87*6712Stomee cw->cw_next = NULL; 88*6712Stomee return (cw); 89*6712Stomee } 90*6712Stomee 91*6712Stomee void 92*6712Stomee combined_walk_add(mdb_walk_state_t *wsp, 93*6712Stomee int (*walk_init)(mdb_walk_state_t *), 94*6712Stomee int (*walk_step)(mdb_walk_state_t *), 95*6712Stomee void (*walk_fini)(mdb_walk_state_t *)) 96*6712Stomee { 97*6712Stomee combined_walk_data_t *cwd = wsp->walk_data; 98*6712Stomee combined_walk_t *cw; 99*6712Stomee 100*6712Stomee cw = mdb_alloc(sizeof (combined_walk_t), UM_SLEEP); 101*6712Stomee 102*6712Stomee cw->cw_init = walk_init; 103*6712Stomee cw->cw_step = walk_step; 104*6712Stomee cw->cw_fini = walk_fini; 105*6712Stomee cw->cw_next = NULL; 106*6712Stomee cw->cw_data = NULL; 107*6712Stomee cw->cw_initialized = B_FALSE; 108*6712Stomee 109*6712Stomee combined_walk_append(cwd, cw); 110*6712Stomee } 111*6712Stomee 112*6712Stomee int 113*6712Stomee combined_walk_step(mdb_walk_state_t *wsp) 114*6712Stomee { 115*6712Stomee combined_walk_data_t *cwd = wsp->walk_data; 116*6712Stomee combined_walk_t *cw = cwd->cwd_current_walk; 117*6712Stomee int status; 118*6712Stomee 119*6712Stomee if (cw == NULL) { 120*6712Stomee return (WALK_DONE); 121*6712Stomee } 122*6712Stomee 123*6712Stomee if (cw->cw_initialized) { 124*6712Stomee wsp->walk_data = cw->cw_data; 125*6712Stomee } else { 126*6712Stomee wsp->walk_addr = cwd->cwd_initial_walk_addr; 127*6712Stomee status = cw->cw_init(wsp); 128*6712Stomee cw->cw_data = wsp->walk_data; 129*6712Stomee cw->cw_initialized = B_TRUE; 130*6712Stomee if (status != WALK_NEXT) { 131*6712Stomee wsp->walk_data = cwd; 132*6712Stomee return (status); 133*6712Stomee } 134*6712Stomee } 135*6712Stomee 136*6712Stomee status = cw->cw_step(wsp); 137*6712Stomee 138*6712Stomee if (status == WALK_DONE) { 139*6712Stomee (void) combined_walk_remove_current(cwd); 140*6712Stomee cw->cw_fini(wsp); 141*6712Stomee mdb_free(cw, sizeof (combined_walk_t)); 142*6712Stomee wsp->walk_data = cwd; 143*6712Stomee return (combined_walk_step(wsp)); 144*6712Stomee } 145*6712Stomee 146*6712Stomee wsp->walk_data = cwd; 147*6712Stomee return (status); 148*6712Stomee } 149*6712Stomee 150*6712Stomee void 151*6712Stomee combined_walk_fini(mdb_walk_state_t *wsp) 152*6712Stomee { 153*6712Stomee combined_walk_data_t *cwd = wsp->walk_data; 154*6712Stomee combined_walk_t *cw; 155*6712Stomee 156*6712Stomee while ((cw = combined_walk_remove_current(cwd)) != NULL) { 157*6712Stomee if (cw->cw_initialized) { 158*6712Stomee wsp->walk_data = cw->cw_data; 159*6712Stomee cw->cw_fini(wsp); 160*6712Stomee } 161*6712Stomee mdb_free(cw, sizeof (combined_walk_t)); 162*6712Stomee } 163*6712Stomee 164*6712Stomee mdb_free(cwd, sizeof (combined_walk_data_t)); 165*6712Stomee } 166