17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5789d94c2Sjwadams * Common Development and Distribution License (the "License"). 6789d94c2Sjwadams * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 220c3b83b1SJonathan Adams * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 264f364e7cSRobert Mustacchi /* 274f364e7cSRobert Mustacchi * Copyright (c) 2012, Joyent, Inc. All rights reserved. 284f364e7cSRobert Mustacchi */ 294f364e7cSRobert Mustacchi 307c478bd9Sstevel@tonic-gate #include "umem.h" 317c478bd9Sstevel@tonic-gate #include <libproc.h> 327c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include "kgrep.h" 357c478bd9Sstevel@tonic-gate #include "leaky.h" 367c478bd9Sstevel@tonic-gate #include "misc.h" 377c478bd9Sstevel@tonic-gate #include "proc_kludges.h" 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include <umem_impl.h> 407c478bd9Sstevel@tonic-gate #include <sys/vmem_impl_user.h> 414f364e7cSRobert Mustacchi #include <thr_uberdata.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include "umem_pagesize.h" 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate typedef struct datafmt { 467c478bd9Sstevel@tonic-gate char *hdr1; 477c478bd9Sstevel@tonic-gate char *hdr2; 487c478bd9Sstevel@tonic-gate char *dashes; 497c478bd9Sstevel@tonic-gate char *fmt; 507c478bd9Sstevel@tonic-gate } datafmt_t; 517c478bd9Sstevel@tonic-gate 524f364e7cSRobert Mustacchi static datafmt_t ptcfmt[] = { 534f364e7cSRobert Mustacchi { " ", "tid", "---", "%3u " }, 544f364e7cSRobert Mustacchi { " memory", " cached", "-------", "%7lH " }, 554f364e7cSRobert Mustacchi { " %", "cap", "---", "%3u " }, 564f364e7cSRobert Mustacchi { " %", NULL, "---", "%3u " }, 574f364e7cSRobert Mustacchi { NULL, NULL, NULL, NULL } 584f364e7cSRobert Mustacchi }; 594f364e7cSRobert Mustacchi 607c478bd9Sstevel@tonic-gate static datafmt_t umemfmt[] = { 617c478bd9Sstevel@tonic-gate { "cache ", "name ", 627c478bd9Sstevel@tonic-gate "-------------------------", "%-25s " }, 637c478bd9Sstevel@tonic-gate { " buf", " size", "------", "%6u " }, 644f364e7cSRobert Mustacchi { " buf", " in use", "-------", "%7u " }, 654f364e7cSRobert Mustacchi { " buf", " in ptc", "-------", "%7s " }, 664f364e7cSRobert Mustacchi { " buf", " total", "-------", "%7u " }, 674f364e7cSRobert Mustacchi { " memory", " in use", "-------", "%7H " }, 687c478bd9Sstevel@tonic-gate { " alloc", " succeed", "---------", "%9u " }, 697c478bd9Sstevel@tonic-gate { "alloc", " fail", "-----", "%5llu" }, 707c478bd9Sstevel@tonic-gate { NULL, NULL, NULL, NULL } 717c478bd9Sstevel@tonic-gate }; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate static datafmt_t vmemfmt[] = { 747c478bd9Sstevel@tonic-gate { "vmem ", "name ", 757c478bd9Sstevel@tonic-gate "-------------------------", "%-*s " }, 764f364e7cSRobert Mustacchi { " memory", " in use", "---------", "%9H " }, 774f364e7cSRobert Mustacchi { " memory", " total", "----------", "%10H " }, 784f364e7cSRobert Mustacchi { " memory", " import", "---------", "%9H " }, 797c478bd9Sstevel@tonic-gate { " alloc", " succeed", "---------", "%9llu " }, 807c478bd9Sstevel@tonic-gate { "alloc", " fail", "-----", "%5llu " }, 817c478bd9Sstevel@tonic-gate { NULL, NULL, NULL, NULL } 827c478bd9Sstevel@tonic-gate }; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 857c478bd9Sstevel@tonic-gate static int 867c478bd9Sstevel@tonic-gate umastat_cpu_avail(uintptr_t addr, const umem_cpu_cache_t *ccp, int *avail) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate if (ccp->cc_rounds > 0) 897c478bd9Sstevel@tonic-gate *avail += ccp->cc_rounds; 907c478bd9Sstevel@tonic-gate if (ccp->cc_prounds > 0) 917c478bd9Sstevel@tonic-gate *avail += ccp->cc_prounds; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate return (WALK_NEXT); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 977c478bd9Sstevel@tonic-gate static int 987c478bd9Sstevel@tonic-gate umastat_cpu_alloc(uintptr_t addr, const umem_cpu_cache_t *ccp, int *alloc) 997c478bd9Sstevel@tonic-gate { 1007c478bd9Sstevel@tonic-gate *alloc += ccp->cc_alloc; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate return (WALK_NEXT); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1067c478bd9Sstevel@tonic-gate static int 1077c478bd9Sstevel@tonic-gate umastat_slab_avail(uintptr_t addr, const umem_slab_t *sp, int *avail) 1087c478bd9Sstevel@tonic-gate { 1097c478bd9Sstevel@tonic-gate *avail += sp->slab_chunks - sp->slab_refcnt; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate return (WALK_NEXT); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate typedef struct umastat_vmem { 1157c478bd9Sstevel@tonic-gate uintptr_t kv_addr; 1167c478bd9Sstevel@tonic-gate struct umastat_vmem *kv_next; 1177c478bd9Sstevel@tonic-gate int kv_meminuse; 1187c478bd9Sstevel@tonic-gate int kv_alloc; 1197c478bd9Sstevel@tonic-gate int kv_fail; 1207c478bd9Sstevel@tonic-gate } umastat_vmem_t; 1217c478bd9Sstevel@tonic-gate 1224f364e7cSRobert Mustacchi /*ARGSUSED*/ 1234f364e7cSRobert Mustacchi static int 1244f364e7cSRobert Mustacchi umastat_cache_nptc(uintptr_t addr, const umem_cache_t *cp, int *nptc) 1254f364e7cSRobert Mustacchi { 1264f364e7cSRobert Mustacchi if (!(cp->cache_flags & UMF_PTC)) 1274f364e7cSRobert Mustacchi return (WALK_NEXT); 1284f364e7cSRobert Mustacchi 1294f364e7cSRobert Mustacchi (*nptc)++; 1304f364e7cSRobert Mustacchi return (WALK_NEXT); 1314f364e7cSRobert Mustacchi } 1324f364e7cSRobert Mustacchi 1334f364e7cSRobert Mustacchi /*ARGSUSED*/ 1344f364e7cSRobert Mustacchi static int 1354f364e7cSRobert Mustacchi umastat_cache_hdr(uintptr_t addr, const umem_cache_t *cp, void *ignored) 1364f364e7cSRobert Mustacchi { 1374f364e7cSRobert Mustacchi if (!(cp->cache_flags & UMF_PTC)) 1384f364e7cSRobert Mustacchi return (WALK_NEXT); 1394f364e7cSRobert Mustacchi 1404f364e7cSRobert Mustacchi mdb_printf("%3d ", cp->cache_bufsize); 1414f364e7cSRobert Mustacchi return (WALK_NEXT); 1424f364e7cSRobert Mustacchi } 1434f364e7cSRobert Mustacchi 1444f364e7cSRobert Mustacchi /*ARGSUSED*/ 1454f364e7cSRobert Mustacchi static int 1464f364e7cSRobert Mustacchi umastat_lwp_ptc(uintptr_t addr, void *buf, int *nbufs) 1474f364e7cSRobert Mustacchi { 1484f364e7cSRobert Mustacchi (*nbufs)++; 1494f364e7cSRobert Mustacchi return (WALK_NEXT); 1504f364e7cSRobert Mustacchi } 1514f364e7cSRobert Mustacchi 1524f364e7cSRobert Mustacchi /*ARGSUSED*/ 1534f364e7cSRobert Mustacchi static int 1544f364e7cSRobert Mustacchi umastat_lwp_cache(uintptr_t addr, const umem_cache_t *cp, ulwp_t *ulwp) 1554f364e7cSRobert Mustacchi { 1564f364e7cSRobert Mustacchi char walk[60]; 1574f364e7cSRobert Mustacchi int nbufs = 0; 1584f364e7cSRobert Mustacchi 1594f364e7cSRobert Mustacchi if (!(cp->cache_flags & UMF_PTC)) 1604f364e7cSRobert Mustacchi return (WALK_NEXT); 1614f364e7cSRobert Mustacchi 162*9c720e3bSIgor Kozhukhov (void) mdb_snprintf(walk, sizeof (walk), "umem_ptc_%d", 163*9c720e3bSIgor Kozhukhov cp->cache_bufsize); 1644f364e7cSRobert Mustacchi 1654f364e7cSRobert Mustacchi if (mdb_pwalk(walk, (mdb_walk_cb_t)umastat_lwp_ptc, 1664f364e7cSRobert Mustacchi &nbufs, (uintptr_t)ulwp->ul_self) == -1) { 1674f364e7cSRobert Mustacchi mdb_warn("unable to walk '%s'", walk); 1684f364e7cSRobert Mustacchi return (WALK_ERR); 1694f364e7cSRobert Mustacchi } 1704f364e7cSRobert Mustacchi 1714f364e7cSRobert Mustacchi mdb_printf("%3d ", ulwp->ul_tmem.tm_size ? 1724f364e7cSRobert Mustacchi (nbufs * cp->cache_bufsize * 100) / ulwp->ul_tmem.tm_size : 0); 1734f364e7cSRobert Mustacchi 1744f364e7cSRobert Mustacchi return (WALK_NEXT); 1754f364e7cSRobert Mustacchi } 1764f364e7cSRobert Mustacchi 1774f364e7cSRobert Mustacchi /*ARGSUSED*/ 1784f364e7cSRobert Mustacchi static int 1794f364e7cSRobert Mustacchi umastat_lwp(uintptr_t addr, const ulwp_t *ulwp, void *ignored) 1804f364e7cSRobert Mustacchi { 1814f364e7cSRobert Mustacchi size_t size; 1824f364e7cSRobert Mustacchi datafmt_t *dfp = ptcfmt; 1834f364e7cSRobert Mustacchi 1844f364e7cSRobert Mustacchi mdb_printf((dfp++)->fmt, ulwp->ul_lwpid); 1854f364e7cSRobert Mustacchi mdb_printf((dfp++)->fmt, ulwp->ul_tmem.tm_size); 1864f364e7cSRobert Mustacchi 1874f364e7cSRobert Mustacchi if (umem_readvar(&size, "umem_ptc_size") == -1) { 1884f364e7cSRobert Mustacchi mdb_warn("unable to read 'umem_ptc_size'"); 1894f364e7cSRobert Mustacchi return (WALK_ERR); 1904f364e7cSRobert Mustacchi } 1914f364e7cSRobert Mustacchi 1924f364e7cSRobert Mustacchi mdb_printf((dfp++)->fmt, (ulwp->ul_tmem.tm_size * 100) / size); 1934f364e7cSRobert Mustacchi 1944f364e7cSRobert Mustacchi if (mdb_walk("umem_cache", 1954f364e7cSRobert Mustacchi (mdb_walk_cb_t)umastat_lwp_cache, (void *)ulwp) == -1) { 1964f364e7cSRobert Mustacchi mdb_warn("can't walk 'umem_cache'"); 1974f364e7cSRobert Mustacchi return (WALK_ERR); 1984f364e7cSRobert Mustacchi } 1994f364e7cSRobert Mustacchi 2004f364e7cSRobert Mustacchi mdb_printf("\n"); 2014f364e7cSRobert Mustacchi 2024f364e7cSRobert Mustacchi return (WALK_NEXT); 2034f364e7cSRobert Mustacchi } 2044f364e7cSRobert Mustacchi 2054f364e7cSRobert Mustacchi /*ARGSUSED*/ 2064f364e7cSRobert Mustacchi static int 2074f364e7cSRobert Mustacchi umastat_cache_ptc(uintptr_t addr, const void *ignored, int *nptc) 2084f364e7cSRobert Mustacchi { 2094f364e7cSRobert Mustacchi (*nptc)++; 2104f364e7cSRobert Mustacchi return (WALK_NEXT); 2114f364e7cSRobert Mustacchi } 2124f364e7cSRobert Mustacchi 2137c478bd9Sstevel@tonic-gate static int 2147c478bd9Sstevel@tonic-gate umastat_cache(uintptr_t addr, const umem_cache_t *cp, umastat_vmem_t **kvp) 2157c478bd9Sstevel@tonic-gate { 2167c478bd9Sstevel@tonic-gate umastat_vmem_t *kv; 2177c478bd9Sstevel@tonic-gate datafmt_t *dfp = umemfmt; 2184f364e7cSRobert Mustacchi char buf[10]; 2197c478bd9Sstevel@tonic-gate int magsize; 2207c478bd9Sstevel@tonic-gate 2214f364e7cSRobert Mustacchi int avail, alloc, total, nptc = 0; 2227c478bd9Sstevel@tonic-gate size_t meminuse = (cp->cache_slab_create - cp->cache_slab_destroy) * 2237c478bd9Sstevel@tonic-gate cp->cache_slabsize; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate mdb_walk_cb_t cpu_avail = (mdb_walk_cb_t)umastat_cpu_avail; 2267c478bd9Sstevel@tonic-gate mdb_walk_cb_t cpu_alloc = (mdb_walk_cb_t)umastat_cpu_alloc; 2277c478bd9Sstevel@tonic-gate mdb_walk_cb_t slab_avail = (mdb_walk_cb_t)umastat_slab_avail; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate magsize = umem_get_magsize(cp); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate alloc = cp->cache_slab_alloc + cp->cache_full.ml_alloc; 2327c478bd9Sstevel@tonic-gate avail = cp->cache_full.ml_total * magsize; 2337c478bd9Sstevel@tonic-gate total = cp->cache_buftotal; 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate (void) mdb_pwalk("umem_cpu_cache", cpu_alloc, &alloc, addr); 2367c478bd9Sstevel@tonic-gate (void) mdb_pwalk("umem_cpu_cache", cpu_avail, &avail, addr); 2377c478bd9Sstevel@tonic-gate (void) mdb_pwalk("umem_slab_partial", slab_avail, &avail, addr); 2387c478bd9Sstevel@tonic-gate 2394f364e7cSRobert Mustacchi if (cp->cache_flags & UMF_PTC) { 2404f364e7cSRobert Mustacchi char walk[60]; 2414f364e7cSRobert Mustacchi 242*9c720e3bSIgor Kozhukhov (void) mdb_snprintf(walk, sizeof (walk), 2434f364e7cSRobert Mustacchi "umem_ptc_%d", cp->cache_bufsize); 2444f364e7cSRobert Mustacchi 2454f364e7cSRobert Mustacchi if (mdb_walk(walk, 2464f364e7cSRobert Mustacchi (mdb_walk_cb_t)umastat_cache_ptc, &nptc) == -1) { 2474f364e7cSRobert Mustacchi mdb_warn("unable to walk '%s'", walk); 2484f364e7cSRobert Mustacchi return (WALK_ERR); 2494f364e7cSRobert Mustacchi } 2504f364e7cSRobert Mustacchi 251*9c720e3bSIgor Kozhukhov (void) mdb_snprintf(buf, sizeof (buf), "%d", nptc); 2524f364e7cSRobert Mustacchi } 2534f364e7cSRobert Mustacchi 2547c478bd9Sstevel@tonic-gate for (kv = *kvp; kv != NULL; kv = kv->kv_next) { 2557c478bd9Sstevel@tonic-gate if (kv->kv_addr == (uintptr_t)cp->cache_arena) 2567c478bd9Sstevel@tonic-gate goto out; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate kv = mdb_zalloc(sizeof (umastat_vmem_t), UM_SLEEP | UM_GC); 2607c478bd9Sstevel@tonic-gate kv->kv_next = *kvp; 2617c478bd9Sstevel@tonic-gate kv->kv_addr = (uintptr_t)cp->cache_arena; 2627c478bd9Sstevel@tonic-gate *kvp = kv; 2637c478bd9Sstevel@tonic-gate out: 2647c478bd9Sstevel@tonic-gate kv->kv_meminuse += meminuse; 2657c478bd9Sstevel@tonic-gate kv->kv_alloc += alloc; 2667c478bd9Sstevel@tonic-gate kv->kv_fail += cp->cache_alloc_fail; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, cp->cache_name); 2697c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, cp->cache_bufsize); 2707c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, total - avail); 2714f364e7cSRobert Mustacchi mdb_printf((dfp++)->fmt, cp->cache_flags & UMF_PTC ? buf : "-"); 2727c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, total); 2737c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, meminuse); 2747c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, alloc); 2757c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, cp->cache_alloc_fail); 2767c478bd9Sstevel@tonic-gate mdb_printf("\n"); 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate return (WALK_NEXT); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate static int 2827c478bd9Sstevel@tonic-gate umastat_vmem_totals(uintptr_t addr, const vmem_t *v, umastat_vmem_t *kv) 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate while (kv != NULL && kv->kv_addr != addr) 2857c478bd9Sstevel@tonic-gate kv = kv->kv_next; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate if (kv == NULL || kv->kv_alloc == 0) 2887c478bd9Sstevel@tonic-gate return (WALK_NEXT); 2897c478bd9Sstevel@tonic-gate 2904f364e7cSRobert Mustacchi mdb_printf("Total [%s]%*s %6s %7s %7s %7s %7H %9u %5u\n", v->vm_name, 2914f364e7cSRobert Mustacchi 17 - strlen(v->vm_name), "", "", "", "", "", 2927c478bd9Sstevel@tonic-gate kv->kv_meminuse, kv->kv_alloc, kv->kv_fail); 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate return (WALK_NEXT); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2987c478bd9Sstevel@tonic-gate static int 2997c478bd9Sstevel@tonic-gate umastat_vmem(uintptr_t addr, const vmem_t *v, void *ignored) 3007c478bd9Sstevel@tonic-gate { 3017c478bd9Sstevel@tonic-gate datafmt_t *dfp = vmemfmt; 3027c478bd9Sstevel@tonic-gate uintptr_t paddr; 3037c478bd9Sstevel@tonic-gate vmem_t parent; 3047c478bd9Sstevel@tonic-gate int ident = 0; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate for (paddr = (uintptr_t)v->vm_source; paddr != NULL; ident += 4) { 3077c478bd9Sstevel@tonic-gate if (mdb_vread(&parent, sizeof (parent), paddr) == -1) { 3087c478bd9Sstevel@tonic-gate mdb_warn("couldn't trace %p's ancestry", addr); 3097c478bd9Sstevel@tonic-gate ident = 0; 3107c478bd9Sstevel@tonic-gate break; 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate paddr = (uintptr_t)parent.vm_source; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate mdb_printf("%*s", ident, ""); 3167c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, 25 - ident, v->vm_name); 3177c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, v->vm_kstat.vk_mem_inuse); 3187c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, v->vm_kstat.vk_mem_total); 3197c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, v->vm_kstat.vk_mem_import); 3207c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, v->vm_kstat.vk_alloc); 3217c478bd9Sstevel@tonic-gate mdb_printf((dfp++)->fmt, v->vm_kstat.vk_fail); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate mdb_printf("\n"); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate return (WALK_NEXT); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3297c478bd9Sstevel@tonic-gate int 3307c478bd9Sstevel@tonic-gate umastat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3317c478bd9Sstevel@tonic-gate { 3327c478bd9Sstevel@tonic-gate umastat_vmem_t *kv = NULL; 3337c478bd9Sstevel@tonic-gate datafmt_t *dfp; 3344f364e7cSRobert Mustacchi int nptc = 0, i; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate if (argc != 0) 3377c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 3387c478bd9Sstevel@tonic-gate 3394f364e7cSRobert Mustacchi /* 3404f364e7cSRobert Mustacchi * We need to determine if we have any caches that have per-thread 3414f364e7cSRobert Mustacchi * caching enabled. 3424f364e7cSRobert Mustacchi */ 3434f364e7cSRobert Mustacchi if (mdb_walk("umem_cache", 3444f364e7cSRobert Mustacchi (mdb_walk_cb_t)umastat_cache_nptc, &nptc) == -1) { 3454f364e7cSRobert Mustacchi mdb_warn("can't walk 'umem_cache'"); 3464f364e7cSRobert Mustacchi return (DCMD_ERR); 3474f364e7cSRobert Mustacchi } 3484f364e7cSRobert Mustacchi 3494f364e7cSRobert Mustacchi if (nptc) { 3504f364e7cSRobert Mustacchi for (dfp = ptcfmt; dfp->hdr2 != NULL; dfp++) 3517c478bd9Sstevel@tonic-gate mdb_printf("%s ", dfp->hdr1); 3524f364e7cSRobert Mustacchi 3534f364e7cSRobert Mustacchi for (i = 0; i < nptc; i++) 3544f364e7cSRobert Mustacchi mdb_printf("%s ", dfp->hdr1); 3554f364e7cSRobert Mustacchi 3567c478bd9Sstevel@tonic-gate mdb_printf("\n"); 3577c478bd9Sstevel@tonic-gate 3584f364e7cSRobert Mustacchi for (dfp = ptcfmt; dfp->hdr2 != NULL; dfp++) 3597c478bd9Sstevel@tonic-gate mdb_printf("%s ", dfp->hdr2); 3604f364e7cSRobert Mustacchi 3614f364e7cSRobert Mustacchi if (mdb_walk("umem_cache", 3624f364e7cSRobert Mustacchi (mdb_walk_cb_t)umastat_cache_hdr, NULL) == -1) { 3634f364e7cSRobert Mustacchi mdb_warn("can't walk 'umem_cache'"); 3644f364e7cSRobert Mustacchi return (DCMD_ERR); 3654f364e7cSRobert Mustacchi } 3664f364e7cSRobert Mustacchi 3674f364e7cSRobert Mustacchi mdb_printf("\n"); 3684f364e7cSRobert Mustacchi 3694f364e7cSRobert Mustacchi for (dfp = ptcfmt; dfp->hdr2 != NULL; dfp++) 3704f364e7cSRobert Mustacchi mdb_printf("%s ", dfp->dashes); 3714f364e7cSRobert Mustacchi 3724f364e7cSRobert Mustacchi for (i = 0; i < nptc; i++) 3734f364e7cSRobert Mustacchi mdb_printf("%s ", dfp->dashes); 3744f364e7cSRobert Mustacchi 3754f364e7cSRobert Mustacchi mdb_printf("\n"); 3764f364e7cSRobert Mustacchi 3774f364e7cSRobert Mustacchi if (mdb_walk("ulwp", (mdb_walk_cb_t)umastat_lwp, NULL) == -1) { 3784f364e7cSRobert Mustacchi mdb_warn("can't walk 'ulwp'"); 3794f364e7cSRobert Mustacchi return (DCMD_ERR); 3804f364e7cSRobert Mustacchi } 3814f364e7cSRobert Mustacchi 3824f364e7cSRobert Mustacchi mdb_printf("\n"); 3834f364e7cSRobert Mustacchi } 3844f364e7cSRobert Mustacchi 3854f364e7cSRobert Mustacchi for (dfp = umemfmt; dfp->hdr1 != NULL; dfp++) 3864f364e7cSRobert Mustacchi mdb_printf("%s%s", dfp == umemfmt ? "" : " ", dfp->hdr1); 3877c478bd9Sstevel@tonic-gate mdb_printf("\n"); 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate for (dfp = umemfmt; dfp->hdr1 != NULL; dfp++) 3904f364e7cSRobert Mustacchi mdb_printf("%s%s", dfp == umemfmt ? "" : " ", dfp->hdr2); 3914f364e7cSRobert Mustacchi mdb_printf("\n"); 3924f364e7cSRobert Mustacchi 3934f364e7cSRobert Mustacchi for (dfp = umemfmt; dfp->hdr1 != NULL; dfp++) 3944f364e7cSRobert Mustacchi mdb_printf("%s%s", dfp == umemfmt ? "" : " ", dfp->dashes); 3957c478bd9Sstevel@tonic-gate mdb_printf("\n"); 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate if (mdb_walk("umem_cache", (mdb_walk_cb_t)umastat_cache, &kv) == -1) { 3987c478bd9Sstevel@tonic-gate mdb_warn("can't walk 'umem_cache'"); 3997c478bd9Sstevel@tonic-gate return (DCMD_ERR); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate for (dfp = umemfmt; dfp->hdr1 != NULL; dfp++) 4034f364e7cSRobert Mustacchi mdb_printf("%s%s", dfp == umemfmt ? "" : " ", dfp->dashes); 4047c478bd9Sstevel@tonic-gate mdb_printf("\n"); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate if (mdb_walk("vmem", (mdb_walk_cb_t)umastat_vmem_totals, kv) == -1) { 4077c478bd9Sstevel@tonic-gate mdb_warn("can't walk 'vmem'"); 4087c478bd9Sstevel@tonic-gate return (DCMD_ERR); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate for (dfp = umemfmt; dfp->hdr1 != NULL; dfp++) 4127c478bd9Sstevel@tonic-gate mdb_printf("%s ", dfp->dashes); 4137c478bd9Sstevel@tonic-gate mdb_printf("\n"); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate mdb_printf("\n"); 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate for (dfp = vmemfmt; dfp->hdr1 != NULL; dfp++) 4187c478bd9Sstevel@tonic-gate mdb_printf("%s ", dfp->hdr1); 4197c478bd9Sstevel@tonic-gate mdb_printf("\n"); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate for (dfp = vmemfmt; dfp->hdr1 != NULL; dfp++) 4227c478bd9Sstevel@tonic-gate mdb_printf("%s ", dfp->hdr2); 4237c478bd9Sstevel@tonic-gate mdb_printf("\n"); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate for (dfp = vmemfmt; dfp->hdr1 != NULL; dfp++) 4267c478bd9Sstevel@tonic-gate mdb_printf("%s ", dfp->dashes); 4277c478bd9Sstevel@tonic-gate mdb_printf("\n"); 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate if (mdb_walk("vmem", (mdb_walk_cb_t)umastat_vmem, NULL) == -1) { 4307c478bd9Sstevel@tonic-gate mdb_warn("can't walk 'vmem'"); 4317c478bd9Sstevel@tonic-gate return (DCMD_ERR); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate for (dfp = vmemfmt; dfp->hdr1 != NULL; dfp++) 4357c478bd9Sstevel@tonic-gate mdb_printf("%s ", dfp->dashes); 4367c478bd9Sstevel@tonic-gate mdb_printf("\n"); 4377c478bd9Sstevel@tonic-gate return (DCMD_OK); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate /* 4417c478bd9Sstevel@tonic-gate * kmdb doesn't use libproc, and thus doesn't have any prmap_t's to walk. 4427c478bd9Sstevel@tonic-gate * We have other ways to grep kmdb's address range. 4437c478bd9Sstevel@tonic-gate */ 4447c478bd9Sstevel@tonic-gate #ifndef _KMDB 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate typedef struct ugrep_walk_data { 4477c478bd9Sstevel@tonic-gate kgrep_cb_func *ug_cb; 4487c478bd9Sstevel@tonic-gate void *ug_cbdata; 4497c478bd9Sstevel@tonic-gate } ugrep_walk_data_t; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4527c478bd9Sstevel@tonic-gate int 4537c478bd9Sstevel@tonic-gate ugrep_mapping_cb(uintptr_t addr, const void *prm_arg, void *data) 4547c478bd9Sstevel@tonic-gate { 4557c478bd9Sstevel@tonic-gate ugrep_walk_data_t *ug = data; 4567c478bd9Sstevel@tonic-gate const prmap_t *prm = prm_arg; 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate return (ug->ug_cb(prm->pr_vaddr, prm->pr_vaddr + prm->pr_size, 4597c478bd9Sstevel@tonic-gate ug->ug_cbdata)); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate int 4637c478bd9Sstevel@tonic-gate kgrep_subr(kgrep_cb_func *cb, void *cbdata) 4647c478bd9Sstevel@tonic-gate { 4657c478bd9Sstevel@tonic-gate ugrep_walk_data_t ug; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate prockludge_add_walkers(); 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate ug.ug_cb = cb; 4707c478bd9Sstevel@tonic-gate ug.ug_cbdata = cbdata; 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate if (mdb_walk(KLUDGE_MAPWALK_NAME, ugrep_mapping_cb, &ug) == -1) { 4737c478bd9Sstevel@tonic-gate mdb_warn("Unable to walk "KLUDGE_MAPWALK_NAME); 4747c478bd9Sstevel@tonic-gate return (DCMD_ERR); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate prockludge_remove_walkers(); 4787c478bd9Sstevel@tonic-gate return (DCMD_OK); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate size_t 4827c478bd9Sstevel@tonic-gate kgrep_subr_pagesize(void) 4837c478bd9Sstevel@tonic-gate { 4847c478bd9Sstevel@tonic-gate return (PAGESIZE); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate #endif /* !_KMDB */ 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = { 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* from libumem.c */ 4927c478bd9Sstevel@tonic-gate { "umastat", NULL, "umem allocator stats", umastat }, 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate /* from misc.c */ 4957c478bd9Sstevel@tonic-gate { "umem_debug", NULL, "toggle umem dcmd/walk debugging", umem_debug}, 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* from umem.c */ 4987c478bd9Sstevel@tonic-gate { "umem_status", NULL, "Print umem status and message buffer", 4997c478bd9Sstevel@tonic-gate umem_status }, 5007c478bd9Sstevel@tonic-gate { "allocdby", ":", "given a thread, print its allocated buffers", 5017c478bd9Sstevel@tonic-gate allocdby }, 5027c478bd9Sstevel@tonic-gate { "bufctl", ":[-vh] [-a addr] [-c caller] [-e earliest] [-l latest] " 5037c478bd9Sstevel@tonic-gate "[-t thd]", "print or filter a bufctl", bufctl, bufctl_help }, 5047c478bd9Sstevel@tonic-gate { "bufctl_audit", ":", "print a bufctl_audit", bufctl_audit }, 5057c478bd9Sstevel@tonic-gate { "freedby", ":", "given a thread, print its freed buffers", freedby }, 5067c478bd9Sstevel@tonic-gate { "umalog", "[ fail | slab ]", 5077c478bd9Sstevel@tonic-gate "display umem transaction log and stack traces", umalog }, 5087c478bd9Sstevel@tonic-gate { "umausers", "[-ef] [cache ...]", "display current medium and large " 5097c478bd9Sstevel@tonic-gate "users of the umem allocator", umausers }, 5107c478bd9Sstevel@tonic-gate { "umem_cache", "?", "print a umem cache", umem_cache }, 5117c478bd9Sstevel@tonic-gate { "umem_log", "?", "dump umem transaction log", umem_log }, 512789d94c2Sjwadams { "umem_malloc_dist", "[-dg] [-b maxbins] [-B minbinsize]", 513789d94c2Sjwadams "report distribution of outstanding malloc()s", 514789d94c2Sjwadams umem_malloc_dist, umem_malloc_dist_help }, 515789d94c2Sjwadams { "umem_malloc_info", "?[-dg] [-b maxbins] [-B minbinsize]", 516789d94c2Sjwadams "report information about malloc()s by cache", 517789d94c2Sjwadams umem_malloc_info, umem_malloc_info_help }, 5187c478bd9Sstevel@tonic-gate { "umem_verify", "?", "check integrity of umem-managed memory", 5197c478bd9Sstevel@tonic-gate umem_verify }, 5207c478bd9Sstevel@tonic-gate { "vmem", "?", "print a vmem_t", vmem }, 5217c478bd9Sstevel@tonic-gate { "vmem_seg", ":[-sv] [-c caller] [-e earliest] [-l latest] " 5227c478bd9Sstevel@tonic-gate "[-m minsize] [-M maxsize] [-t thread] [-T type]", 5237c478bd9Sstevel@tonic-gate "print or filter a vmem_seg", vmem_seg, vmem_seg_help }, 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate #ifndef _KMDB 5267c478bd9Sstevel@tonic-gate /* from ../genunix/kgrep.c + libumem.c */ 5277c478bd9Sstevel@tonic-gate { "ugrep", KGREP_USAGE, "search user address space for a pointer", 528154eb83fSjwadams kgrep, kgrep_help }, 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate /* from ../genunix/leaky.c + leaky_subr.c */ 5317c478bd9Sstevel@tonic-gate { "findleaks", FINDLEAKS_USAGE, "search for potential memory leaks", 5327c478bd9Sstevel@tonic-gate findleaks, findleaks_help }, 5337c478bd9Sstevel@tonic-gate #endif 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate { NULL } 5367c478bd9Sstevel@tonic-gate }; 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate static const mdb_walker_t walkers[] = { 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate /* from umem.c */ 5417c478bd9Sstevel@tonic-gate { "allocdby", "given a thread, walk its allocated bufctls", 5427c478bd9Sstevel@tonic-gate allocdby_walk_init, allocdby_walk_step, allocdby_walk_fini }, 5437c478bd9Sstevel@tonic-gate { "bufctl", "walk a umem cache's bufctls", 5447c478bd9Sstevel@tonic-gate bufctl_walk_init, umem_walk_step, umem_walk_fini }, 5457c478bd9Sstevel@tonic-gate { "bufctl_history", "walk the available history of a bufctl", 5467c478bd9Sstevel@tonic-gate bufctl_history_walk_init, bufctl_history_walk_step, 5477c478bd9Sstevel@tonic-gate bufctl_history_walk_fini }, 5487c478bd9Sstevel@tonic-gate { "freectl", "walk a umem cache's free bufctls", 5497c478bd9Sstevel@tonic-gate freectl_walk_init, umem_walk_step, umem_walk_fini }, 5507c478bd9Sstevel@tonic-gate { "freedby", "given a thread, walk its freed bufctls", 5517c478bd9Sstevel@tonic-gate freedby_walk_init, allocdby_walk_step, allocdby_walk_fini }, 5527c478bd9Sstevel@tonic-gate { "freemem", "walk a umem cache's free memory", 5537c478bd9Sstevel@tonic-gate freemem_walk_init, umem_walk_step, umem_walk_fini }, 5547c478bd9Sstevel@tonic-gate { "umem", "walk a umem cache", 5557c478bd9Sstevel@tonic-gate umem_walk_init, umem_walk_step, umem_walk_fini }, 5567c478bd9Sstevel@tonic-gate { "umem_cpu", "walk the umem CPU structures", 5577c478bd9Sstevel@tonic-gate umem_cpu_walk_init, umem_cpu_walk_step, umem_cpu_walk_fini }, 5587c478bd9Sstevel@tonic-gate { "umem_cpu_cache", "given a umem cache, walk its per-CPU caches", 5597c478bd9Sstevel@tonic-gate umem_cpu_cache_walk_init, umem_cpu_cache_walk_step, NULL }, 5607c478bd9Sstevel@tonic-gate { "umem_hash", "given a umem cache, walk its allocated hash table", 5617c478bd9Sstevel@tonic-gate umem_hash_walk_init, umem_hash_walk_step, umem_hash_walk_fini }, 5627c478bd9Sstevel@tonic-gate { "umem_log", "walk the umem transaction log", 5637c478bd9Sstevel@tonic-gate umem_log_walk_init, umem_log_walk_step, umem_log_walk_fini }, 5647c478bd9Sstevel@tonic-gate { "umem_slab", "given a umem cache, walk its slabs", 5657c478bd9Sstevel@tonic-gate umem_slab_walk_init, umem_slab_walk_step, NULL }, 5667c478bd9Sstevel@tonic-gate { "umem_slab_partial", 5677c478bd9Sstevel@tonic-gate "given a umem cache, walk its partially allocated slabs (min 1)", 5687c478bd9Sstevel@tonic-gate umem_slab_walk_partial_init, umem_slab_walk_step, NULL }, 5697c478bd9Sstevel@tonic-gate { "vmem", "walk vmem structures in pre-fix, depth-first order", 5707c478bd9Sstevel@tonic-gate vmem_walk_init, vmem_walk_step, vmem_walk_fini }, 5717c478bd9Sstevel@tonic-gate { "vmem_alloc", "given a vmem_t, walk its allocated vmem_segs", 5727c478bd9Sstevel@tonic-gate vmem_alloc_walk_init, vmem_seg_walk_step, vmem_seg_walk_fini }, 5737c478bd9Sstevel@tonic-gate { "vmem_free", "given a vmem_t, walk its free vmem_segs", 5747c478bd9Sstevel@tonic-gate vmem_free_walk_init, vmem_seg_walk_step, vmem_seg_walk_fini }, 5757c478bd9Sstevel@tonic-gate { "vmem_postfix", "walk vmem structures in post-fix, depth-first order", 5767c478bd9Sstevel@tonic-gate vmem_walk_init, vmem_postfix_walk_step, vmem_walk_fini }, 5777c478bd9Sstevel@tonic-gate { "vmem_seg", "given a vmem_t, walk all of its vmem_segs", 5787c478bd9Sstevel@tonic-gate vmem_seg_walk_init, vmem_seg_walk_step, vmem_seg_walk_fini }, 5797c478bd9Sstevel@tonic-gate { "vmem_span", "given a vmem_t, walk its spanning vmem_segs", 5807c478bd9Sstevel@tonic-gate vmem_span_walk_init, vmem_seg_walk_step, vmem_seg_walk_fini }, 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate #ifndef _KMDB 5837c478bd9Sstevel@tonic-gate /* from ../genunix/leaky.c + leaky_subr.c */ 5847c478bd9Sstevel@tonic-gate { "leak", "given a leak ctl, walk other leaks w/ that stacktrace", 5857c478bd9Sstevel@tonic-gate leaky_walk_init, leaky_walk_step, leaky_walk_fini }, 5867c478bd9Sstevel@tonic-gate { "leakbuf", "given a leak ctl, walk addr of leaks w/ that stacktrace", 5877c478bd9Sstevel@tonic-gate leaky_walk_init, leaky_buf_walk_step, leaky_walk_fini }, 5887c478bd9Sstevel@tonic-gate #endif 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate { NULL } 5917c478bd9Sstevel@tonic-gate }; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate static const mdb_modinfo_t modinfo = {MDB_API_VERSION, dcmds, walkers}; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate const mdb_modinfo_t * 5967c478bd9Sstevel@tonic-gate _mdb_init(void) 5977c478bd9Sstevel@tonic-gate { 5987c478bd9Sstevel@tonic-gate if (umem_init() != 0) 5997c478bd9Sstevel@tonic-gate return (NULL); 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate return (&modinfo); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate void 6057c478bd9Sstevel@tonic-gate _mdb_fini(void) 6067c478bd9Sstevel@tonic-gate { 6077c478bd9Sstevel@tonic-gate #ifndef _KMDB 6087c478bd9Sstevel@tonic-gate leaky_cleanup(1); 6097c478bd9Sstevel@tonic-gate #endif 6107c478bd9Sstevel@tonic-gate } 611