xref: /titanic_41/usr/src/uts/common/sys/lgrp.h (revision 8d4e547db823a866b8f73efc0acdc423e2963caf)
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 2007 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 	kstat_t		*lgrp_kstat;	/* per-lgrp kstats */
257 } lgrp_t;
258 
259 /*
260  * lgroup load average structure
261  */
262 
263 typedef struct lgrp_ld {
264 	lgrp_load_t	lpl_loadavg;	/* load average		*/
265 	uint_t		lpl_ncpu;	/* how many cpus	*/
266 	lgrp_id_t	lpl_lgrpid;	/* which group this lpl part of */
267 	lgrp_t		*lpl_lgrp;	/* ptr to lpl's lgrp */
268 	struct lgrp_ld	*lpl_parent;	/* lpl of parent lgrp */
269 	struct cpu	*lpl_cpus;	/* list of cpus in lpl */
270 					/* NULL for non-leaf lgrps */
271 	uint_t		lpl_nrset;	/* no. of leaf lpls for lgrp */
272 	int		lpl_hint;	/* where to start looking in parent */
273 	hrtime_t	lpl_homed_time;	/* time of last homing to this lpl */
274 	struct lgrp_ld	*lpl_rset[LPL_RSET_ARRYSZ]; /* leaf lpls for lgrp */
275 					/* contains ptr to self for leaf lgrp */
276 } lpl_t;
277 
278 /*
279  * 1 << LGRP_MAX_EFFECT_SHFT ==  lgrp_loadavg_max_effect
280  */
281 #define	LGRP_MAX_EFFECT_SHFT 16
282 
283 /*
284  * Operations handled by lgrp_config()
285  */
286 typedef enum lgrp_config_flag {
287 	LGRP_CONFIG_NOP,
288 	LGRP_CONFIG_CPU_ADD,
289 	LGRP_CONFIG_CPU_DEL,
290 	LGRP_CONFIG_CPU_ONLINE,
291 	LGRP_CONFIG_CPU_OFFLINE,
292 	LGRP_CONFIG_CPUPART_ADD,
293 	LGRP_CONFIG_CPUPART_DEL,
294 	LGRP_CONFIG_MEM_ADD,
295 	LGRP_CONFIG_MEM_DEL,
296 	LGRP_CONFIG_MEM_RENAME,
297 	LGRP_CONFIG_GEN_UPDATE,
298 	LGRP_CONFIG_FLATTEN,
299 	LGRP_CONFIG_LAT_CHANGE_ALL,
300 	LGRP_CONFIG_LAT_CHANGE
301 } lgrp_config_flag_t;
302 
303 /*
304  * Memory allocation policies
305  */
306 typedef enum lgrp_mem_policy {
307 	LGRP_MEM_POLICY_DEFAULT,
308 	LGRP_MEM_POLICY_NEXT,		/* near LWP to next touch */
309 	LGRP_MEM_POLICY_RANDOM_PROC,	/* randomly across process */
310 	LGRP_MEM_POLICY_RANDOM_PSET,	/* randomly across processor set */
311 	LGRP_MEM_POLICY_RANDOM,		/* randomly across all lgroups */
312 	LGRP_MEM_POLICY_ROUNDROBIN,	/* round robin across all lgroups */
313 	LGRP_MEM_POLICY_NEXT_CPU,	/* Near next CPU to touch memory */
314 	LGRP_NUM_MEM_POLICIES
315 } lgrp_mem_policy_t;
316 
317 /*
318  * Search scopes for finding resouces
319  */
320 typedef	enum lgrp_res_ss {
321 	LGRP_SRCH_LOCAL,		/* Search local lgroup only */
322 	LGRP_SRCH_HIER			/* Search entire hierarchy */
323 } lgrp_res_ss_t;
324 
325 /*
326  * Cookie used for lgrp mnode selection
327  */
328 typedef struct lgrp_mnode_cookie {
329 	lgrp_t		*lmc_lgrp;	/* lgrp under consideration */
330 	mnodeset_t	lmc_nodes;	/* nodes not yet tried in lgrp */
331 	int		lmc_cnt;	/* how many nodes in untried set */
332 	mnodeset_t	lmc_tried;	/* nodes already tried */
333 	int		lmc_ntried;	/* how many nodes in tried set */
334 	lgrp_res_ss_t	lmc_scope;	/* consider non-local nodes? */
335 	ushort_t	lmc_rand;	/* a "random" number */
336 } lgrp_mnode_cookie_t;
337 
338 /*
339  * Information needed to implement memory allocation policy
340  */
341 typedef struct lgrp_mem_policy_info {
342 	int	mem_policy;			/* memory allocation policy */
343 	int	mem_reserved;			/* reserved */
344 } lgrp_mem_policy_info_t;
345 
346 /*
347  * Shared memory policy segment
348  */
349 typedef struct lgrp_shm_policy_seg {
350 	u_offset_t		shm_off;	/* offset into shared object */
351 	size_t			shm_size;	/* size of segment */
352 	lgrp_mem_policy_info_t	shm_policy;	/* memory allocation policy */
353 	avl_node_t		shm_tree;	/* AVL tree */
354 } lgrp_shm_policy_seg_t;
355 
356 /*
357  * Shared memory locality info
358  */
359 typedef struct lgrp_shm_locality {
360 	size_t		loc_count;		/* reference count */
361 	avl_tree_t	*loc_tree;		/* policy segment tree */
362 	krwlock_t	loc_lock;		/* protects tree */
363 } lgrp_shm_locality_t;
364 
365 /*
366  * Queries that may be made to determine lgroup memory size
367  */
368 typedef enum {
369 	LGRP_MEM_SIZE_FREE,		/* number of free pages */
370 	LGRP_MEM_SIZE_AVAIL,		/* number of pages in phys_avail */
371 	LGRP_MEM_SIZE_INSTALL		/* number of pages in phys_install */
372 } lgrp_mem_query_t;
373 
374 /*
375  * Argument for the memory copy-rename operation, contains the source and the
376  * destination platform handles.
377  */
378 typedef struct lgrp_config_mem_rename {
379 	lgrp_handle_t lmem_rename_from;
380 	lgrp_handle_t lmem_rename_to;
381 } lgrp_config_mem_rename_t;
382 
383 /* Macro to clear an lgroup bitmap */
384 #define	klgrpset_clear(klgrpset) \
385 	(klgrpset) = (klgrpset_t)0
386 
387 /* Macro to fill an lgroup bitmap */
388 #define	klgrpset_fill(klgrpset) \
389 	(klgrpset) = (klgrpset_t)(-1)
390 
391 /* Macro to add an lgroup to an lgroup bitmap */
392 #define	klgrpset_add(klgrpset, lgrpid) \
393 	(klgrpset) |= ((klgrpset_t)1 << (lgrpid))
394 
395 /* Macro to delete an lgroup from an lgroup bitmap */
396 #define	klgrpset_del(klgrpset, lgrpid) \
397 	(klgrpset) &= ~((klgrpset_t)1 << (lgrpid))
398 
399 /* Macro to copy a klgrpset into another klgrpset */
400 #define	klgrpset_copy(klgrpset_to, klgrpset_from) \
401 	(klgrpset_to) = (klgrpset_from)
402 
403 /* Macro to perform an 'and' operation on a pair of lgroup bitmaps */
404 #define	klgrpset_and(klgrpset_rslt, klgrpset_arg) \
405 	(klgrpset_rslt) &= (klgrpset_arg)
406 
407 /* Macro to perform an 'or' operation on a pair of lgroup bitmaps */
408 #define	klgrpset_or(klgrpset_rslt, klgrpset_arg) \
409 	(klgrpset_rslt) |= (klgrpset_arg)
410 
411 /* Macro to perform a 'diff' operation on a pair of lgroup bitmaps */
412 #define	klgrpset_diff(klgrpset_rslt, klgrpset_arg) \
413 	(klgrpset_rslt) &= ~(klgrpset_arg)
414 
415 /* Macro to check if an lgroup is a member of an lgrpset */
416 #define	klgrpset_ismember(klgrpset, lgrpid) \
417 	((klgrpset) & ((klgrpset_t)1 << (lgrpid)))
418 
419 /* Macro to check if an lgroup bitmap is empty */
420 #define	klgrpset_isempty(klgrpset) \
421 	((klgrpset) == (klgrpset_t)0)
422 
423 /* Macro to check if two lgrpsets intersect */
424 #define	klgrpset_intersects(klgrpset1, klgrpset2) \
425 	((klgrpset1) & (klgrpset2))
426 
427 /* Macro to count the number of members in an lgrpset */
428 #define	klgrpset_nlgrps(klgrpset, count)				\
429 {									\
430 	lgrp_id_t	lgrpid;						\
431 	for (lgrpid = 0, count = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\
432 		if (klgrpset_ismember(klgrpset, lgrpid))		\
433 			count++;					\
434 	}								\
435 }
436 
437 /* Macro to get total memory size (in bytes) of a given set of lgroups */
438 #define	klgrpset_totalsize(klgrpset, size)				\
439 {									\
440 	lgrp_handle_t	hand;						\
441 	lgrp_id_t	lgrpid;						\
442 									\
443 	for (lgrpid = 0, size = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\
444 		if (klgrpset_ismember(klgrpset, lgrpid) &&		\
445 		    lgrp_table[lgrpid])	{				\
446 			hand = lgrp_table[lgrpid]->lgrp_plathand;	\
447 			size += lgrp_plat_mem_size(hand,		\
448 			    LGRP_MEM_SIZE_AVAIL) * PAGESIZE;		\
449 		}							\
450 	}								\
451 }
452 
453 /*
454  * Does this lgroup exist?
455  */
456 #define	LGRP_EXISTS(lgrp)	\
457 	(lgrp != NULL && lgrp->lgrp_id != LGRP_NONE)
458 
459 /*
460  * Initialize an lgrp_mnode_cookie
461  */
462 #define	LGRP_MNODE_COOKIE_INIT(c, lgrp, scope)	\
463 {							\
464 	bzero(&(c), sizeof (lgrp_mnode_cookie_t));	\
465 	(&(c))->lmc_lgrp = lgrp;			\
466 	(&(c))->lmc_nodes = lgrp->lgrp_mnodes;		\
467 	(&(c))->lmc_cnt = lgrp->lgrp_nmnodes;		\
468 	(&(c))->lmc_scope = scope;			\
469 	(&(c))->lmc_rand = (ushort_t)gethrtime_unscaled() >> 4;	\
470 }
471 
472 /*
473  * Upgrade cookie scope from LGRP_SRCH_LOCAL to LGRP_SRCH_HIER.
474  */
475 #define	LGRP_MNODE_COOKIE_UPGRADE(c)	\
476 {							\
477 	ASSERT((&(c))->lmc_scope == LGRP_SRCH_LOCAL);	\
478 	(&(c))->lmc_scope = LGRP_SRCH_HIER;		\
479 }
480 
481 /*
482  * Macro to see whether memory allocation policy can be reapplied
483  */
484 #define	LGRP_MEM_POLICY_REAPPLICABLE(p) \
485 	(p == LGRP_MEM_POLICY_NEXT)
486 
487 /*
488  * Return true if lgrp has CPU resources in the cpupart
489  */
490 #define	LGRP_CPUS_IN_PART(lgrpid, cpupart) \
491 	(cpupart->cp_lgrploads[lgrpid].lpl_ncpu > 0)
492 
493 extern int	lgrp_alloc_max;
494 extern lgrp_t	*lgrp_table[NLGRPS_MAX];	/* indexed by lgrp_id */
495 extern int		nlgrps;		/* number of lgroups in machine */
496 extern int		nlgrpsmax;	/* max number of lgroups on platform */
497 extern lgrp_gen_t	lgrp_gen;	/* generation of lgroup hierarchy */
498 extern int		lgrp_initialized; /* single-CPU initialization done */
499 extern int		lgrp_topo_initialized; /* lgrp topology constructed */
500 extern lgrp_t		*lgrp_root;	/* root lgroup */
501 extern unsigned int	lgrp_topo_levels;
502 extern lpl_t		*lpl_bootstrap;	/* bootstrap lpl for non-active CPUs */
503 
504 
505 /* generic interfaces */
506 
507 /*
508  * lgroup management
509  */
510 int	lgrp_optimizations(void);
511 void	lgrp_init(void);
512 void	lgrp_setup(void);
513 lgrp_t	*lgrp_create(void);
514 void	lgrp_destroy(lgrp_t *);
515 void	lgrp_config(lgrp_config_flag_t, uintptr_t, uintptr_t);
516 lgrp_t	*lgrp_hand_to_lgrp(lgrp_handle_t);
517 
518 /*
519  * lgroup stats
520  */
521 void	lgrp_kstat_create(struct cpu *);
522 void	lgrp_kstat_destroy(struct cpu *);
523 void	lgrp_stat_add(lgrp_id_t, lgrp_stat_t, int64_t);
524 int64_t lgrp_stat_read(lgrp_id_t, lgrp_stat_t);
525 
526 /*
527  * lgroup memory
528  */
529 lgrp_mem_policy_t	lgrp_madv_to_policy(uchar_t, size_t, int);
530 pgcnt_t	lgrp_mem_size(lgrp_id_t, lgrp_mem_query_t);
531 lgrp_t	*lgrp_mem_choose(struct seg *, caddr_t, size_t);
532 int	lgrp_memnode_choose(lgrp_mnode_cookie_t *);
533 lgrp_mem_policy_t	lgrp_mem_policy_default(size_t, int);
534 int	lgrp_mnode_update(klgrpset_t, klgrpset_t *);
535 lgrp_t	*lgrp_pfn_to_lgrp(pfn_t);
536 lgrp_t	*lgrp_phys_to_lgrp(u_longlong_t);	/* used by numat driver */
537 int	lgrp_privm_policy_set(lgrp_mem_policy_t, lgrp_mem_policy_info_t *,
538     size_t);
539 void	lgrp_shm_policy_init(struct anon_map *, vnode_t *);
540 void	lgrp_shm_policy_fini(struct anon_map *, vnode_t *);
541 lgrp_mem_policy_info_t	*lgrp_shm_policy_get(struct anon_map *, ulong_t,
542     vnode_t *, u_offset_t);
543 int	lgrp_shm_policy_set(lgrp_mem_policy_t, struct anon_map *, ulong_t,
544     vnode_t *, u_offset_t, size_t);
545 
546 /*
547  * Used by numat driver
548  */
549 int	lgrp_query_cpu(processorid_t, lgrp_id_t *);
550 int	lgrp_query_load(processorid_t, lgrp_load_t *);
551 
552 /*
553  * lgroup thread placement
554  */
555 lpl_t	*lgrp_affinity_best(kthread_t *, struct cpupart *, lgrp_id_t,
556     boolean_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