1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * ident "%Z%%M% %I% %E% SMI" 27 * 28 */ 29 30 package com.sun.solaris.service.locality; 31 32 import java.util.*; 33 34 import com.sun.solaris.service.pools.*; 35 36 /** 37 * A representation of the Locality Groups for a single Solaris 38 * instance. 39 */ 40 public class LocalityDomain 41 { 42 /** 43 * Obtain a Locality Group snapshot based on the view 44 * available to the caller. 45 */ 46 public static final int LGRP_VIEW_CALLER = 0; 47 48 /** 49 * Obtain a Locality Group snapshot based on the view 50 * of the Operating System. 51 */ 52 public static final int LGRP_VIEW_OS = 1; 53 54 static 55 { 56 System.loadLibrary("jlgrp"); 57 } 58 59 /** 60 * The view used to create this LocalityDomain. 61 */ 62 private int view; 63 64 /** 65 * The cookie which represents the snapshot of locality 66 * information held by the lgrp library. 67 */ 68 private long cookie; 69 70 /** 71 * The root LocalityGroup for the LocalityDomain 72 */ 73 private LocalityGroup root; 74 75 /** 76 * Cached value of maxLatency. 77 */ 78 private final int maxLatency; 79 80 /** 81 * String representation of often used property. 82 */ 83 private final static String CPU_SYS_ID = "cpu.sys_id"; 84 85 /** 86 * Constructor. 87 * 88 * @param view to use when creating the LocalityDomain. 89 * @throws Exception if there is a problem initializing the 90 * lgrp snapshot. 91 */ 92 public LocalityDomain(int view) throws Exception 93 { 94 this.view = view; 95 cookie = jl_init(view); 96 root = jl_root(); 97 /* 98 * The maxLatency calculation is expensive and is used 99 * every time a locality objective is examined. Since 100 * it will never change over the lifetime of a 101 * LocalityDomain, we calculate it once in the 102 * constructor and cache for future use. 103 */ 104 maxLatency = calcMaxLatency(); 105 } 106 107 /** 108 * Reclaim the resource allocated by the C proxy. 109 * 110 * @throws Throwable if there is a problem reclaiming the reosurces. 111 */ 112 protected void finalize() throws Throwable 113 { 114 try 115 { 116 close(); 117 } 118 finally 119 { 120 super.finalize(); 121 } 122 } 123 124 /** 125 * Return the "root" LocalityGroup. 126 */ 127 public LocalityGroup getRoot() 128 { 129 return (root); 130 } 131 132 /** 133 * Close this LocalityDomain. Resources are reclaimed in the C 134 * proxy and this LocalityDomain should never be used 135 * again. None of the LocalityGroups which are referenced from 136 * this LocalityDomain should be used after this method is 137 * invoked. NB: jl_fini returns a success indicator which is 138 * ignored as we are closing this domain. 139 */ 140 public void close() 141 { 142 if (cookie != 0) { 143 jl_fini(); 144 cookie = 0; 145 root = null; 146 } 147 } 148 149 /** 150 * Return a string representation of this instance. 151 */ 152 public String toString() 153 { 154 return (root.toString()); 155 } 156 157 /** 158 * Return the groups in this domain to which the supplied cpus 159 * belong, excluding the supplied set of groups. 160 * 161 * @param exclude Set of groups to be excluded. 162 * @param cpus List of cpus 163 * 164 * @throws PoolsException if there is an error accessing the 165 * cpu details. 166 */ 167 public Set foreignGroups(Set exclude, List cpus) throws PoolsException 168 { 169 Iterator cpuIt = cpus.iterator(); 170 Set result = new HashSet(); 171 while (cpuIt.hasNext()) { 172 Component comp = (Component) cpuIt.next(); 173 int id = (int) comp.getLongProperty(CPU_SYS_ID); 174 LocalityGroup group = getGroup(id); 175 if (group != null && exclude.contains(group) == false) 176 result.add(group); 177 } 178 return (result); 179 } 180 181 /** 182 * Return the locality group which contains the majority of 183 * the cpus in the supplied list. If more than one group 184 * satisfies this criteria, then the choice of group is 185 * deterministic but unspecified. 186 * 187 * @param cpus List of cpus to be examined. 188 * 189 * @throws PoolsException if there is an error accessing the 190 * cpu details. 191 */ 192 public LocalityGroup getRepresentativeGroup(List cpus) 193 throws PoolsException 194 { 195 Iterator cpuIt = cpus.iterator(); 196 Map grps = new HashMap(); 197 while (cpuIt.hasNext()) { 198 Component comp = (Component) cpuIt.next(); 199 int id = (int) comp.getLongProperty(CPU_SYS_ID); 200 LocalityGroup group = getGroup(id); 201 Integer score = (Integer) grps.get(group); 202 if (score != null) { 203 int iscore = score.intValue() + 1; 204 grps.put(group, new Integer(iscore)); 205 } else { 206 grps.put(group, new Integer(1)); 207 } 208 } 209 Iterator groupIt = grps.keySet().iterator(); 210 LocalityGroup centre = null; 211 Integer highest = new Integer(0); 212 while (groupIt.hasNext()) { 213 LocalityGroup cand = (LocalityGroup) groupIt.next(); 214 Integer value = (Integer) grps.get(cand); 215 if (value.intValue() > highest.intValue()) { 216 highest = value; 217 centre = cand; 218 } 219 } 220 return (centre); 221 } 222 223 /** 224 * Return the maximum latency between the groups in this 225 * domain. 226 * 227 */ 228 private int calcMaxLatency() 229 { 230 int max = 0; 231 232 Set groups = getGroups(); 233 Iterator outer = groups.iterator(); 234 while (outer.hasNext()) { 235 Iterator inner = groups.iterator(); 236 LocalityGroup g1 = (LocalityGroup) outer.next(); 237 while (inner.hasNext()) { 238 LocalityGroup g2 = (LocalityGroup) inner.next(); 239 int latency = g1.getLatency(g2); 240 if (latency > max) 241 max = latency; 242 } 243 } 244 return (max); 245 } 246 247 /** 248 * Return the maximum possible latency between all locality 249 * groups in this domain. 250 */ 251 public int getMaxLatency() 252 { 253 return (maxLatency); 254 } 255 256 /** 257 * Return the set of all LocalityGroups for this LocalityDomain. 258 */ 259 public Set getGroups() 260 { 261 Set groups = new HashSet(); 262 groups.add(root); 263 getGroups(root, groups); 264 return (groups); 265 } 266 267 /** 268 * Add all the descendent LocalityGroups for the supplied 269 * group into the supplied set. 270 * 271 * @param group is the group whose descendents are processed. 272 * @param descendents the set to add descendents of group. 273 */ 274 private void getGroups(LocalityGroup group, Set descendents) 275 { 276 Set children = group.getChildren(); 277 278 if (! children.isEmpty()) { 279 Iterator itChild = children.iterator(); 280 while (itChild.hasNext()) { 281 LocalityGroup child = (LocalityGroup) itChild. 282 next(); 283 getGroups(child, descendents); 284 } 285 descendents.addAll(children); 286 } 287 } 288 289 /** 290 * Return the LocalityGroup containing the supplied CPU 291 * id. Search all LocalityGroups starting at the root group. 292 * 293 * @param cpuid is the sys-id of the CPU to search for. 294 */ 295 public LocalityGroup getGroup(int cpuid) 296 { 297 LocalityGroup answer = getGroup(root, cpuid); 298 return (getGroup(root, cpuid)); 299 } 300 301 /** 302 * Return the LocalityGroup containing the supplied CPU 303 * id. Search LocalityGroups starting at the supplied group. 304 * 305 * @param group is the group to start searching from. 306 * @param cpuid is the sys-id of the CPU to search for. 307 */ 308 private LocalityGroup getGroup(LocalityGroup group, int cpuid) 309 { 310 Set children = group.getChildren(); 311 312 if (children.isEmpty()) { 313 int cpus[] = group.getCPUIDs(); 314 315 316 for (int i = 0; i < cpus.length; i++) 317 if (cpus[i] == cpuid) { 318 return (group); 319 } 320 } else { 321 Iterator itGroup = children.iterator(); 322 while (itGroup.hasNext()) { 323 LocalityGroup owner; 324 LocalityGroup child = (LocalityGroup) itGroup. 325 next(); 326 if ((owner = getGroup(child, cpuid)) != null) 327 return (owner); 328 } 329 } 330 return (null); 331 } 332 333 /** 334 * Initialise the LocalityDomain with an lgrp snapshot. 335 * 336 * @param view is the type of snapshot to obtain. 337 */ 338 private native long jl_init(int view) throws Exception; 339 340 /** 341 * Release the lgrp snapshot. 342 */ 343 private native int jl_fini(); 344 345 /** 346 * Find the root LocalityGroup. 347 */ 348 private native LocalityGroup jl_root(); 349 350 } 351