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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _LGRP_H 28 #define _LGRP_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /* 33 * locality group definitions for kernel 34 */ 35 36 #include <sys/types.h> 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 #define LGRP_NONE (-1) /* non-existent lgroup ID */ 43 44 45 typedef id_t lgrp_id_t; /* lgroup ID */ 46 47 #if (!defined(_KERNEL) && !defined(_KMEMUSER)) 48 typedef struct lgrp_mem_policy_info { int opaque[2]; } lgrp_mem_policy_info_t; 49 #endif /* !_KERNEL && !_KMEMUSER */ 50 51 #if (defined(_KERNEL) || defined(_KMEMUSER)) 52 #include <sys/cpuvar.h> 53 #include <sys/bitmap.h> 54 #include <sys/vnode.h> 55 #include <vm/anon.h> 56 #include <vm/seg.h> 57 #include <sys/lgrp_user.h> 58 #include <sys/param.h> 59 60 typedef uint32_t lgrp_load_t; /* lgrp_loadavg type */ 61 typedef uintptr_t lgrp_handle_t; /* lgrp handle */ 62 63 #define LGRP_NONE_SUCH LGRP_NONE /* non-existent lgroup ID */ 64 /* null platform handle */ 65 #define LGRP_NULL_HANDLE ((lgrp_handle_t)0xbadbad) 66 #define LGRP_DEFAULT_HANDLE ((lgrp_handle_t)0xbabecafe) /* uma handle */ 67 #define LGRP_ROOTID (0) /* root lgroup ID */ 68 69 /* 70 * Maximum number of lgrps a platform may define. 71 */ 72 73 #define NLGRPS_MAX 64 74 #define NLGRP_LEAVES_MAX 24 75 #define LGRP_LOADAVG_MAX UINT32_MAX 76 #define LPL_RSET_MAX NLGRP_LEAVES_MAX 77 #define LPL_RSET_ARRYSZ (LPL_RSET_MAX + 1) 78 79 /* 80 * The load-average we expect for one cpu-bound thread's worth of load 81 */ 82 #define LGRP_LOADAVG_THREAD_MAX 65516 83 84 /* 85 * The input to the load-average generating function for one cpu-bound thread's 86 * worth of load 87 */ 88 89 #define LGRP_LOADAVG_IN_THREAD_MAX 128 90 91 /* 92 * LPL actions 93 */ 94 95 typedef enum { 96 LPL_INCREMENT, 97 LPL_DECREMENT 98 } lpl_act_t; 99 100 /* 101 * lgroup statistics. Most of these are counters that are updated 102 * dynamically so they are hashed to CPU buckets to reduce cache 103 * interference. The remaining statistics are snapshots of kernel 104 * data, so they aren't stored in the array of counter stats. 105 * 106 * For the hashed stats to make sense, you have to sum all the buckets for 107 * that stat, hence macros are provided to read the stats. 108 */ 109 110 #define LGRP_NUM_CPU_BUCKETS 8 /* must be power of 2 */ 111 #define LGRP_CPU_BUCKET_MASK (LGRP_NUM_CPU_BUCKETS - 1) 112 113 /* 114 * Flags for what to do with lgroup memory policy 115 * Used for heap and stack where policy is extended to new segments added to 116 * the end 117 */ 118 #define LGRP_MP_FLAG_EXTEND_UP 0x1 /* policy should extend up */ 119 #define LGRP_MP_FLAG_EXTEND_DOWN 0x2 /* policy should extend down */ 120 121 #define LGRP_STAT(stats, bucket, whichstat) \ 122 ((stats)->ls_data[bucket][whichstat]) 123 124 /* Return a pointer suitable for an atomic 64-bit op on the bucket */ 125 #define LGRP_STAT_WRITE_PTR(stats, whichstat) \ 126 (&LGRP_STAT(stats, (CPU->cpu_id) & LGRP_CPU_BUCKET_MASK, \ 127 whichstat)) 128 129 /* Sum up all the buckets and return the value in 'val' */ 130 #define LGRP_STAT_READ(stats, whichstat, val) { \ 131 int bkt; \ 132 for (val = 0, bkt = 0; bkt < LGRP_NUM_CPU_BUCKETS; bkt++) \ 133 val += LGRP_STAT(stats, bkt, whichstat); \ 134 } 135 136 /* Reset all buckets for the stat to 0 */ 137 #define LGRP_STAT_RESET(stats, stat) { \ 138 int i; \ 139 for (i = 0; i < LGRP_NUM_CPU_BUCKETS; i++) \ 140 LGRP_STAT(stats, i, stat) = 0; \ 141 } 142 143 /* 144 * Define all of the statistics that are kept for lgrp kstats, 145 * and their corresponding text names. 146 */ 147 148 typedef enum lgrp_stat_types { 149 LGRP_NUM_MIGR, /* # migrations away from this lgrp */ 150 LGRP_NUM_ALLOC_FAIL, /* # times alloc fails for chosen lgrp */ 151 LGRP_PM_SRC_PGS, /* # pages migrated from this lgrp */ 152 LGRP_PM_DEST_PGS, /* # pages migrated to this lgrp */ 153 LGRP_PM_FAIL_ALLOC_PGS, /* # pages failed to migrate to this lgrp */ 154 LGRP_PM_FAIL_LOCK_PGS, /* # pages failed to migrate from this lgrp */ 155 LGRP_PMM_PGS, /* # pages marked to migrate from this lgrp */ 156 LGRP_PMM_FAIL_PGS, /* # pages marked to migrate from this lgrp */ 157 LGRP_NUM_DEFAULT, /* # of times default policy applied */ 158 LGRP_NUM_NEXT, /* # of times next touch policy applied */ 159 LGRP_NUM_RANDOM, /* # of times random policy applied */ 160 LGRP_NUM_RANDOM_PROC, /* # of times random proc policy applied */ 161 LGRP_NUM_RANDOM_PSET, /* # of times random pset policy applied */ 162 LGRP_NUM_ROUNDROBIN, /* # of times round robin policy applied */ 163 LGRP_NUM_COUNTER_STATS, /* always last */ 164 LGRP_CTR_STATS_ALLOC = 16 /* cache-align pad - multiple of 8 */ 165 /* always keep >= LGRP_NUM_COUNTER_STATS */ 166 } lgrp_stat_t; 167 168 typedef enum lgrp_snap_stat_types { 169 LGRP_NUM_CPUS, /* number of CPUs */ 170 LGRP_NUM_PG_FREE, /* # of free pages */ 171 LGRP_NUM_PG_AVAIL, /* # of allocatable physical pages */ 172 LGRP_NUM_PG_INSTALL, /* # of installed physical pages */ 173 LGRP_LOADAVG, /* unscaled load average of this lgrp */ 174 LGRP_LOADAVG_SCALE, /* load unit of one CPU bound thread */ 175 LGRP_NUM_SNAPSHOT_STATS /* always last */ 176 } lgrp_snap_stat_t; 177 178 #define LGRP_KSTAT_NAMES \ 179 static char *lgrp_kstat_names[] = { \ 180 \ 181 /* Counter stats */ \ 182 "lwp migrations", \ 183 "alloc fail", \ 184 "pages migrated from", \ 185 "pages migrated to", \ 186 "pages failed to migrate to", \ 187 "pages failed to migrate from", \ 188 "pages marked for migration", \ 189 "pages failed to mark", \ 190 "default policy", \ 191 "next-touch policy", \ 192 "random policy", \ 193 "span process policy", \ 194 "span psrset policy", \ 195 "round robin policy", \ 196 \ 197 /* Snapshot stats */ \ 198 "cpus", \ 199 "pages free", \ 200 "pages avail", \ 201 "pages installed", \ 202 "load average", \ 203 "loadscale" \ 204 } 205 206 #define LGRP_NUM_STATS ((int)LGRP_NUM_COUNTER_STATS + \ 207 (int)LGRP_NUM_SNAPSHOT_STATS) 208 209 /* 210 * The contents of this structure are opaque and should only be 211 * accessed through the LGRP_STAT macro. 212 */ 213 struct lgrp_stats { 214 int64_t ls_data[LGRP_NUM_CPU_BUCKETS][LGRP_CTR_STATS_ALLOC]; 215 }; 216 217 /* The kernel's version of a bitmap of lgroups */ 218 typedef uint64_t klgrpset_t; 219 220 /* 221 * This really belongs in memnode.h, but it must be defined here to avoid 222 * recursive inclusion problems. Note that memnode.h includes this header. 223 */ 224 typedef uint64_t mnodeset_t; 225 226 /* 227 * lgroup structure 228 * 229 * Visible to generic code and contains the lgroup ID, CPUs in this lgroup, 230 * and a platform handle used to identify this lgroup to the lgroup platform 231 * support code 232 */ 233 typedef struct lgrp { 234 235 lgrp_id_t lgrp_id; /* which lgroup */ 236 int lgrp_latency; 237 lgrp_handle_t lgrp_plathand; /* handle for platform calls */ 238 struct lgrp *lgrp_parent; /* parent lgroup */ 239 uint_t lgrp_reserved1; /* filler */ 240 uint_t lgrp_childcnt; /* number of children lgroups */ 241 klgrpset_t lgrp_children; /* children lgroups */ 242 klgrpset_t lgrp_leaves; /* (direct decendant) leaf lgroups */ 243 244 /* 245 * set of lgroups containing a given type of resource 246 * at this level of locality 247 */ 248 klgrpset_t lgrp_set[LGRP_RSRC_COUNT]; 249 250 mnodeset_t lgrp_mnodes; /* set of memory nodes in this lgroup */ 251 uint_t lgrp_nmnodes; /* number of memnodes */ 252 uint_t lgrp_reserved2; /* filler */ 253 254 struct cpu *lgrp_cpu; /* pointer to a cpu may be null */ 255 uint_t lgrp_cpucnt; /* number of cpus in this lgrp */ 256 uint_t lgrp_chipcnt; 257 struct chip *lgrp_chips; /* pointer to chips in this lgrp */ 258 kstat_t *lgrp_kstat; /* per-lgrp kstats */ 259 } lgrp_t; 260 261 /* 262 * lgroup load average structure 263 */ 264 265 typedef struct lgrp_ld { 266 lgrp_load_t lpl_loadavg; /* load average */ 267 uint_t lpl_ncpu; /* how many cpus */ 268 lgrp_id_t lpl_lgrpid; /* which group this lpl part of */ 269 lgrp_t *lpl_lgrp; /* ptr to lpl's lgrp */ 270 struct lgrp_ld *lpl_parent; /* lpl of parent lgrp */ 271 struct cpu *lpl_cpus; /* list of cpus in lpl */ 272 /* NULL for non-leaf lgrps */ 273 uint_t lpl_nrset; /* no. of leaf lpls for lgrp */ 274 int lpl_hint; /* where to start looking in parent */ 275 hrtime_t lpl_homed_time; /* time of last homing to this lpl */ 276 struct lgrp_ld *lpl_rset[LPL_RSET_ARRYSZ]; /* leaf lpls for lgrp */ 277 /* contains ptr to self for leaf lgrp */ 278 } lpl_t; 279 280 /* 281 * 1 << LGRP_MAX_EFFECT_SHFT == lgrp_loadavg_max_effect 282 */ 283 #define LGRP_MAX_EFFECT_SHFT 16 284 285 /* 286 * Operations handled by lgrp_config() 287 */ 288 typedef enum lgrp_config_flag { 289 LGRP_CONFIG_NOP, 290 LGRP_CONFIG_CPU_ADD, 291 LGRP_CONFIG_CPU_DEL, 292 LGRP_CONFIG_CPU_ONLINE, 293 LGRP_CONFIG_CPU_OFFLINE, 294 LGRP_CONFIG_CPUPART_ADD, 295 LGRP_CONFIG_CPUPART_DEL, 296 LGRP_CONFIG_MEM_ADD, 297 LGRP_CONFIG_MEM_DEL, 298 LGRP_CONFIG_MEM_RENAME, 299 LGRP_CONFIG_GEN_UPDATE, 300 LGRP_CONFIG_FLATTEN, 301 LGRP_CONFIG_LATENCY_CHANGE 302 } lgrp_config_flag_t; 303 304 /* 305 * Memory allocation policies 306 */ 307 typedef enum lgrp_mem_policy { 308 LGRP_MEM_POLICY_DEFAULT, 309 LGRP_MEM_POLICY_NEXT, /* near LWP to next touch */ 310 LGRP_MEM_POLICY_RANDOM_PROC, /* randomly across process */ 311 LGRP_MEM_POLICY_RANDOM_PSET, /* randomly across processor set */ 312 LGRP_MEM_POLICY_RANDOM, /* randomly across all lgroups */ 313 LGRP_MEM_POLICY_ROUNDROBIN, /* round robin across all lgroups */ 314 LGRP_MEM_POLICY_NEXT_CPU, /* Near next CPU to touch memory */ 315 LGRP_NUM_MEM_POLICIES 316 } lgrp_mem_policy_t; 317 318 /* 319 * Search scopes for finding resouces 320 */ 321 typedef enum lgrp_res_ss { 322 LGRP_SRCH_LOCAL, /* Search local lgroup only */ 323 LGRP_SRCH_HIER /* Search entire hierarchy */ 324 } lgrp_res_ss_t; 325 326 /* 327 * Cookie used for lgrp mnode selection 328 */ 329 typedef struct lgrp_mnode_cookie { 330 lgrp_t *lmc_lgrp; /* lgrp under consideration */ 331 mnodeset_t lmc_nodes; /* nodes not yet tried in lgrp */ 332 int lmc_cnt; /* how many nodes in untried set */ 333 mnodeset_t lmc_tried; /* nodes already tried */ 334 int lmc_ntried; /* how many nodes in tried set */ 335 lgrp_res_ss_t lmc_scope; /* consider non-local nodes? */ 336 ushort_t lmc_rand; /* a "random" number */ 337 } lgrp_mnode_cookie_t; 338 339 /* 340 * Information needed to implement memory allocation policy 341 */ 342 typedef struct lgrp_mem_policy_info { 343 int mem_policy; /* memory allocation policy */ 344 int mem_reserved; /* reserved */ 345 } lgrp_mem_policy_info_t; 346 347 /* 348 * Shared memory policy segment 349 */ 350 typedef struct lgrp_shm_policy_seg { 351 u_offset_t shm_off; /* offset into shared object */ 352 size_t shm_size; /* size of segment */ 353 lgrp_mem_policy_info_t shm_policy; /* memory allocation policy */ 354 avl_node_t shm_tree; /* AVL tree */ 355 } lgrp_shm_policy_seg_t; 356 357 /* 358 * Shared memory locality info 359 */ 360 typedef struct lgrp_shm_locality { 361 size_t loc_count; /* reference count */ 362 avl_tree_t *loc_tree; /* policy segment tree */ 363 krwlock_t loc_lock; /* protects tree */ 364 } lgrp_shm_locality_t; 365 366 /* 367 * Queries that may be made to determine lgroup memory size 368 */ 369 typedef enum { 370 LGRP_MEM_SIZE_FREE, /* number of free pages */ 371 LGRP_MEM_SIZE_AVAIL, /* number of pages in phys_avail */ 372 LGRP_MEM_SIZE_INSTALL /* number of pages in phys_install */ 373 } lgrp_mem_query_t; 374 375 /* 376 * Argument for the memory copy-rename operation, contains the source and the 377 * destination platform handles. 378 */ 379 typedef struct lgrp_config_mem_rename { 380 lgrp_handle_t lmem_rename_from; 381 lgrp_handle_t lmem_rename_to; 382 } lgrp_config_mem_rename_t; 383 384 /* Macro to clear an lgroup bitmap */ 385 #define klgrpset_clear(klgrpset) \ 386 (klgrpset) = (klgrpset_t)0 387 388 /* Macro to fill an lgroup bitmap */ 389 #define klgrpset_fill(klgrpset) \ 390 (klgrpset) = (klgrpset_t)(-1) 391 392 /* Macro to add an lgroup to an lgroup bitmap */ 393 #define klgrpset_add(klgrpset, lgrpid) \ 394 (klgrpset) |= ((klgrpset_t)1 << (lgrpid)) 395 396 /* Macro to delete an lgroup from an lgroup bitmap */ 397 #define klgrpset_del(klgrpset, lgrpid) \ 398 (klgrpset) &= ~((klgrpset_t)1 << (lgrpid)) 399 400 /* Macro to copy a klgrpset into another klgrpset */ 401 #define klgrpset_copy(klgrpset_to, klgrpset_from) \ 402 (klgrpset_to) = (klgrpset_from) 403 404 /* Macro to perform an 'and' operation on a pair of lgroup bitmaps */ 405 #define klgrpset_and(klgrpset_rslt, klgrpset_arg) \ 406 (klgrpset_rslt) &= (klgrpset_arg) 407 408 /* Macro to perform an 'or' operation on a pair of lgroup bitmaps */ 409 #define klgrpset_or(klgrpset_rslt, klgrpset_arg) \ 410 (klgrpset_rslt) |= (klgrpset_arg) 411 412 /* Macro to perform a 'diff' operation on a pair of lgroup bitmaps */ 413 #define klgrpset_diff(klgrpset_rslt, klgrpset_arg) \ 414 (klgrpset_rslt) &= ~(klgrpset_arg) 415 416 /* Macro to check if an lgroup is a member of an lgrpset */ 417 #define klgrpset_ismember(klgrpset, lgrpid) \ 418 ((klgrpset) & ((klgrpset_t)1 << (lgrpid))) 419 420 /* Macro to check if an lgroup bitmap is empty */ 421 #define klgrpset_isempty(klgrpset) \ 422 ((klgrpset) == (klgrpset_t)0) 423 424 /* Macro to check if two lgrpsets intersect */ 425 #define klgrpset_intersects(klgrpset1, klgrpset2) \ 426 ((klgrpset1) & (klgrpset2)) 427 428 /* Macro to count the number of members in an lgrpset */ 429 #define klgrpset_nlgrps(klgrpset, count) \ 430 { \ 431 lgrp_id_t lgrpid; \ 432 for (lgrpid = 0, count = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\ 433 if (klgrpset_ismember(klgrpset, lgrpid)) \ 434 count++; \ 435 } \ 436 } 437 438 /* Macro to get total memory size (in bytes) of a given set of lgroups */ 439 #define klgrpset_totalsize(klgrpset, size) \ 440 { \ 441 lgrp_handle_t hand; \ 442 lgrp_id_t lgrpid; \ 443 \ 444 for (lgrpid = 0, size = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\ 445 if (klgrpset_ismember(klgrpset, lgrpid) && \ 446 lgrp_table[lgrpid]) { \ 447 hand = lgrp_table[lgrpid]->lgrp_plathand; \ 448 size += lgrp_plat_mem_size(hand, \ 449 LGRP_MEM_SIZE_AVAIL) * PAGESIZE; \ 450 } \ 451 } \ 452 } 453 454 /* 455 * Does this lgroup exist? 456 */ 457 #define LGRP_EXISTS(lgrp) \ 458 (lgrp != NULL && lgrp->lgrp_id != LGRP_NONE) 459 460 /* 461 * Initialize an lgrp_mnode_cookie 462 */ 463 #define LGRP_MNODE_COOKIE_INIT(c, lgrp, scope) \ 464 { \ 465 bzero(&(c), sizeof (lgrp_mnode_cookie_t)); \ 466 (&(c))->lmc_lgrp = lgrp; \ 467 (&(c))->lmc_nodes = lgrp->lgrp_mnodes; \ 468 (&(c))->lmc_cnt = lgrp->lgrp_nmnodes; \ 469 (&(c))->lmc_scope = scope; \ 470 (&(c))->lmc_rand = (ushort_t)gethrtime_unscaled() >> 4; \ 471 } 472 473 /* 474 * Upgrade cookie scope from LGRP_SRCH_LOCAL to LGRP_SRCH_HIER. 475 */ 476 #define LGRP_MNODE_COOKIE_UPGRADE(c) \ 477 { \ 478 ASSERT((&(c))->lmc_scope == LGRP_SRCH_LOCAL); \ 479 (&(c))->lmc_scope = LGRP_SRCH_HIER; \ 480 } 481 482 /* 483 * Macro to see whether memory allocation policy can be reapplied 484 */ 485 #define LGRP_MEM_POLICY_REAPPLICABLE(p) \ 486 (p == LGRP_MEM_POLICY_NEXT) 487 488 /* 489 * Return true if lgrp has CPU resources in the cpupart 490 */ 491 #define LGRP_CPUS_IN_PART(lgrpid, cpupart) \ 492 (cpupart->cp_lgrploads[lgrpid].lpl_ncpu > 0) 493 494 extern int lgrp_alloc_max; 495 extern lgrp_t *lgrp_table[NLGRPS_MAX]; /* indexed by lgrp_id */ 496 extern int nlgrps; /* number of lgroups in machine */ 497 extern int nlgrpsmax; /* max number of lgroups on platform */ 498 extern lgrp_gen_t lgrp_gen; /* generation of lgroup hierarchy */ 499 extern int lgrp_initialized; /* single-CPU initialization done */ 500 extern int lgrp_topo_initialized; /* lgrp topology constructed */ 501 extern lgrp_t *lgrp_root; /* root lgroup */ 502 extern unsigned int lgrp_topo_levels; 503 extern lpl_t *lpl_bootstrap; /* bootstrap lpl for non-active CPUs */ 504 505 506 /* generic interfaces */ 507 508 /* 509 * lgroup management 510 */ 511 int lgrp_optimizations(void); 512 void lgrp_init(void); 513 void lgrp_setup(void); 514 lgrp_t *lgrp_create(void); 515 void lgrp_destroy(lgrp_t *); 516 void lgrp_config(lgrp_config_flag_t, uintptr_t, uintptr_t); 517 lgrp_t *lgrp_hand_to_lgrp(lgrp_handle_t); 518 519 /* 520 * lgroup stats 521 */ 522 void lgrp_kstat_create(struct cpu *); 523 void lgrp_kstat_destroy(struct cpu *); 524 void lgrp_stat_add(lgrp_id_t, lgrp_stat_t, int64_t); 525 int64_t lgrp_stat_read(lgrp_id_t, lgrp_stat_t); 526 527 /* 528 * lgroup memory 529 */ 530 lgrp_mem_policy_t lgrp_madv_to_policy(uchar_t, size_t, int); 531 pgcnt_t lgrp_mem_size(lgrp_id_t, lgrp_mem_query_t); 532 lgrp_t *lgrp_mem_choose(struct seg *, caddr_t, size_t); 533 int lgrp_memnode_choose(lgrp_mnode_cookie_t *); 534 lgrp_mem_policy_t lgrp_mem_policy_default(size_t, int); 535 int lgrp_mnode_update(klgrpset_t, klgrpset_t *); 536 lgrp_t *lgrp_pfn_to_lgrp(pfn_t); 537 lgrp_t *lgrp_phys_to_lgrp(u_longlong_t); /* used by numat driver */ 538 int lgrp_privm_policy_set(lgrp_mem_policy_t, lgrp_mem_policy_info_t *, 539 size_t); 540 void lgrp_shm_policy_init(struct anon_map *, vnode_t *); 541 void lgrp_shm_policy_fini(struct anon_map *, vnode_t *); 542 lgrp_mem_policy_info_t *lgrp_shm_policy_get(struct anon_map *, ulong_t, 543 vnode_t *, u_offset_t); 544 int lgrp_shm_policy_set(lgrp_mem_policy_t, struct anon_map *, ulong_t, 545 vnode_t *, u_offset_t, size_t); 546 547 /* 548 * Used by numat driver 549 */ 550 int lgrp_query_cpu(processorid_t, lgrp_id_t *); 551 int lgrp_query_load(processorid_t, lgrp_load_t *); 552 553 /* 554 * lgroup thread placement 555 */ 556 lpl_t *lgrp_affinity_best(kthread_t *, struct cpupart *, lgrp_id_t); 557 void lgrp_affinity_init(lgrp_affinity_t **); 558 void lgrp_affinity_free(lgrp_affinity_t **); 559 lpl_t *lgrp_choose(kthread_t *t, struct cpupart *); 560 lgrp_t *lgrp_home_lgrp(void); 561 lgrp_id_t lgrp_home_id(kthread_t *); 562 void lgrp_loadavg(lpl_t *, uint_t, int); 563 void lgrp_move_thread(kthread_t *, lpl_t *, int); 564 565 /* 566 * lgroup topology 567 */ 568 int lgrp_leaf_add(lgrp_t *, lgrp_t **, int, klgrpset_t *); 569 int lgrp_leaf_delete(lgrp_t *, lgrp_t **, int, klgrpset_t *); 570 int lgrp_rsets_empty(klgrpset_t *); 571 int lgrp_rsets_member(klgrpset_t *, lgrp_id_t); 572 int lgrp_topo_flatten(int, lgrp_t **, int, klgrpset_t *); 573 int lgrp_topo_ht_limit(void); 574 int lgrp_topo_ht_limit_default(void); 575 int lgrp_topo_ht_limit_set(int); 576 int lgrp_topo_update(lgrp_t **, int, klgrpset_t *); 577 578 /* 579 * lpl topology 580 */ 581 void lpl_topo_bootstrap(lpl_t *, int); 582 int lpl_topo_flatten(int); 583 int lpl_topo_verify(struct cpupart *); 584 585 586 /* platform interfaces */ 587 void lgrp_plat_init(void); 588 void lgrp_plat_main_init(void); 589 lgrp_t *lgrp_plat_alloc(lgrp_id_t lgrpid); 590 void lgrp_plat_config(lgrp_config_flag_t, uintptr_t); 591 lgrp_handle_t lgrp_plat_cpu_to_hand(processorid_t); 592 lgrp_handle_t lgrp_plat_pfn_to_hand(pfn_t); 593 int lgrp_plat_max_lgrps(void); 594 pgcnt_t lgrp_plat_mem_size(lgrp_handle_t, lgrp_mem_query_t); 595 int lgrp_plat_latency(lgrp_handle_t, lgrp_handle_t); 596 lgrp_handle_t lgrp_plat_root_hand(void); 597 void lgrp_plat_probe(void); 598 599 #endif /* _KERNEL && _KMEMUSER */ 600 601 #ifdef __cplusplus 602 } 603 #endif 604 605 #endif /* _LGRP_H */ 606