1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * lgroup interface 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate #include <errno.h> 34*7c478bd9Sstevel@tonic-gate #include <stdio.h> 35*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 36*7c478bd9Sstevel@tonic-gate #include <strings.h> 37*7c478bd9Sstevel@tonic-gate #include <unistd.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/bitmap.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/pset.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #include <sys/lgrp_user.h> 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* 46*7c478bd9Sstevel@tonic-gate * Fast trap for getting home lgroup of current thread 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate extern lgrp_id_t _lgrp_home_fast(void); 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate /* 51*7c478bd9Sstevel@tonic-gate * lgroup system call 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate extern int _lgrpsys(int subcode, long arg, void *ap); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate static int lgrp_cpus_hier(lgrp_snapshot_header_t *snap, lgrp_id_t lgrp, 56*7c478bd9Sstevel@tonic-gate processorid_t **cpuids, uint_t *count); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * Get generation ID of lgroup hierarchy given view 61*7c478bd9Sstevel@tonic-gate * which changes whenever the hierarchy changes (eg. DR or pset contents 62*7c478bd9Sstevel@tonic-gate * change for caller's view) 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate static lgrp_gen_t 65*7c478bd9Sstevel@tonic-gate lgrp_generation(lgrp_view_t view) 66*7c478bd9Sstevel@tonic-gate { 67*7c478bd9Sstevel@tonic-gate return (_lgrpsys(LGRP_SYS_GENERATION, view, NULL)); 68*7c478bd9Sstevel@tonic-gate } 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * Get supported revision number of lgroup interface 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate int 75*7c478bd9Sstevel@tonic-gate lgrp_version(int version) 76*7c478bd9Sstevel@tonic-gate { 77*7c478bd9Sstevel@tonic-gate return (_lgrpsys(LGRP_SYS_VERSION, version, NULL)); 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * Get affinity for given lgroup 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate lgrp_affinity_t 85*7c478bd9Sstevel@tonic-gate lgrp_affinity_get(idtype_t idtype, id_t id, lgrp_id_t lgrp) 86*7c478bd9Sstevel@tonic-gate { 87*7c478bd9Sstevel@tonic-gate lgrp_affinity_args_t args; 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate args.idtype = idtype; 90*7c478bd9Sstevel@tonic-gate args.id = id; 91*7c478bd9Sstevel@tonic-gate args.lgrp = lgrp; 92*7c478bd9Sstevel@tonic-gate return (_lgrpsys(LGRP_SYS_AFFINITY_GET, 0, (void *)&args)); 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * Set affinity for given lgroup 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate int 100*7c478bd9Sstevel@tonic-gate lgrp_affinity_set(idtype_t idtype, id_t id, lgrp_id_t lgrp, 101*7c478bd9Sstevel@tonic-gate lgrp_affinity_t aff) 102*7c478bd9Sstevel@tonic-gate { 103*7c478bd9Sstevel@tonic-gate lgrp_affinity_args_t args; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate args.idtype = idtype; 106*7c478bd9Sstevel@tonic-gate args.id = id; 107*7c478bd9Sstevel@tonic-gate args.lgrp = lgrp; 108*7c478bd9Sstevel@tonic-gate args.aff = aff; 109*7c478bd9Sstevel@tonic-gate return (_lgrpsys(LGRP_SYS_AFFINITY_SET, 0, (void *)&args)); 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * Get home lgroup for given process or thread 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate lgrp_id_t 117*7c478bd9Sstevel@tonic-gate lgrp_home(idtype_t idtype, id_t id) 118*7c478bd9Sstevel@tonic-gate { 119*7c478bd9Sstevel@tonic-gate /* 120*7c478bd9Sstevel@tonic-gate * Use fast trap to get home lgroup of current thread or process 121*7c478bd9Sstevel@tonic-gate * Otherwise, use system call for other process or thread 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate if (id == P_MYID && (idtype == P_LWPID || idtype == P_PID)) 124*7c478bd9Sstevel@tonic-gate return (_lgrp_home_fast()); 125*7c478bd9Sstevel@tonic-gate else 126*7c478bd9Sstevel@tonic-gate return (_lgrpsys(LGRP_SYS_HOME, idtype, (void *)(intptr_t)id)); 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Get a snapshot of the lgroup hierarchy 132*7c478bd9Sstevel@tonic-gate */ 133*7c478bd9Sstevel@tonic-gate static int 134*7c478bd9Sstevel@tonic-gate lgrp_snapshot(void *buf, size_t bufsize) 135*7c478bd9Sstevel@tonic-gate { 136*7c478bd9Sstevel@tonic-gate return (_lgrpsys(LGRP_SYS_SNAPSHOT, bufsize, buf)); 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate /* 141*7c478bd9Sstevel@tonic-gate * Find any orphan lgroups without parents and make them be children of 142*7c478bd9Sstevel@tonic-gate * root lgroup 143*7c478bd9Sstevel@tonic-gate */ 144*7c478bd9Sstevel@tonic-gate static int 145*7c478bd9Sstevel@tonic-gate parent_orphans(lgrp_snapshot_header_t *snap) 146*7c478bd9Sstevel@tonic-gate { 147*7c478bd9Sstevel@tonic-gate int i; 148*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 149*7c478bd9Sstevel@tonic-gate int nlgrpsmax; 150*7c478bd9Sstevel@tonic-gate int orphan; 151*7c478bd9Sstevel@tonic-gate lgrp_info_t *root; 152*7c478bd9Sstevel@tonic-gate ulong_t *parents; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_info == NULL || 155*7c478bd9Sstevel@tonic-gate snap->ss_parents == NULL || snap->ss_root < 0 || 156*7c478bd9Sstevel@tonic-gate snap->ss_root >= snap->ss_nlgrps_max) 157*7c478bd9Sstevel@tonic-gate return (-1); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate nlgrpsmax = snap->ss_nlgrps_max; 160*7c478bd9Sstevel@tonic-gate root = &snap->ss_info[snap->ss_root]; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate for (i = 0; i < nlgrpsmax; i++) { 163*7c478bd9Sstevel@tonic-gate int j; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * Skip root lgroup 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate if (i == snap->ss_root) 169*7c478bd9Sstevel@tonic-gate continue; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[i]; 172*7c478bd9Sstevel@tonic-gate if (lgrp_info == NULL || lgrp_info->info_lgrpid == LGRP_NONE) 173*7c478bd9Sstevel@tonic-gate continue; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * Make sure parents bitmap is setup 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate if (lgrp_info->info_parents == NULL) 179*7c478bd9Sstevel@tonic-gate lgrp_info->info_parents = 180*7c478bd9Sstevel@tonic-gate (ulong_t *)((uintptr_t)snap->ss_parents + 181*7c478bd9Sstevel@tonic-gate (i * BT_SIZEOFMAP(nlgrpsmax))); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * Look for orphans (lgroups with no parents) 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate orphan = 1; 187*7c478bd9Sstevel@tonic-gate parents = lgrp_info->info_parents; 188*7c478bd9Sstevel@tonic-gate for (j = 0; j < BT_BITOUL(nlgrpsmax); j++) 189*7c478bd9Sstevel@tonic-gate if (parents[j] != 0) { 190*7c478bd9Sstevel@tonic-gate orphan = 0; 191*7c478bd9Sstevel@tonic-gate break; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate * Make root be parent of any orphans 196*7c478bd9Sstevel@tonic-gate */ 197*7c478bd9Sstevel@tonic-gate if (orphan) { 198*7c478bd9Sstevel@tonic-gate BT_SET(parents, root->info_lgrpid); 199*7c478bd9Sstevel@tonic-gate if (root->info_children) { 200*7c478bd9Sstevel@tonic-gate BT_SET(root->info_children, i); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate return (0); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate /* 210*7c478bd9Sstevel@tonic-gate * Remove given lgroup from parent lgroup(s) 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate static void 213*7c478bd9Sstevel@tonic-gate prune_child(lgrp_snapshot_header_t *snap, lgrp_id_t lgrp) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate int i; 216*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 217*7c478bd9Sstevel@tonic-gate ulong_t *parents; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate if (snap == NULL || lgrp < 0 || lgrp > snap->ss_nlgrps_max) 220*7c478bd9Sstevel@tonic-gate return; 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[lgrp]; 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate parents = lgrp_info->info_parents; 225*7c478bd9Sstevel@tonic-gate if (parents == NULL) 226*7c478bd9Sstevel@tonic-gate return; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate /* 229*7c478bd9Sstevel@tonic-gate * Update children of parents not to include given lgroup 230*7c478bd9Sstevel@tonic-gate */ 231*7c478bd9Sstevel@tonic-gate for (i = 0; i < snap->ss_nlgrps_max; i++) { 232*7c478bd9Sstevel@tonic-gate if (BT_TEST(parents, i)) { 233*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[i]; 234*7c478bd9Sstevel@tonic-gate BT_CLEAR(lgrp_info->info_children, lgrp); 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate /* 240*7c478bd9Sstevel@tonic-gate * Prune any CPUs not in given array from specified lgroup 241*7c478bd9Sstevel@tonic-gate */ 242*7c478bd9Sstevel@tonic-gate static void 243*7c478bd9Sstevel@tonic-gate prune_cpus(lgrp_snapshot_header_t *snap, lgrp_id_t lgrp, processorid_t *cpus, 244*7c478bd9Sstevel@tonic-gate int ncpus) 245*7c478bd9Sstevel@tonic-gate { 246*7c478bd9Sstevel@tonic-gate int count; 247*7c478bd9Sstevel@tonic-gate int i; 248*7c478bd9Sstevel@tonic-gate int j; 249*7c478bd9Sstevel@tonic-gate int k; 250*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 251*7c478bd9Sstevel@tonic-gate uint_t lgrp_ncpus; 252*7c478bd9Sstevel@tonic-gate processorid_t *lgrp_cpus; 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate if (snap == NULL || lgrp < 0 || lgrp > snap->ss_nlgrps_max) 255*7c478bd9Sstevel@tonic-gate return; 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[lgrp]; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* 260*7c478bd9Sstevel@tonic-gate * No CPUs to remove 261*7c478bd9Sstevel@tonic-gate */ 262*7c478bd9Sstevel@tonic-gate if (ncpus == 0 || lgrp_info->info_ncpus == 0) 263*7c478bd9Sstevel@tonic-gate return; 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate /* 266*7c478bd9Sstevel@tonic-gate * Remove all CPUs from lgroup 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate if (cpus == NULL && ncpus == -1) { 269*7c478bd9Sstevel@tonic-gate lgrp_info->info_ncpus = 0; 270*7c478bd9Sstevel@tonic-gate return; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /* 274*7c478bd9Sstevel@tonic-gate * Remove any CPUs from lgroup not in given list of CPUs 275*7c478bd9Sstevel@tonic-gate */ 276*7c478bd9Sstevel@tonic-gate lgrp_cpus = lgrp_info->info_cpuids; 277*7c478bd9Sstevel@tonic-gate lgrp_ncpus = lgrp_info->info_ncpus; 278*7c478bd9Sstevel@tonic-gate i = 0; 279*7c478bd9Sstevel@tonic-gate for (count = 0; count < lgrp_ncpus; count++) { 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * Look for CPU in list 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate for (j = 0; j < ncpus; j++) 284*7c478bd9Sstevel@tonic-gate if (lgrp_cpus[i] == cpus[j]) 285*7c478bd9Sstevel@tonic-gate break; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* 288*7c478bd9Sstevel@tonic-gate * Go to next CPU if found this one in list 289*7c478bd9Sstevel@tonic-gate */ 290*7c478bd9Sstevel@tonic-gate if (j < ncpus) { 291*7c478bd9Sstevel@tonic-gate i++; 292*7c478bd9Sstevel@tonic-gate continue; 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * Remove this CPU and shift others into its place 297*7c478bd9Sstevel@tonic-gate * and decrement number of CPUs 298*7c478bd9Sstevel@tonic-gate */ 299*7c478bd9Sstevel@tonic-gate for (k = i + 1; k < lgrp_info->info_ncpus; k++) 300*7c478bd9Sstevel@tonic-gate lgrp_cpus[k - 1] = lgrp_cpus[k]; 301*7c478bd9Sstevel@tonic-gate lgrp_cpus[k - 1] = -1; 302*7c478bd9Sstevel@tonic-gate lgrp_info->info_ncpus--; 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* 308*7c478bd9Sstevel@tonic-gate * Prune lgroup hierarchy for caller's view 309*7c478bd9Sstevel@tonic-gate */ 310*7c478bd9Sstevel@tonic-gate static int 311*7c478bd9Sstevel@tonic-gate prune_tree(lgrp_snapshot_header_t *snap) 312*7c478bd9Sstevel@tonic-gate { 313*7c478bd9Sstevel@tonic-gate processorid_t *cpus; 314*7c478bd9Sstevel@tonic-gate int i; 315*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 316*7c478bd9Sstevel@tonic-gate lgrp_mem_size_t nbytes; 317*7c478bd9Sstevel@tonic-gate uint_t ncpus; 318*7c478bd9Sstevel@tonic-gate int nlgrps_max; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_info == NULL) 321*7c478bd9Sstevel@tonic-gate return (-1); 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * Get CPUs in caller's pset 325*7c478bd9Sstevel@tonic-gate */ 326*7c478bd9Sstevel@tonic-gate if (pset_info(PS_MYID, NULL, &ncpus, NULL) == -1) 327*7c478bd9Sstevel@tonic-gate return (-1); 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate cpus = NULL; 330*7c478bd9Sstevel@tonic-gate if (ncpus > 0) { 331*7c478bd9Sstevel@tonic-gate cpus = malloc(ncpus * sizeof (processorid_t)); 332*7c478bd9Sstevel@tonic-gate if (pset_info(PS_MYID, NULL, &ncpus, cpus) == -1) { 333*7c478bd9Sstevel@tonic-gate free(cpus); 334*7c478bd9Sstevel@tonic-gate return (-1); 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate * Remove any CPUs not in caller's pset from lgroup hierarchy 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate nlgrps_max = snap->ss_nlgrps_max; 342*7c478bd9Sstevel@tonic-gate for (i = 0; i < nlgrps_max; i++) { 343*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[i]; 344*7c478bd9Sstevel@tonic-gate if (BT_TEST(snap->ss_lgrpset, i)) 345*7c478bd9Sstevel@tonic-gate prune_cpus(snap, i, cpus, ncpus); 346*7c478bd9Sstevel@tonic-gate else if (lgrp_info->info_lgrpid != LGRP_NONE) 347*7c478bd9Sstevel@tonic-gate prune_cpus(snap, i, NULL, -1); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate if (ncpus > 0) 351*7c478bd9Sstevel@tonic-gate free(cpus); 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate /* 354*7c478bd9Sstevel@tonic-gate * Change lgroup bitmask from just reflecting lgroups overlapping 355*7c478bd9Sstevel@tonic-gate * caller's pset to all lgroups available to caller, starting by 356*7c478bd9Sstevel@tonic-gate * filling in all lgroups and then removing any empty ones below 357*7c478bd9Sstevel@tonic-gate */ 358*7c478bd9Sstevel@tonic-gate for (i = 0; i < nlgrps_max; i++) { 359*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[i]; 360*7c478bd9Sstevel@tonic-gate if (lgrp_info->info_lgrpid == LGRP_NONE) 361*7c478bd9Sstevel@tonic-gate continue; 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate BT_SET(snap->ss_lgrpset, i); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * Remove empty lgroups from lgroup hierarchy, removing it from its 368*7c478bd9Sstevel@tonic-gate * parents and decrementing nlgrps 369*7c478bd9Sstevel@tonic-gate */ 370*7c478bd9Sstevel@tonic-gate for (i = 0; i < nlgrps_max; i++) { 371*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[i]; 372*7c478bd9Sstevel@tonic-gate if (lgrp_info->info_lgrpid == LGRP_NONE) 373*7c478bd9Sstevel@tonic-gate continue; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate ncpus = lgrp_cpus_hier(snap, i, NULL, NULL); 376*7c478bd9Sstevel@tonic-gate nbytes = lgrp_mem_size((lgrp_cookie_t)snap, i, 377*7c478bd9Sstevel@tonic-gate LGRP_MEM_SZ_INSTALLED, LGRP_CONTENT_HIERARCHY); 378*7c478bd9Sstevel@tonic-gate if (ncpus == 0 && nbytes == 0) { 379*7c478bd9Sstevel@tonic-gate BT_CLEAR(snap->ss_lgrpset, i); 380*7c478bd9Sstevel@tonic-gate prune_child(snap, i); 381*7c478bd9Sstevel@tonic-gate snap->ss_nlgrps--; 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate return (0); 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* 390*7c478bd9Sstevel@tonic-gate * Initialize lgroup interface 391*7c478bd9Sstevel@tonic-gate */ 392*7c478bd9Sstevel@tonic-gate lgrp_cookie_t 393*7c478bd9Sstevel@tonic-gate lgrp_init(lgrp_view_t view) 394*7c478bd9Sstevel@tonic-gate { 395*7c478bd9Sstevel@tonic-gate ssize_t bufsize; 396*7c478bd9Sstevel@tonic-gate uint_t gen; 397*7c478bd9Sstevel@tonic-gate int i; 398*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate /* 401*7c478bd9Sstevel@tonic-gate * Check for legal view 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate if (view != LGRP_VIEW_OS && view != LGRP_VIEW_CALLER) { 404*7c478bd9Sstevel@tonic-gate errno = EINVAL; 405*7c478bd9Sstevel@tonic-gate return (LGRP_COOKIE_NONE); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * Try to take a consistent snapshot of lgroup hierarchy 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate snap = NULL; 412*7c478bd9Sstevel@tonic-gate while (snap == NULL) { 413*7c478bd9Sstevel@tonic-gate /* 414*7c478bd9Sstevel@tonic-gate * Get lgroup generation number before taking snapshot 415*7c478bd9Sstevel@tonic-gate */ 416*7c478bd9Sstevel@tonic-gate gen = lgrp_generation(view); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate /* 419*7c478bd9Sstevel@tonic-gate * Get size of buffer needed for snapshot 420*7c478bd9Sstevel@tonic-gate */ 421*7c478bd9Sstevel@tonic-gate bufsize = lgrp_snapshot(NULL, 0); 422*7c478bd9Sstevel@tonic-gate if (bufsize <= 0) { 423*7c478bd9Sstevel@tonic-gate if (errno == ENOMEM) 424*7c478bd9Sstevel@tonic-gate return (LGRP_COOKIE_NONE); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate snap = NULL; 427*7c478bd9Sstevel@tonic-gate continue; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* 431*7c478bd9Sstevel@tonic-gate * Allocate buffer 432*7c478bd9Sstevel@tonic-gate */ 433*7c478bd9Sstevel@tonic-gate snap = malloc(bufsize); 434*7c478bd9Sstevel@tonic-gate if (snap == NULL) 435*7c478bd9Sstevel@tonic-gate return (LGRP_COOKIE_NONE); 436*7c478bd9Sstevel@tonic-gate bzero(snap, bufsize); 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /* 439*7c478bd9Sstevel@tonic-gate * Take snapshot of lgroup hierarchy 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate bufsize = lgrp_snapshot(snap, bufsize); 442*7c478bd9Sstevel@tonic-gate if (bufsize <= 0) { 443*7c478bd9Sstevel@tonic-gate free(snap); 444*7c478bd9Sstevel@tonic-gate if (errno == ENOMEM) 445*7c478bd9Sstevel@tonic-gate return (LGRP_COOKIE_NONE); 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate snap = NULL; 448*7c478bd9Sstevel@tonic-gate continue; 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate /* 452*7c478bd9Sstevel@tonic-gate * See whether lgroup generation number changed 453*7c478bd9Sstevel@tonic-gate */ 454*7c478bd9Sstevel@tonic-gate if (gen == lgrp_generation(view)) 455*7c478bd9Sstevel@tonic-gate break; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate free(snap); 458*7c478bd9Sstevel@tonic-gate snap = NULL; 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* 462*7c478bd9Sstevel@tonic-gate * Remember generation number and view of this snapshot 463*7c478bd9Sstevel@tonic-gate */ 464*7c478bd9Sstevel@tonic-gate snap->ss_gen = gen; 465*7c478bd9Sstevel@tonic-gate snap->ss_view = view; 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * Keep caller's pset ID for caller's view 469*7c478bd9Sstevel@tonic-gate */ 470*7c478bd9Sstevel@tonic-gate snap->ss_pset = 0; 471*7c478bd9Sstevel@tonic-gate if (view == LGRP_VIEW_CALLER) { 472*7c478bd9Sstevel@tonic-gate psetid_t pset; 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate if (pset_bind(PS_QUERY, P_LWPID, P_MYID, &pset) == -1) 475*7c478bd9Sstevel@tonic-gate return ((uintptr_t)-1); 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate snap->ss_pset = pset; 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate /* 481*7c478bd9Sstevel@tonic-gate * Find any orphan lgroups without parents and make them be children 482*7c478bd9Sstevel@tonic-gate * of the root lgroup 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate if (snap->ss_levels > 1) 485*7c478bd9Sstevel@tonic-gate (void) parent_orphans(snap); 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate /* 488*7c478bd9Sstevel@tonic-gate * Prune snapshot of lgroup hierarchy for caller's view 489*7c478bd9Sstevel@tonic-gate */ 490*7c478bd9Sstevel@tonic-gate if (view == LGRP_VIEW_CALLER) 491*7c478bd9Sstevel@tonic-gate (void) prune_tree(snap); 492*7c478bd9Sstevel@tonic-gate else { 493*7c478bd9Sstevel@tonic-gate /* 494*7c478bd9Sstevel@tonic-gate * Change lgroup bitmask from just reflecting lgroups 495*7c478bd9Sstevel@tonic-gate * overlapping caller's pset to all lgroups available 496*7c478bd9Sstevel@tonic-gate */ 497*7c478bd9Sstevel@tonic-gate for (i = 0; i < snap->ss_nlgrps_max; i++) { 498*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[i]; 501*7c478bd9Sstevel@tonic-gate if (lgrp_info->info_lgrpid == LGRP_NONE) 502*7c478bd9Sstevel@tonic-gate continue; 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate BT_SET(snap->ss_lgrpset, i); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate return ((uintptr_t)snap); 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* 513*7c478bd9Sstevel@tonic-gate * Return whether given cookie is out-of-date (stale) or not 514*7c478bd9Sstevel@tonic-gate */ 515*7c478bd9Sstevel@tonic-gate int 516*7c478bd9Sstevel@tonic-gate lgrp_cookie_stale(lgrp_cookie_t cookie) 517*7c478bd9Sstevel@tonic-gate { 518*7c478bd9Sstevel@tonic-gate psetid_t pset; 519*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate /* 522*7c478bd9Sstevel@tonic-gate * Check for bad cookie 523*7c478bd9Sstevel@tonic-gate */ 524*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 525*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie) { 526*7c478bd9Sstevel@tonic-gate errno = EINVAL; 527*7c478bd9Sstevel@tonic-gate return (-1); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate /* 531*7c478bd9Sstevel@tonic-gate * Check generation number which changes when lgroup hierarchy changes 532*7c478bd9Sstevel@tonic-gate * or pset contents change for caller's view 533*7c478bd9Sstevel@tonic-gate */ 534*7c478bd9Sstevel@tonic-gate if (snap->ss_gen != lgrp_generation(snap->ss_view)) 535*7c478bd9Sstevel@tonic-gate return (1); 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate /* 538*7c478bd9Sstevel@tonic-gate * See whether pset binding has changed for caller's view 539*7c478bd9Sstevel@tonic-gate */ 540*7c478bd9Sstevel@tonic-gate if (snap->ss_view == LGRP_VIEW_CALLER) { 541*7c478bd9Sstevel@tonic-gate if (pset_bind(PS_QUERY, P_LWPID, P_MYID, &pset) == -1) 542*7c478bd9Sstevel@tonic-gate return (-1); 543*7c478bd9Sstevel@tonic-gate if (snap->ss_pset != pset) 544*7c478bd9Sstevel@tonic-gate return (1); 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate return (0); /* cookie isn't stale */ 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate /* 552*7c478bd9Sstevel@tonic-gate * Get view of lgroup hierarchy from snapshot represented by given cookie 553*7c478bd9Sstevel@tonic-gate */ 554*7c478bd9Sstevel@tonic-gate lgrp_view_t 555*7c478bd9Sstevel@tonic-gate lgrp_view(lgrp_cookie_t cookie) 556*7c478bd9Sstevel@tonic-gate { 557*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 560*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie) { 561*7c478bd9Sstevel@tonic-gate errno = EINVAL; 562*7c478bd9Sstevel@tonic-gate return (-1); 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate return (snap->ss_view); 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate /* 570*7c478bd9Sstevel@tonic-gate * Get number of lgroups 571*7c478bd9Sstevel@tonic-gate */ 572*7c478bd9Sstevel@tonic-gate int 573*7c478bd9Sstevel@tonic-gate lgrp_nlgrps(lgrp_cookie_t cookie) 574*7c478bd9Sstevel@tonic-gate { 575*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie) { 580*7c478bd9Sstevel@tonic-gate errno = EINVAL; 581*7c478bd9Sstevel@tonic-gate return (-1); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate return (snap->ss_nlgrps); 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate /* 589*7c478bd9Sstevel@tonic-gate * Return root lgroup ID 590*7c478bd9Sstevel@tonic-gate */ 591*7c478bd9Sstevel@tonic-gate lgrp_id_t 592*7c478bd9Sstevel@tonic-gate lgrp_root(lgrp_cookie_t cookie) 593*7c478bd9Sstevel@tonic-gate { 594*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie) { 599*7c478bd9Sstevel@tonic-gate errno = EINVAL; 600*7c478bd9Sstevel@tonic-gate return (-1); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate return (snap->ss_root); 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate /* 608*7c478bd9Sstevel@tonic-gate * Get parent lgroups of given lgroup 609*7c478bd9Sstevel@tonic-gate */ 610*7c478bd9Sstevel@tonic-gate int 611*7c478bd9Sstevel@tonic-gate lgrp_parents(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_id_t *parents, 612*7c478bd9Sstevel@tonic-gate uint_t count) 613*7c478bd9Sstevel@tonic-gate { 614*7c478bd9Sstevel@tonic-gate int i; 615*7c478bd9Sstevel@tonic-gate ulong_t *lgrp_parents; 616*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 617*7c478bd9Sstevel@tonic-gate int nlgrps_max; 618*7c478bd9Sstevel@tonic-gate int nparents; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate /* 623*7c478bd9Sstevel@tonic-gate * Check for valid arguments 624*7c478bd9Sstevel@tonic-gate */ 625*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie || 626*7c478bd9Sstevel@tonic-gate lgrp < 0 || lgrp == LGRP_NONE) { 627*7c478bd9Sstevel@tonic-gate errno = EINVAL; 628*7c478bd9Sstevel@tonic-gate return (-1); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* 632*7c478bd9Sstevel@tonic-gate * See whether given lgroup exists 633*7c478bd9Sstevel@tonic-gate */ 634*7c478bd9Sstevel@tonic-gate nlgrps_max = snap->ss_nlgrps_max; 635*7c478bd9Sstevel@tonic-gate if (lgrp >= nlgrps_max || !BT_TEST(snap->ss_lgrpset, lgrp)) { 636*7c478bd9Sstevel@tonic-gate errno = ESRCH; 637*7c478bd9Sstevel@tonic-gate return (-1); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * No parents, since given lgroup is root lgroup or 642*7c478bd9Sstevel@tonic-gate * only one level in lgroup hierarchy (ie. SMP) 643*7c478bd9Sstevel@tonic-gate */ 644*7c478bd9Sstevel@tonic-gate if (lgrp == snap->ss_root || snap->ss_levels == 1) { 645*7c478bd9Sstevel@tonic-gate if (parents == NULL || count < 1) 646*7c478bd9Sstevel@tonic-gate return (0); 647*7c478bd9Sstevel@tonic-gate return (0); 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate /* 651*7c478bd9Sstevel@tonic-gate * Make sure that parents exist 652*7c478bd9Sstevel@tonic-gate */ 653*7c478bd9Sstevel@tonic-gate if (snap->ss_parents == NULL) { 654*7c478bd9Sstevel@tonic-gate errno = ESRCH; 655*7c478bd9Sstevel@tonic-gate return (-1); 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate /* 659*7c478bd9Sstevel@tonic-gate * Given lgroup should have a parent 660*7c478bd9Sstevel@tonic-gate */ 661*7c478bd9Sstevel@tonic-gate lgrp_parents = &snap->ss_parents[lgrp * BT_BITOUL(nlgrps_max)]; 662*7c478bd9Sstevel@tonic-gate if (lgrp_parents == NULL) { 663*7c478bd9Sstevel@tonic-gate errno = ESRCH; 664*7c478bd9Sstevel@tonic-gate return (-1); 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate /* 668*7c478bd9Sstevel@tonic-gate * Check lgroup parents bitmask, fill in parents array, and return 669*7c478bd9Sstevel@tonic-gate * number of parents 670*7c478bd9Sstevel@tonic-gate */ 671*7c478bd9Sstevel@tonic-gate nparents = 0; 672*7c478bd9Sstevel@tonic-gate for (i = 0; i < nlgrps_max; i++) { 673*7c478bd9Sstevel@tonic-gate if (BT_TEST(lgrp_parents, i)) { 674*7c478bd9Sstevel@tonic-gate if (parents != NULL && nparents < count) { 675*7c478bd9Sstevel@tonic-gate parents[nparents] = i; 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate nparents++; 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate return (nparents); 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate /* 685*7c478bd9Sstevel@tonic-gate * Get children lgroups of given lgroup 686*7c478bd9Sstevel@tonic-gate */ 687*7c478bd9Sstevel@tonic-gate int 688*7c478bd9Sstevel@tonic-gate lgrp_children(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_id_t *children, 689*7c478bd9Sstevel@tonic-gate uint_t count) 690*7c478bd9Sstevel@tonic-gate { 691*7c478bd9Sstevel@tonic-gate int i; 692*7c478bd9Sstevel@tonic-gate ulong_t *lgrp_children; 693*7c478bd9Sstevel@tonic-gate int nlgrps_max; 694*7c478bd9Sstevel@tonic-gate int nchildren; 695*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* 700*7c478bd9Sstevel@tonic-gate * Check for valid arguments 701*7c478bd9Sstevel@tonic-gate */ 702*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie || 703*7c478bd9Sstevel@tonic-gate lgrp < 0 || lgrp == LGRP_NONE) { 704*7c478bd9Sstevel@tonic-gate errno = EINVAL; 705*7c478bd9Sstevel@tonic-gate return (-1); 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate /* 709*7c478bd9Sstevel@tonic-gate * See whether given lgroup exists 710*7c478bd9Sstevel@tonic-gate */ 711*7c478bd9Sstevel@tonic-gate nlgrps_max = snap->ss_nlgrps_max; 712*7c478bd9Sstevel@tonic-gate if (lgrp >= nlgrps_max || !BT_TEST(snap->ss_lgrpset, lgrp)) { 713*7c478bd9Sstevel@tonic-gate errno = ESRCH; 714*7c478bd9Sstevel@tonic-gate return (-1); 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate /* 718*7c478bd9Sstevel@tonic-gate * No children, since only one level in lgroup hierarchy (ie. SMP) 719*7c478bd9Sstevel@tonic-gate */ 720*7c478bd9Sstevel@tonic-gate if (snap->ss_levels == 1) { 721*7c478bd9Sstevel@tonic-gate if (children == NULL || count < 1) 722*7c478bd9Sstevel@tonic-gate return (0); 723*7c478bd9Sstevel@tonic-gate return (0); 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate /* 727*7c478bd9Sstevel@tonic-gate * Make sure that children exist 728*7c478bd9Sstevel@tonic-gate */ 729*7c478bd9Sstevel@tonic-gate if (snap->ss_children == NULL) { 730*7c478bd9Sstevel@tonic-gate errno = ESRCH; 731*7c478bd9Sstevel@tonic-gate return (-1); 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate /* 735*7c478bd9Sstevel@tonic-gate * Given lgroup may not have any children 736*7c478bd9Sstevel@tonic-gate */ 737*7c478bd9Sstevel@tonic-gate lgrp_children = &snap->ss_children[lgrp * BT_BITOUL(nlgrps_max)]; 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate if (lgrp_children == NULL) 740*7c478bd9Sstevel@tonic-gate return (0); 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate /* 743*7c478bd9Sstevel@tonic-gate * Check lgroup children bitmask, fill in children array, and return 744*7c478bd9Sstevel@tonic-gate * number of children 745*7c478bd9Sstevel@tonic-gate */ 746*7c478bd9Sstevel@tonic-gate nchildren = 0; 747*7c478bd9Sstevel@tonic-gate for (i = 0; i < nlgrps_max; i++) { 748*7c478bd9Sstevel@tonic-gate if (BT_TEST(lgrp_children, i)) { 749*7c478bd9Sstevel@tonic-gate if (children != NULL && nchildren < count) 750*7c478bd9Sstevel@tonic-gate children[nchildren] = i; 751*7c478bd9Sstevel@tonic-gate nchildren++; 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate return (nchildren); 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate /* 759*7c478bd9Sstevel@tonic-gate * Get all CPUs within given lgroup (hierarchy) 760*7c478bd9Sstevel@tonic-gate */ 761*7c478bd9Sstevel@tonic-gate static int 762*7c478bd9Sstevel@tonic-gate lgrp_cpus_hier(lgrp_snapshot_header_t *snap, lgrp_id_t lgrp, 763*7c478bd9Sstevel@tonic-gate processorid_t **cpuids, uint_t *count) 764*7c478bd9Sstevel@tonic-gate { 765*7c478bd9Sstevel@tonic-gate processorid_t *cpus; 766*7c478bd9Sstevel@tonic-gate int i; 767*7c478bd9Sstevel@tonic-gate int j; 768*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 769*7c478bd9Sstevel@tonic-gate int ncpus; 770*7c478bd9Sstevel@tonic-gate int nlgrps_max; 771*7c478bd9Sstevel@tonic-gate ulong_t *rset; 772*7c478bd9Sstevel@tonic-gate int total; 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate /* 775*7c478bd9Sstevel@tonic-gate * Get lgroup info 776*7c478bd9Sstevel@tonic-gate */ 777*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[lgrp]; 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate if (lgrp_info == NULL) { 780*7c478bd9Sstevel@tonic-gate errno = ESRCH; 781*7c478bd9Sstevel@tonic-gate return (-1); 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate /* 785*7c478bd9Sstevel@tonic-gate * Check whether given lgroup contains any lgroups with CPU resources 786*7c478bd9Sstevel@tonic-gate */ 787*7c478bd9Sstevel@tonic-gate if (lgrp_info->info_rset == NULL) 788*7c478bd9Sstevel@tonic-gate return (0); 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate nlgrps_max = snap->ss_nlgrps_max; 791*7c478bd9Sstevel@tonic-gate rset = &lgrp_info->info_rset[LGRP_RSRC_CPU * BT_BITOUL(nlgrps_max)]; 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate /* 794*7c478bd9Sstevel@tonic-gate * Get all CPUs within this lgroup 795*7c478bd9Sstevel@tonic-gate */ 796*7c478bd9Sstevel@tonic-gate total = 0; 797*7c478bd9Sstevel@tonic-gate for (i = 0; i < nlgrps_max; i++) { 798*7c478bd9Sstevel@tonic-gate if (!BT_TEST(rset, i)) 799*7c478bd9Sstevel@tonic-gate continue; 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[i]; 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate /* 804*7c478bd9Sstevel@tonic-gate * Get all CPUs within lgroup 805*7c478bd9Sstevel@tonic-gate */ 806*7c478bd9Sstevel@tonic-gate cpus = lgrp_info->info_cpuids; 807*7c478bd9Sstevel@tonic-gate ncpus = lgrp_info->info_ncpus; 808*7c478bd9Sstevel@tonic-gate total += ncpus; 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate /* 811*7c478bd9Sstevel@tonic-gate * Copy as many CPU IDs into array that will fit 812*7c478bd9Sstevel@tonic-gate * and decrement count and increment array pointer 813*7c478bd9Sstevel@tonic-gate * as we go 814*7c478bd9Sstevel@tonic-gate */ 815*7c478bd9Sstevel@tonic-gate if (cpuids && *cpuids && count) { 816*7c478bd9Sstevel@tonic-gate for (j = 0; j < ncpus; j++) { 817*7c478bd9Sstevel@tonic-gate if (*count) { 818*7c478bd9Sstevel@tonic-gate **cpuids = cpus[j]; 819*7c478bd9Sstevel@tonic-gate (*cpuids)++; 820*7c478bd9Sstevel@tonic-gate (*count)--; 821*7c478bd9Sstevel@tonic-gate } 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate return (total); 827*7c478bd9Sstevel@tonic-gate } 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* 831*7c478bd9Sstevel@tonic-gate * Get CPUs in given lgroup 832*7c478bd9Sstevel@tonic-gate */ 833*7c478bd9Sstevel@tonic-gate int 834*7c478bd9Sstevel@tonic-gate lgrp_cpus(lgrp_cookie_t cookie, lgrp_id_t lgrp, processorid_t *cpuids, 835*7c478bd9Sstevel@tonic-gate uint_t count, lgrp_content_t content) 836*7c478bd9Sstevel@tonic-gate { 837*7c478bd9Sstevel@tonic-gate int i; 838*7c478bd9Sstevel@tonic-gate processorid_t *cpus; 839*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 840*7c478bd9Sstevel@tonic-gate int ncpus; 841*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate /* 846*7c478bd9Sstevel@tonic-gate * Check for valid arguments 847*7c478bd9Sstevel@tonic-gate */ 848*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie || 849*7c478bd9Sstevel@tonic-gate lgrp < 0 || lgrp == LGRP_NONE || 850*7c478bd9Sstevel@tonic-gate (content != LGRP_CONTENT_DIRECT && 851*7c478bd9Sstevel@tonic-gate content != LGRP_CONTENT_HIERARCHY)) { 852*7c478bd9Sstevel@tonic-gate errno = EINVAL; 853*7c478bd9Sstevel@tonic-gate return (-1); 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate /* 857*7c478bd9Sstevel@tonic-gate * See whether given lgroup exists 858*7c478bd9Sstevel@tonic-gate */ 859*7c478bd9Sstevel@tonic-gate if (lgrp >= snap->ss_nlgrps_max || snap->ss_info == NULL || 860*7c478bd9Sstevel@tonic-gate !BT_TEST(snap->ss_lgrpset, lgrp)) { 861*7c478bd9Sstevel@tonic-gate errno = ESRCH; 862*7c478bd9Sstevel@tonic-gate return (-1); 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate /* 866*7c478bd9Sstevel@tonic-gate * Get lgroup info 867*7c478bd9Sstevel@tonic-gate */ 868*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[lgrp]; 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate /* 871*7c478bd9Sstevel@tonic-gate * Get contents of lgroup 872*7c478bd9Sstevel@tonic-gate */ 873*7c478bd9Sstevel@tonic-gate switch (content) { 874*7c478bd9Sstevel@tonic-gate case LGRP_CONTENT_DIRECT: 875*7c478bd9Sstevel@tonic-gate /* 876*7c478bd9Sstevel@tonic-gate * Get CPUs contained directly within given lgroup 877*7c478bd9Sstevel@tonic-gate */ 878*7c478bd9Sstevel@tonic-gate cpus = lgrp_info->info_cpuids; 879*7c478bd9Sstevel@tonic-gate ncpus = lgrp_info->info_ncpus; 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate /* 882*7c478bd9Sstevel@tonic-gate * No array to copy CPU IDs into, 883*7c478bd9Sstevel@tonic-gate * so just return number of CPUs. 884*7c478bd9Sstevel@tonic-gate */ 885*7c478bd9Sstevel@tonic-gate if (cpuids == NULL) 886*7c478bd9Sstevel@tonic-gate return (ncpus); 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate /* 889*7c478bd9Sstevel@tonic-gate * Copy as many CPU IDs into array that will fit 890*7c478bd9Sstevel@tonic-gate */ 891*7c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) 892*7c478bd9Sstevel@tonic-gate if (i < count) 893*7c478bd9Sstevel@tonic-gate cpuids[i] = cpus[i]; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate return (ncpus); 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate case LGRP_CONTENT_ALL: 898*7c478bd9Sstevel@tonic-gate return (lgrp_cpus_hier(snap, lgrp, &cpuids, &count)); 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate default: 901*7c478bd9Sstevel@tonic-gate errno = EINVAL; 902*7c478bd9Sstevel@tonic-gate return (-1); 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate } 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate /* 908*7c478bd9Sstevel@tonic-gate * Return physical memory size in pages for given lgroup 909*7c478bd9Sstevel@tonic-gate */ 910*7c478bd9Sstevel@tonic-gate lgrp_mem_size_t 911*7c478bd9Sstevel@tonic-gate lgrp_mem_size(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_mem_size_flag_t type, 912*7c478bd9Sstevel@tonic-gate lgrp_content_t content) 913*7c478bd9Sstevel@tonic-gate { 914*7c478bd9Sstevel@tonic-gate int i; 915*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 916*7c478bd9Sstevel@tonic-gate int nlgrps_max; 917*7c478bd9Sstevel@tonic-gate int pgsz; 918*7c478bd9Sstevel@tonic-gate ulong_t *rset; 919*7c478bd9Sstevel@tonic-gate lgrp_mem_size_t size; 920*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate /* 925*7c478bd9Sstevel@tonic-gate * Check for valid arguments 926*7c478bd9Sstevel@tonic-gate */ 927*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie || 928*7c478bd9Sstevel@tonic-gate lgrp < 0 || lgrp == LGRP_NONE) { 929*7c478bd9Sstevel@tonic-gate errno = EINVAL; 930*7c478bd9Sstevel@tonic-gate return (-1); 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate /* 934*7c478bd9Sstevel@tonic-gate * See whether given lgroup exists 935*7c478bd9Sstevel@tonic-gate */ 936*7c478bd9Sstevel@tonic-gate nlgrps_max = snap->ss_nlgrps_max; 937*7c478bd9Sstevel@tonic-gate if (lgrp >= nlgrps_max || snap->ss_info == NULL || 938*7c478bd9Sstevel@tonic-gate !BT_TEST(snap->ss_lgrpset, lgrp)) { 939*7c478bd9Sstevel@tonic-gate errno = ESRCH; 940*7c478bd9Sstevel@tonic-gate return (-1); 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate pgsz = getpagesize(); 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate /* 946*7c478bd9Sstevel@tonic-gate * Get lgroup info 947*7c478bd9Sstevel@tonic-gate */ 948*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[lgrp]; 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate switch (content) { 951*7c478bd9Sstevel@tonic-gate case LGRP_CONTENT_DIRECT: 952*7c478bd9Sstevel@tonic-gate /* 953*7c478bd9Sstevel@tonic-gate * Get memory contained directly in this lgroup 954*7c478bd9Sstevel@tonic-gate */ 955*7c478bd9Sstevel@tonic-gate switch (type) { 956*7c478bd9Sstevel@tonic-gate case LGRP_MEM_SZ_FREE: 957*7c478bd9Sstevel@tonic-gate size = (lgrp_mem_size_t)pgsz * 958*7c478bd9Sstevel@tonic-gate lgrp_info->info_mem_free; 959*7c478bd9Sstevel@tonic-gate return (size); 960*7c478bd9Sstevel@tonic-gate case LGRP_MEM_SZ_INSTALLED: 961*7c478bd9Sstevel@tonic-gate size = (lgrp_mem_size_t)pgsz * 962*7c478bd9Sstevel@tonic-gate lgrp_info->info_mem_install; 963*7c478bd9Sstevel@tonic-gate return (size); 964*7c478bd9Sstevel@tonic-gate default: 965*7c478bd9Sstevel@tonic-gate errno = EINVAL; 966*7c478bd9Sstevel@tonic-gate return (-1); 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate case LGRP_CONTENT_ALL: 970*7c478bd9Sstevel@tonic-gate /* 971*7c478bd9Sstevel@tonic-gate * Get memory contained within this lgroup (and its children) 972*7c478bd9Sstevel@tonic-gate */ 973*7c478bd9Sstevel@tonic-gate /* 974*7c478bd9Sstevel@tonic-gate * Check whether given lgroup contains any lgroups with CPU 975*7c478bd9Sstevel@tonic-gate * resources 976*7c478bd9Sstevel@tonic-gate */ 977*7c478bd9Sstevel@tonic-gate if (lgrp_info->info_rset == NULL) 978*7c478bd9Sstevel@tonic-gate return (0); 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate rset = &lgrp_info->info_rset[LGRP_RSRC_MEM * 981*7c478bd9Sstevel@tonic-gate BT_BITOUL(nlgrps_max)]; 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate /* 984*7c478bd9Sstevel@tonic-gate * Add up memory in lgroup resources 985*7c478bd9Sstevel@tonic-gate */ 986*7c478bd9Sstevel@tonic-gate size = 0; 987*7c478bd9Sstevel@tonic-gate for (i = 0; i < nlgrps_max; i++) { 988*7c478bd9Sstevel@tonic-gate if (!BT_TEST(rset, i)) 989*7c478bd9Sstevel@tonic-gate continue; 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[i]; 992*7c478bd9Sstevel@tonic-gate switch (type) { 993*7c478bd9Sstevel@tonic-gate case LGRP_MEM_SZ_FREE: 994*7c478bd9Sstevel@tonic-gate size += (lgrp_mem_size_t)pgsz * 995*7c478bd9Sstevel@tonic-gate lgrp_info->info_mem_free; 996*7c478bd9Sstevel@tonic-gate break; 997*7c478bd9Sstevel@tonic-gate case LGRP_MEM_SZ_INSTALLED: 998*7c478bd9Sstevel@tonic-gate size += (lgrp_mem_size_t)pgsz * 999*7c478bd9Sstevel@tonic-gate lgrp_info->info_mem_install; 1000*7c478bd9Sstevel@tonic-gate break; 1001*7c478bd9Sstevel@tonic-gate default: 1002*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1003*7c478bd9Sstevel@tonic-gate return (-1); 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate } 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate return (size); 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate default: 1011*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1012*7c478bd9Sstevel@tonic-gate return (-1); 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate } 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate /* 1018*7c478bd9Sstevel@tonic-gate * Get resources for a particuliar lgroup 1019*7c478bd9Sstevel@tonic-gate */ 1020*7c478bd9Sstevel@tonic-gate int 1021*7c478bd9Sstevel@tonic-gate lgrp_resources(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_id_t *lgrps, 1022*7c478bd9Sstevel@tonic-gate uint_t count, lgrp_rsrc_t type) 1023*7c478bd9Sstevel@tonic-gate { 1024*7c478bd9Sstevel@tonic-gate int i; 1025*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 1026*7c478bd9Sstevel@tonic-gate int nlgrps; 1027*7c478bd9Sstevel@tonic-gate int nlgrps_max; 1028*7c478bd9Sstevel@tonic-gate ulong_t *rset; 1029*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate /* 1034*7c478bd9Sstevel@tonic-gate * Check for valid arguments 1035*7c478bd9Sstevel@tonic-gate */ 1036*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie || 1037*7c478bd9Sstevel@tonic-gate lgrp < 0 || lgrp == LGRP_NONE || 1038*7c478bd9Sstevel@tonic-gate (type != LGRP_RSRC_CPU && type != LGRP_RSRC_MEM)) { 1039*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1040*7c478bd9Sstevel@tonic-gate return (-1); 1041*7c478bd9Sstevel@tonic-gate } 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate /* 1044*7c478bd9Sstevel@tonic-gate * See whether given lgroup exists 1045*7c478bd9Sstevel@tonic-gate */ 1046*7c478bd9Sstevel@tonic-gate nlgrps_max = snap->ss_nlgrps_max; 1047*7c478bd9Sstevel@tonic-gate if (lgrp >= nlgrps_max || snap->ss_info == NULL || 1048*7c478bd9Sstevel@tonic-gate !BT_TEST(snap->ss_lgrpset, lgrp)) { 1049*7c478bd9Sstevel@tonic-gate errno = ESRCH; 1050*7c478bd9Sstevel@tonic-gate return (-1); 1051*7c478bd9Sstevel@tonic-gate } 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate /* 1054*7c478bd9Sstevel@tonic-gate * Get lgroup info 1055*7c478bd9Sstevel@tonic-gate */ 1056*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[lgrp]; 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate /* 1059*7c478bd9Sstevel@tonic-gate * Count number lgroups contained within this lgroup and 1060*7c478bd9Sstevel@tonic-gate * copy as many lgroup IDs into array that will fit 1061*7c478bd9Sstevel@tonic-gate */ 1062*7c478bd9Sstevel@tonic-gate rset = &lgrp_info->info_rset[type * BT_BITOUL(nlgrps_max)]; 1063*7c478bd9Sstevel@tonic-gate nlgrps = 0; 1064*7c478bd9Sstevel@tonic-gate for (i = 0; i < snap->ss_nlgrps_max; i++) 1065*7c478bd9Sstevel@tonic-gate if (BT_TEST(rset, i)) { 1066*7c478bd9Sstevel@tonic-gate if (lgrps != NULL && nlgrps < count) 1067*7c478bd9Sstevel@tonic-gate lgrps[nlgrps] = i; 1068*7c478bd9Sstevel@tonic-gate nlgrps++; 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate return (nlgrps); 1072*7c478bd9Sstevel@tonic-gate } 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate /* 1076*7c478bd9Sstevel@tonic-gate * Finish using lgroup interface 1077*7c478bd9Sstevel@tonic-gate */ 1078*7c478bd9Sstevel@tonic-gate int 1079*7c478bd9Sstevel@tonic-gate lgrp_fini(lgrp_cookie_t cookie) 1080*7c478bd9Sstevel@tonic-gate { 1081*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 1084*7c478bd9Sstevel@tonic-gate 1085*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie) { 1086*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1087*7c478bd9Sstevel@tonic-gate return (-1); 1088*7c478bd9Sstevel@tonic-gate } 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate bzero(snap, snap->ss_size); 1091*7c478bd9Sstevel@tonic-gate free(snap); 1092*7c478bd9Sstevel@tonic-gate snap = NULL; 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate return (0); 1095*7c478bd9Sstevel@tonic-gate } 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate /* 1099*7c478bd9Sstevel@tonic-gate * Return latency between "from" and "to" lgroups 1100*7c478bd9Sstevel@tonic-gate * 1101*7c478bd9Sstevel@tonic-gate * This latency number can only be used for relative comparison 1102*7c478bd9Sstevel@tonic-gate * between lgroups on the running system, cannot be used across platforms, 1103*7c478bd9Sstevel@tonic-gate * and may not reflect the actual latency. It is platform and implementation 1104*7c478bd9Sstevel@tonic-gate * specific, so platform gets to decide its value. It would be nice if the 1105*7c478bd9Sstevel@tonic-gate * number was at least proportional to make comparisons more meaningful though. 1106*7c478bd9Sstevel@tonic-gate */ 1107*7c478bd9Sstevel@tonic-gate int 1108*7c478bd9Sstevel@tonic-gate lgrp_latency(lgrp_id_t from, lgrp_id_t to) 1109*7c478bd9Sstevel@tonic-gate { 1110*7c478bd9Sstevel@tonic-gate lgrp_cookie_t cookie; 1111*7c478bd9Sstevel@tonic-gate int latency; 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate cookie = lgrp_init(LGRP_VIEW_OS); 1114*7c478bd9Sstevel@tonic-gate latency = lgrp_latency_cookie(cookie, from, to, LGRP_LAT_CPU_TO_MEM); 1115*7c478bd9Sstevel@tonic-gate (void) lgrp_fini(cookie); 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate return (latency); 1118*7c478bd9Sstevel@tonic-gate } 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate /* 1122*7c478bd9Sstevel@tonic-gate * Return latency between "from" and "to" lgroups 1123*7c478bd9Sstevel@tonic-gate * 1124*7c478bd9Sstevel@tonic-gate * This latency number can only be used for relative comparison 1125*7c478bd9Sstevel@tonic-gate * between lgroups on the running system, cannot be used across platforms, 1126*7c478bd9Sstevel@tonic-gate * and may not reflect the actual latency. It is platform and implementation 1127*7c478bd9Sstevel@tonic-gate * specific, so platform gets to decide its value. It would be nice if the 1128*7c478bd9Sstevel@tonic-gate * number was at least proportional to make comparisons more meaningful though. 1129*7c478bd9Sstevel@tonic-gate */ 1130*7c478bd9Sstevel@tonic-gate int 1131*7c478bd9Sstevel@tonic-gate lgrp_latency_cookie(lgrp_cookie_t cookie, lgrp_id_t from, lgrp_id_t to, 1132*7c478bd9Sstevel@tonic-gate lgrp_lat_between_t between) 1133*7c478bd9Sstevel@tonic-gate { 1134*7c478bd9Sstevel@tonic-gate lgrp_info_t *lgrp_info; 1135*7c478bd9Sstevel@tonic-gate lgrp_mem_size_t nbytes; 1136*7c478bd9Sstevel@tonic-gate int ncpus; 1137*7c478bd9Sstevel@tonic-gate int nlgrps_max; 1138*7c478bd9Sstevel@tonic-gate lgrp_snapshot_header_t *snap; 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate snap = (lgrp_snapshot_header_t *)cookie; 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate /* 1143*7c478bd9Sstevel@tonic-gate * Check for valid snapshot, lgroup, and between flag 1144*7c478bd9Sstevel@tonic-gate */ 1145*7c478bd9Sstevel@tonic-gate if (snap == NULL || snap->ss_magic != cookie || from < 0 || to < 0 || 1146*7c478bd9Sstevel@tonic-gate between != LGRP_LAT_CPU_TO_MEM) { 1147*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1148*7c478bd9Sstevel@tonic-gate return (-1); 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate /* 1152*7c478bd9Sstevel@tonic-gate * Check whether lgroups exist 1153*7c478bd9Sstevel@tonic-gate */ 1154*7c478bd9Sstevel@tonic-gate nlgrps_max = snap->ss_nlgrps_max; 1155*7c478bd9Sstevel@tonic-gate if (from >= nlgrps_max || to >= nlgrps_max) { 1156*7c478bd9Sstevel@tonic-gate errno = ESRCH; 1157*7c478bd9Sstevel@tonic-gate return (-1); 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate /* 1161*7c478bd9Sstevel@tonic-gate * Check whether "from" lgroup has any CPUs 1162*7c478bd9Sstevel@tonic-gate */ 1163*7c478bd9Sstevel@tonic-gate ncpus = lgrp_cpus(cookie, from, NULL, 0, LGRP_CONTENT_HIERARCHY); 1164*7c478bd9Sstevel@tonic-gate if (ncpus <= 0) { 1165*7c478bd9Sstevel@tonic-gate if (ncpus == 0) 1166*7c478bd9Sstevel@tonic-gate errno = ESRCH; 1167*7c478bd9Sstevel@tonic-gate return (-1); 1168*7c478bd9Sstevel@tonic-gate } 1169*7c478bd9Sstevel@tonic-gate 1170*7c478bd9Sstevel@tonic-gate /* 1171*7c478bd9Sstevel@tonic-gate * Check whether "to" lgroup has any memory 1172*7c478bd9Sstevel@tonic-gate */ 1173*7c478bd9Sstevel@tonic-gate nbytes = lgrp_mem_size(cookie, to, LGRP_MEM_SZ_INSTALLED, 1174*7c478bd9Sstevel@tonic-gate LGRP_CONTENT_HIERARCHY); 1175*7c478bd9Sstevel@tonic-gate if (nbytes <= 0) { 1176*7c478bd9Sstevel@tonic-gate if (nbytes == 0) 1177*7c478bd9Sstevel@tonic-gate errno = ESRCH; 1178*7c478bd9Sstevel@tonic-gate return (-1); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate if (from == to) { 1182*7c478bd9Sstevel@tonic-gate lgrp_info = &snap->ss_info[from]; 1183*7c478bd9Sstevel@tonic-gate return (lgrp_info->info_latency); 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate return (snap->ss_latencies[from][to]); 1187*7c478bd9Sstevel@tonic-gate } 1188