1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 3 #ifndef __CPUSET_INTERNAL_H 4 #define __CPUSET_INTERNAL_H 5 6 #include <linux/cgroup.h> 7 #include <linux/cpu.h> 8 #include <linux/cpumask.h> 9 #include <linux/cpuset.h> 10 #include <linux/spinlock.h> 11 #include <linux/union_find.h> 12 13 /* See "Frequency meter" comments, below. */ 14 15 struct fmeter { 16 int cnt; /* unprocessed events count */ 17 int val; /* most recent output value */ 18 time64_t time; /* clock (secs) when val computed */ 19 spinlock_t lock; /* guards read or write of above */ 20 }; 21 22 /* 23 * Invalid partition error code 24 */ 25 enum prs_errcode { 26 PERR_NONE = 0, 27 PERR_INVCPUS, 28 PERR_INVPARENT, 29 PERR_NOTPART, 30 PERR_NOTEXCL, 31 PERR_NOCPUS, 32 PERR_HOTPLUG, 33 PERR_CPUSEMPTY, 34 PERR_HKEEPING, 35 PERR_ACCESS, 36 PERR_REMOTE, 37 }; 38 39 /* bits in struct cpuset flags field */ 40 typedef enum { 41 CS_ONLINE, 42 CS_CPU_EXCLUSIVE, 43 CS_MEM_EXCLUSIVE, 44 CS_MEM_HARDWALL, 45 CS_MEMORY_MIGRATE, 46 CS_SCHED_LOAD_BALANCE, 47 CS_SPREAD_PAGE, 48 CS_SPREAD_SLAB, 49 } cpuset_flagbits_t; 50 51 /* The various types of files and directories in a cpuset file system */ 52 53 typedef enum { 54 FILE_MEMORY_MIGRATE, 55 FILE_CPULIST, 56 FILE_MEMLIST, 57 FILE_EFFECTIVE_CPULIST, 58 FILE_EFFECTIVE_MEMLIST, 59 FILE_SUBPARTS_CPULIST, 60 FILE_EXCLUSIVE_CPULIST, 61 FILE_EFFECTIVE_XCPULIST, 62 FILE_ISOLATED_CPULIST, 63 FILE_CPU_EXCLUSIVE, 64 FILE_MEM_EXCLUSIVE, 65 FILE_MEM_HARDWALL, 66 FILE_SCHED_LOAD_BALANCE, 67 FILE_PARTITION_ROOT, 68 FILE_SCHED_RELAX_DOMAIN_LEVEL, 69 FILE_MEMORY_PRESSURE_ENABLED, 70 FILE_MEMORY_PRESSURE, 71 FILE_SPREAD_PAGE, 72 FILE_SPREAD_SLAB, 73 } cpuset_filetype_t; 74 75 struct cpuset { 76 struct cgroup_subsys_state css; 77 78 unsigned long flags; /* "unsigned long" so bitops work */ 79 80 /* 81 * On default hierarchy: 82 * 83 * The user-configured masks can only be changed by writing to 84 * cpuset.cpus and cpuset.mems, and won't be limited by the 85 * parent masks. 86 * 87 * The effective masks is the real masks that apply to the tasks 88 * in the cpuset. They may be changed if the configured masks are 89 * changed or hotplug happens. 90 * 91 * effective_mask == configured_mask & parent's effective_mask, 92 * and if it ends up empty, it will inherit the parent's mask. 93 * 94 * 95 * On legacy hierarchy: 96 * 97 * The user-configured masks are always the same with effective masks. 98 */ 99 100 /* user-configured CPUs and Memory Nodes allow to tasks */ 101 cpumask_var_t cpus_allowed; 102 nodemask_t mems_allowed; 103 104 /* effective CPUs and Memory Nodes allow to tasks */ 105 cpumask_var_t effective_cpus; 106 nodemask_t effective_mems; 107 108 /* 109 * Exclusive CPUs dedicated to current cgroup (default hierarchy only) 110 * 111 * The effective_cpus of a valid partition root comes solely from its 112 * effective_xcpus and some of the effective_xcpus may be distributed 113 * to sub-partitions below & hence excluded from its effective_cpus. 114 * For a valid partition root, its effective_cpus have no relationship 115 * with cpus_allowed unless its exclusive_cpus isn't set. 116 * 117 * This value will only be set if either exclusive_cpus is set or 118 * when this cpuset becomes a local partition root. 119 */ 120 cpumask_var_t effective_xcpus; 121 122 /* 123 * Exclusive CPUs as requested by the user (default hierarchy only) 124 * 125 * Its value is independent of cpus_allowed and designates the set of 126 * CPUs that can be granted to the current cpuset or its children when 127 * it becomes a valid partition root. The effective set of exclusive 128 * CPUs granted (effective_xcpus) depends on whether those exclusive 129 * CPUs are passed down by its ancestors and not yet taken up by 130 * another sibling partition root along the way. 131 * 132 * If its value isn't set, it defaults to cpus_allowed. 133 */ 134 cpumask_var_t exclusive_cpus; 135 136 /* 137 * This is old Memory Nodes tasks took on. 138 * 139 * - top_cpuset.old_mems_allowed is initialized to mems_allowed. 140 * - A new cpuset's old_mems_allowed is initialized when some 141 * task is moved into it. 142 * - old_mems_allowed is used in cpuset_migrate_mm() when we change 143 * cpuset.mems_allowed and have tasks' nodemask updated, and 144 * then old_mems_allowed is updated to mems_allowed. 145 */ 146 nodemask_t old_mems_allowed; 147 148 struct fmeter fmeter; /* memory_pressure filter */ 149 150 /* 151 * Tasks are being attached to this cpuset. Used to prevent 152 * zeroing cpus/mems_allowed between ->can_attach() and ->attach(). 153 */ 154 int attach_in_progress; 155 156 /* for custom sched domain */ 157 int relax_domain_level; 158 159 /* number of valid local child partitions */ 160 int nr_subparts; 161 162 /* partition root state */ 163 int partition_root_state; 164 165 /* 166 * number of SCHED_DEADLINE tasks attached to this cpuset, so that we 167 * know when to rebuild associated root domain bandwidth information. 168 */ 169 int nr_deadline_tasks; 170 int nr_migrate_dl_tasks; 171 u64 sum_migrate_dl_bw; 172 173 /* Invalid partition error code, not lock protected */ 174 enum prs_errcode prs_err; 175 176 /* Handle for cpuset.cpus.partition */ 177 struct cgroup_file partition_file; 178 179 /* Remote partition silbling list anchored at remote_children */ 180 struct list_head remote_sibling; 181 182 /* Used to merge intersecting subsets for generate_sched_domains */ 183 struct uf_node node; 184 }; 185 186 static inline struct cpuset *css_cs(struct cgroup_subsys_state *css) 187 { 188 return css ? container_of(css, struct cpuset, css) : NULL; 189 } 190 191 /* Retrieve the cpuset for a task */ 192 static inline struct cpuset *task_cs(struct task_struct *task) 193 { 194 return css_cs(task_css(task, cpuset_cgrp_id)); 195 } 196 197 static inline struct cpuset *parent_cs(struct cpuset *cs) 198 { 199 return css_cs(cs->css.parent); 200 } 201 202 /* convenient tests for these bits */ 203 static inline bool is_cpuset_online(struct cpuset *cs) 204 { 205 return test_bit(CS_ONLINE, &cs->flags) && !css_is_dying(&cs->css); 206 } 207 208 static inline int is_cpu_exclusive(const struct cpuset *cs) 209 { 210 return test_bit(CS_CPU_EXCLUSIVE, &cs->flags); 211 } 212 213 static inline int is_mem_exclusive(const struct cpuset *cs) 214 { 215 return test_bit(CS_MEM_EXCLUSIVE, &cs->flags); 216 } 217 218 static inline int is_mem_hardwall(const struct cpuset *cs) 219 { 220 return test_bit(CS_MEM_HARDWALL, &cs->flags); 221 } 222 223 static inline int is_sched_load_balance(const struct cpuset *cs) 224 { 225 return test_bit(CS_SCHED_LOAD_BALANCE, &cs->flags); 226 } 227 228 static inline int is_memory_migrate(const struct cpuset *cs) 229 { 230 return test_bit(CS_MEMORY_MIGRATE, &cs->flags); 231 } 232 233 static inline int is_spread_page(const struct cpuset *cs) 234 { 235 return test_bit(CS_SPREAD_PAGE, &cs->flags); 236 } 237 238 static inline int is_spread_slab(const struct cpuset *cs) 239 { 240 return test_bit(CS_SPREAD_SLAB, &cs->flags); 241 } 242 243 /** 244 * cpuset_for_each_child - traverse online children of a cpuset 245 * @child_cs: loop cursor pointing to the current child 246 * @pos_css: used for iteration 247 * @parent_cs: target cpuset to walk children of 248 * 249 * Walk @child_cs through the online children of @parent_cs. Must be used 250 * with RCU read locked. 251 */ 252 #define cpuset_for_each_child(child_cs, pos_css, parent_cs) \ 253 css_for_each_child((pos_css), &(parent_cs)->css) \ 254 if (is_cpuset_online(((child_cs) = css_cs((pos_css))))) 255 256 /** 257 * cpuset_for_each_descendant_pre - pre-order walk of a cpuset's descendants 258 * @des_cs: loop cursor pointing to the current descendant 259 * @pos_css: used for iteration 260 * @root_cs: target cpuset to walk ancestor of 261 * 262 * Walk @des_cs through the online descendants of @root_cs. Must be used 263 * with RCU read locked. The caller may modify @pos_css by calling 264 * css_rightmost_descendant() to skip subtree. @root_cs is included in the 265 * iteration and the first node to be visited. 266 */ 267 #define cpuset_for_each_descendant_pre(des_cs, pos_css, root_cs) \ 268 css_for_each_descendant_pre((pos_css), &(root_cs)->css) \ 269 if (is_cpuset_online(((des_cs) = css_cs((pos_css))))) 270 271 void rebuild_sched_domains_locked(void); 272 void cpuset_callback_lock_irq(void); 273 void cpuset_callback_unlock_irq(void); 274 void cpuset_update_tasks_cpumask(struct cpuset *cs, struct cpumask *new_cpus); 275 void cpuset_update_tasks_nodemask(struct cpuset *cs); 276 int cpuset_update_flag(cpuset_flagbits_t bit, struct cpuset *cs, int turning_on); 277 ssize_t cpuset_write_resmask(struct kernfs_open_file *of, 278 char *buf, size_t nbytes, loff_t off); 279 int cpuset_common_seq_show(struct seq_file *sf, void *v); 280 281 /* 282 * cpuset-v1.c 283 */ 284 #ifdef CONFIG_CPUSETS_V1 285 extern struct cftype cpuset1_files[]; 286 void fmeter_init(struct fmeter *fmp); 287 void cpuset1_update_task_spread_flags(struct cpuset *cs, 288 struct task_struct *tsk); 289 void cpuset1_update_tasks_flags(struct cpuset *cs); 290 void cpuset1_hotplug_update_tasks(struct cpuset *cs, 291 struct cpumask *new_cpus, nodemask_t *new_mems, 292 bool cpus_updated, bool mems_updated); 293 int cpuset1_validate_change(struct cpuset *cur, struct cpuset *trial); 294 #else 295 static inline void fmeter_init(struct fmeter *fmp) {} 296 static inline void cpuset1_update_task_spread_flags(struct cpuset *cs, 297 struct task_struct *tsk) {} 298 static inline void cpuset1_update_tasks_flags(struct cpuset *cs) {} 299 static inline void cpuset1_hotplug_update_tasks(struct cpuset *cs, 300 struct cpumask *new_cpus, nodemask_t *new_mems, 301 bool cpus_updated, bool mems_updated) {} 302 static inline int cpuset1_validate_change(struct cpuset *cur, 303 struct cpuset *trial) { return 0; } 304 #endif /* CONFIG_CPUSETS_V1 */ 305 306 #endif /* __CPUSET_INTERNAL_H */ 307