#ifndef _LGRP_H
#define _LGRP_H
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define LGRP_NONE (-1)
#if !defined(_KERNEL) && !defined(_FAKE_KERNEL) && !defined(_KMEMUSER)
typedef struct lgrp_mem_policy_info { int opaque[2]; } lgrp_mem_policy_info_t;
#endif
#if defined(_KERNEL) || defined(_FAKE_KERNEL) || defined(_KMEMUSER)
#include <sys/cpuvar.h>
#include <sys/bitmap.h>
#include <sys/vnode.h>
#include <vm/anon.h>
#include <vm/seg.h>
#include <sys/lgrp_user.h>
#include <sys/param.h>
typedef uint32_t lgrp_load_t;
typedef uintptr_t lgrp_handle_t;
#define LGRP_NONE_SUCH LGRP_NONE
#define LGRP_NULL_HANDLE ((lgrp_handle_t)0xbadbad)
#define LGRP_DEFAULT_HANDLE ((lgrp_handle_t)0xbabecafe)
#define LGRP_ROOTID (0)
#define NLGRPS_MAX 64
#define LGRP_LOADAVG_MAX UINT32_MAX
#define LGRP_LOADAVG_THREAD_MAX 65516
#define LGRP_LOADAVG_IN_THREAD_MAX 128
typedef enum {
LPL_INCREMENT,
LPL_DECREMENT
} lpl_act_t;
#define LGRP_NUM_CPU_BUCKETS 8
#define LGRP_CPU_BUCKET_MASK (LGRP_NUM_CPU_BUCKETS - 1)
#define LGRP_MP_FLAG_EXTEND_UP 0x1
#define LGRP_MP_FLAG_EXTEND_DOWN 0x2
#define LGRP_STAT(stats, bucket, whichstat) \
((stats)->ls_data[bucket][whichstat])
#define LGRP_STAT_WRITE_PTR(stats, whichstat) \
(&LGRP_STAT(stats, (CPU->cpu_id) & LGRP_CPU_BUCKET_MASK, \
whichstat))
#define LGRP_STAT_READ(stats, whichstat, val) { \
int bkt; \
for (val = 0, bkt = 0; bkt < LGRP_NUM_CPU_BUCKETS; bkt++) \
val += LGRP_STAT(stats, bkt, whichstat); \
}
#define LGRP_STAT_RESET(stats, stat) { \
int i; \
for (i = 0; i < LGRP_NUM_CPU_BUCKETS; i++) \
LGRP_STAT(stats, i, stat) = 0; \
}
typedef enum lgrp_stat_types {
LGRP_NUM_MIGR,
LGRP_NUM_ALLOC_FAIL,
LGRP_PM_SRC_PGS,
LGRP_PM_DEST_PGS,
LGRP_PM_FAIL_ALLOC_PGS,
LGRP_PM_FAIL_LOCK_PGS,
LGRP_PMM_PGS,
LGRP_PMM_FAIL_PGS,
LGRP_NUM_DEFAULT,
LGRP_NUM_NEXT,
LGRP_NUM_RANDOM,
LGRP_NUM_RANDOM_PROC,
LGRP_NUM_RANDOM_PSET,
LGRP_NUM_ROUNDROBIN,
LGRP_NUM_NEXT_SEG,
LGRP_NUM_COUNTER_STATS,
LGRP_CTR_STATS_ALLOC = 16
} lgrp_stat_t;
typedef enum lgrp_snap_stat_types {
LGRP_NUM_CPUS,
LGRP_NUM_PG_FREE,
LGRP_NUM_PG_AVAIL,
LGRP_NUM_PG_INSTALL,
LGRP_LOADAVG,
LGRP_LOADAVG_SCALE,
LGRP_NUM_SNAPSHOT_STATS
} lgrp_snap_stat_t;
#define LGRP_KSTAT_NAMES \
static char *lgrp_kstat_names[] = { \
\
\
"lwp migrations", \
"alloc fail", \
"pages migrated from", \
"pages migrated to", \
"pages failed to migrate to", \
"pages failed to migrate from", \
"pages marked for migration", \
"pages failed to mark", \
"default policy", \
"next-touch policy", \
"random policy", \
"span process policy", \
"span psrset policy", \
"round robin policy", \
"next-seg policy", \
\
\
"cpus", \
"pages free", \
"pages avail", \
"pages installed", \
"load average", \
"loadscale" \
}
#define LGRP_NUM_STATS ((int)LGRP_NUM_COUNTER_STATS + \
(int)LGRP_NUM_SNAPSHOT_STATS)
struct lgrp_stats {
int64_t ls_data[LGRP_NUM_CPU_BUCKETS][LGRP_CTR_STATS_ALLOC];
};
typedef uint64_t klgrpset_t;
typedef uint64_t mnodeset_t;
typedef struct lgrp {
lgrp_id_t lgrp_id;
int lgrp_latency;
lgrp_handle_t lgrp_plathand;
struct lgrp *lgrp_parent;
uint_t lgrp_reserved1;
uint_t lgrp_childcnt;
klgrpset_t lgrp_children;
klgrpset_t lgrp_leaves;
klgrpset_t lgrp_set[LGRP_RSRC_COUNT];
mnodeset_t lgrp_mnodes;
uint_t lgrp_nmnodes;
uint_t lgrp_reserved2;
struct cpu *lgrp_cpu;
uint_t lgrp_cpucnt;
kstat_t *lgrp_kstat;
} lgrp_t;
typedef struct lgrp_ld {
lgrp_load_t lpl_loadavg;
uint_t lpl_ncpu;
lgrp_id_t lpl_lgrpid;
lgrp_t *lpl_lgrp;
struct lgrp_ld *lpl_parent;
struct cpu *lpl_cpus;
uint_t lpl_nrset;
hrtime_t lpl_homed_time;
uint_t lpl_rset_sz;
struct lgrp_ld **lpl_rset;
int *lpl_id2rset;
} lpl_t;
#define LGRP_MAX_EFFECT_SHFT 16
typedef enum lgrp_config_flag {
LGRP_CONFIG_NOP,
LGRP_CONFIG_CPU_ADD,
LGRP_CONFIG_CPU_DEL,
LGRP_CONFIG_CPU_ONLINE,
LGRP_CONFIG_CPU_OFFLINE,
LGRP_CONFIG_CPUPART_ADD,
LGRP_CONFIG_CPUPART_DEL,
LGRP_CONFIG_MEM_ADD,
LGRP_CONFIG_MEM_DEL,
LGRP_CONFIG_MEM_RENAME,
LGRP_CONFIG_GEN_UPDATE,
LGRP_CONFIG_FLATTEN,
LGRP_CONFIG_LAT_CHANGE_ALL,
LGRP_CONFIG_LAT_CHANGE
} lgrp_config_flag_t;
typedef enum lgrp_init_stages {
LGRP_INIT_STAGE1,
LGRP_INIT_STAGE2,
LGRP_INIT_STAGE3,
LGRP_INIT_STAGE4,
LGRP_INIT_STAGE5
} lgrp_init_stages_t;
typedef enum lgrp_mem_policy {
LGRP_MEM_POLICY_DEFAULT,
LGRP_MEM_POLICY_NEXT,
LGRP_MEM_POLICY_RANDOM_PROC,
LGRP_MEM_POLICY_RANDOM_PSET,
LGRP_MEM_POLICY_RANDOM,
LGRP_MEM_POLICY_ROUNDROBIN,
LGRP_MEM_POLICY_NEXT_CPU,
LGRP_MEM_POLICY_NEXT_SEG,
LGRP_NUM_MEM_POLICIES
} lgrp_mem_policy_t;
typedef enum lgrp_res_ss {
LGRP_SRCH_LOCAL,
LGRP_SRCH_HIER
} lgrp_res_ss_t;
typedef struct lgrp_mnode_cookie {
lgrp_t *lmc_lgrp;
mnodeset_t lmc_nodes;
int lmc_cnt;
mnodeset_t lmc_tried;
int lmc_ntried;
lgrp_res_ss_t lmc_scope;
ushort_t lmc_rand;
} lgrp_mnode_cookie_t;
typedef struct lgrp_mem_policy_info {
int mem_policy;
lgrp_id_t mem_lgrpid;
} lgrp_mem_policy_info_t;
typedef struct lgrp_shm_policy_seg {
u_offset_t shm_off;
size_t shm_size;
lgrp_mem_policy_info_t shm_policy;
avl_node_t shm_tree;
} lgrp_shm_policy_seg_t;
typedef struct lgrp_shm_locality {
size_t loc_count;
avl_tree_t *loc_tree;
krwlock_t loc_lock;
} lgrp_shm_locality_t;
typedef enum {
LGRP_MEM_SIZE_FREE,
LGRP_MEM_SIZE_AVAIL,
LGRP_MEM_SIZE_INSTALL
} lgrp_mem_query_t;
typedef struct lgrp_config_mem_rename {
lgrp_handle_t lmem_rename_from;
lgrp_handle_t lmem_rename_to;
} lgrp_config_mem_rename_t;
#define klgrpset_clear(klgrpset) \
(klgrpset) = (klgrpset_t)0
#define klgrpset_fill(klgrpset) \
(klgrpset) = (klgrpset_t)(-1)
#define klgrpset_add(klgrpset, lgrpid) \
(klgrpset) |= ((klgrpset_t)1 << (lgrpid))
#define klgrpset_del(klgrpset, lgrpid) \
(klgrpset) &= ~((klgrpset_t)1 << (lgrpid))
#define klgrpset_copy(klgrpset_to, klgrpset_from) \
(klgrpset_to) = (klgrpset_from)
#define klgrpset_and(klgrpset_rslt, klgrpset_arg) \
(klgrpset_rslt) &= (klgrpset_arg)
#define klgrpset_or(klgrpset_rslt, klgrpset_arg) \
(klgrpset_rslt) |= (klgrpset_arg)
#define klgrpset_diff(klgrpset_rslt, klgrpset_arg) \
(klgrpset_rslt) &= ~(klgrpset_arg)
#define klgrpset_ismember(klgrpset, lgrpid) \
((klgrpset) & ((klgrpset_t)1 << (lgrpid)))
#define klgrpset_isempty(klgrpset) \
((klgrpset) == (klgrpset_t)0)
#define klgrpset_intersects(klgrpset1, klgrpset2) \
((klgrpset1) & (klgrpset2))
#define klgrpset_nlgrps(klgrpset, count) \
{ \
lgrp_id_t lgrpid; \
for (lgrpid = 0, count = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\
if (klgrpset_ismember(klgrpset, lgrpid)) \
count++; \
} \
}
#define klgrpset_totalsize(klgrpset, size) \
{ \
lgrp_handle_t hand; \
lgrp_id_t lgrpid; \
\
for (lgrpid = 0, size = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\
if (klgrpset_ismember(klgrpset, lgrpid) && \
lgrp_table[lgrpid]) { \
hand = lgrp_table[lgrpid]->lgrp_plathand; \
size += lgrp_plat_mem_size(hand, \
LGRP_MEM_SIZE_AVAIL) * PAGESIZE; \
} \
} \
}
#define LGRP_EXISTS(lgrp) \
(lgrp != NULL && lgrp->lgrp_id != LGRP_NONE)
#define LGRP_CONTAINS_CPU(lgrp, cpu) \
(klgrpset_ismember(lgrp->lgrp_set[LGRP_RSRC_CPU], \
cpu->cpu_lpl->lpl_lgrpid))
#define LGRP_MNODE_COOKIE_INIT(c, lgrp, scope) \
{ \
bzero(&(c), sizeof (lgrp_mnode_cookie_t)); \
(&(c))->lmc_lgrp = lgrp; \
(&(c))->lmc_nodes = lgrp->lgrp_mnodes; \
(&(c))->lmc_cnt = lgrp->lgrp_nmnodes; \
(&(c))->lmc_scope = scope; \
(&(c))->lmc_rand = (ushort_t)gethrtime_unscaled() >> 4; \
}
#define LGRP_MNODE_COOKIE_UPGRADE(c) \
{ \
ASSERT((&(c))->lmc_scope == LGRP_SRCH_LOCAL); \
(&(c))->lmc_scope = LGRP_SRCH_HIER; \
}
#define LGRP_MEM_POLICY_REAPPLICABLE(p) \
(p == LGRP_MEM_POLICY_NEXT)
#define LGRP_CPUS_IN_PART(lgrpid, cpupart) \
(cpupart->cp_lgrploads[lgrpid].lpl_ncpu > 0)
extern int lgrp_alloc_max;
extern lgrp_t *lgrp_table[NLGRPS_MAX];
extern int nlgrps;
extern int nlgrpsmax;
extern lgrp_gen_t lgrp_gen;
extern int lgrp_initialized;
extern int lgrp_topo_initialized;
extern lgrp_t *lgrp_root;
extern unsigned int lgrp_topo_levels;
extern lpl_t *lpl_bootstrap;
int lgrp_optimizations(void);
void lgrp_init(lgrp_init_stages_t);
lgrp_t *lgrp_create(void);
void lgrp_destroy(lgrp_t *);
void lgrp_config(lgrp_config_flag_t, uintptr_t, uintptr_t);
lgrp_t *lgrp_hand_to_lgrp(lgrp_handle_t);
void lgrp_kstat_create(struct cpu *);
void lgrp_kstat_destroy(struct cpu *);
void lgrp_stat_add(lgrp_id_t, lgrp_stat_t, int64_t);
int64_t lgrp_stat_read(lgrp_id_t, lgrp_stat_t);
lgrp_mem_policy_t lgrp_madv_to_policy(uchar_t, size_t, int);
pgcnt_t lgrp_mem_size(lgrp_id_t, lgrp_mem_query_t);
lgrp_t *lgrp_mem_choose(struct seg *, caddr_t, size_t);
int lgrp_memnode_choose(lgrp_mnode_cookie_t *);
lgrp_mem_policy_t lgrp_mem_policy_default(size_t, int);
int lgrp_mnode_update(klgrpset_t, klgrpset_t *);
lgrp_t *lgrp_pfn_to_lgrp(pfn_t);
lgrp_t *lgrp_phys_to_lgrp(u_longlong_t);
int lgrp_privm_policy_set(lgrp_mem_policy_t, lgrp_mem_policy_info_t *,
size_t);
void lgrp_shm_policy_init(struct anon_map *, vnode_t *);
void lgrp_shm_policy_fini(struct anon_map *, vnode_t *);
lgrp_mem_policy_info_t *lgrp_shm_policy_get(struct anon_map *, ulong_t,
vnode_t *, u_offset_t);
int lgrp_shm_policy_set(lgrp_mem_policy_t, struct anon_map *, ulong_t,
vnode_t *, u_offset_t, size_t);
int lgrp_query_cpu(processorid_t, lgrp_id_t *);
int lgrp_query_load(processorid_t, lgrp_load_t *);
lpl_t *lgrp_affinity_best(kthread_t *, struct cpupart *, lgrp_id_t,
boolean_t);
void lgrp_affinity_init(lgrp_affinity_t **);
void lgrp_affinity_free(lgrp_affinity_t **);
lpl_t *lgrp_choose(kthread_t *t, struct cpupart *);
lgrp_t *lgrp_home_lgrp(void);
lgrp_id_t lgrp_home_id(kthread_t *);
void lgrp_loadavg(lpl_t *, uint_t, int);
void lgrp_move_thread(kthread_t *, lpl_t *, int);
uint64_t lgrp_get_trthr_migrations(void);
void lgrp_update_trthr_migrations(uint64_t);
int lgrp_leaf_add(lgrp_t *, lgrp_t **, int, klgrpset_t *);
int lgrp_leaf_delete(lgrp_t *, lgrp_t **, int, klgrpset_t *);
int lgrp_rsets_empty(klgrpset_t *);
int lgrp_rsets_member(klgrpset_t *, lgrp_id_t);
int lgrp_topo_flatten(int, lgrp_t **, int, klgrpset_t *);
int lgrp_topo_ht_limit(void);
int lgrp_topo_ht_limit_default(void);
int lgrp_topo_ht_limit_set(int);
int lgrp_topo_update(lgrp_t **, int, klgrpset_t *);
void lpl_topo_bootstrap(lpl_t *, int);
int lpl_topo_flatten(int);
int lpl_topo_verify(struct cpupart *);
void lgrp_plat_init(lgrp_init_stages_t);
lgrp_t *lgrp_plat_alloc(lgrp_id_t lgrpid);
void lgrp_plat_config(lgrp_config_flag_t, uintptr_t);
lgrp_handle_t lgrp_plat_cpu_to_hand(processorid_t);
lgrp_handle_t lgrp_plat_pfn_to_hand(pfn_t);
int lgrp_plat_max_lgrps(void);
pgcnt_t lgrp_plat_mem_size(lgrp_handle_t, lgrp_mem_query_t);
int lgrp_plat_latency(lgrp_handle_t, lgrp_handle_t);
lgrp_handle_t lgrp_plat_root_hand(void);
extern uint32_t lgrp_expand_proc_thresh;
extern uint32_t lgrp_expand_proc_diff;
extern pgcnt_t lgrp_mem_free_thresh;
extern uint32_t lgrp_loadavg_tolerance;
extern uint32_t lgrp_loadavg_max_effect;
extern uint32_t lgrp_load_thresh;
extern lgrp_mem_policy_t lgrp_mem_policy_root;
#endif
#ifdef __cplusplus
}
#endif
#endif