13d0407baSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 23d0407baSopenharmony_ci#ifndef _LINUX_CPUSET_H 33d0407baSopenharmony_ci#define _LINUX_CPUSET_H 43d0407baSopenharmony_ci/* 53d0407baSopenharmony_ci * cpuset interface 63d0407baSopenharmony_ci * 73d0407baSopenharmony_ci * Copyright (C) 2003 BULL SA 83d0407baSopenharmony_ci * Copyright (C) 2004-2006 Silicon Graphics, Inc. 93d0407baSopenharmony_ci * 103d0407baSopenharmony_ci */ 113d0407baSopenharmony_ci 123d0407baSopenharmony_ci#include <linux/sched.h> 133d0407baSopenharmony_ci#include <linux/sched/topology.h> 143d0407baSopenharmony_ci#include <linux/sched/task.h> 153d0407baSopenharmony_ci#include <linux/cpumask.h> 163d0407baSopenharmony_ci#include <linux/nodemask.h> 173d0407baSopenharmony_ci#include <linux/mm.h> 183d0407baSopenharmony_ci#include <linux/mmu_context.h> 193d0407baSopenharmony_ci#include <linux/jump_label.h> 203d0407baSopenharmony_ci 213d0407baSopenharmony_ci#ifdef CONFIG_CPUSETS 223d0407baSopenharmony_ci 233d0407baSopenharmony_ci/* 243d0407baSopenharmony_ci * Static branch rewrites can happen in an arbitrary order for a given 253d0407baSopenharmony_ci * key. In code paths where we need to loop with read_mems_allowed_begin() and 263d0407baSopenharmony_ci * read_mems_allowed_retry() to get a consistent view of mems_allowed, we need 273d0407baSopenharmony_ci * to ensure that begin() always gets rewritten before retry() in the 283d0407baSopenharmony_ci * disabled -> enabled transition. If not, then if local irqs are disabled 293d0407baSopenharmony_ci * around the loop, we can deadlock since retry() would always be 303d0407baSopenharmony_ci * comparing the latest value of the mems_allowed seqcount against 0 as 313d0407baSopenharmony_ci * begin() still would see cpusets_enabled() as false. The enabled -> disabled 323d0407baSopenharmony_ci * transition should happen in reverse order for the same reasons (want to stop 333d0407baSopenharmony_ci * looking at real value of mems_allowed.sequence in retry() first). 343d0407baSopenharmony_ci */ 353d0407baSopenharmony_ciextern struct static_key_false cpusets_pre_enable_key; 363d0407baSopenharmony_ciextern struct static_key_false cpusets_enabled_key; 373d0407baSopenharmony_cistatic inline bool cpusets_enabled(void) 383d0407baSopenharmony_ci{ 393d0407baSopenharmony_ci return static_branch_unlikely(&cpusets_enabled_key); 403d0407baSopenharmony_ci} 413d0407baSopenharmony_ci 423d0407baSopenharmony_cistatic inline void cpuset_inc(void) 433d0407baSopenharmony_ci{ 443d0407baSopenharmony_ci static_branch_inc_cpuslocked(&cpusets_pre_enable_key); 453d0407baSopenharmony_ci static_branch_inc_cpuslocked(&cpusets_enabled_key); 463d0407baSopenharmony_ci} 473d0407baSopenharmony_ci 483d0407baSopenharmony_cistatic inline void cpuset_dec(void) 493d0407baSopenharmony_ci{ 503d0407baSopenharmony_ci static_branch_dec_cpuslocked(&cpusets_enabled_key); 513d0407baSopenharmony_ci static_branch_dec_cpuslocked(&cpusets_pre_enable_key); 523d0407baSopenharmony_ci} 533d0407baSopenharmony_ci 543d0407baSopenharmony_ciextern int cpuset_init(void); 553d0407baSopenharmony_ciextern void cpuset_init_smp(void); 563d0407baSopenharmony_ciextern void cpuset_force_rebuild(void); 573d0407baSopenharmony_ciextern void cpuset_update_active_cpus(void); 583d0407baSopenharmony_ciextern void cpuset_wait_for_hotplug(void); 593d0407baSopenharmony_ciextern void cpuset_read_lock(void); 603d0407baSopenharmony_ciextern void cpuset_read_unlock(void); 613d0407baSopenharmony_ciextern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); 623d0407baSopenharmony_ciextern void cpuset_cpus_allowed_fallback(struct task_struct *p); 633d0407baSopenharmony_ciextern nodemask_t cpuset_mems_allowed(struct task_struct *p); 643d0407baSopenharmony_ci#define cpuset_current_mems_allowed (current->mems_allowed) 653d0407baSopenharmony_civoid cpuset_init_current_mems_allowed(void); 663d0407baSopenharmony_ciint cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask); 673d0407baSopenharmony_ci 683d0407baSopenharmony_ciextern bool _cpuset_node_allowed(int node, gfp_t gfp_mask); 693d0407baSopenharmony_ci 703d0407baSopenharmony_cistatic inline bool cpuset_node_allowed(int node, gfp_t gfp_mask) 713d0407baSopenharmony_ci{ 723d0407baSopenharmony_ci if (cpusets_enabled()) { 733d0407baSopenharmony_ci return _cpuset_node_allowed(node, gfp_mask); 743d0407baSopenharmony_ci } 753d0407baSopenharmony_ci return true; 763d0407baSopenharmony_ci} 773d0407baSopenharmony_ci 783d0407baSopenharmony_cistatic inline bool __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) 793d0407baSopenharmony_ci{ 803d0407baSopenharmony_ci return _cpuset_node_allowed(zone_to_nid(z), gfp_mask); 813d0407baSopenharmony_ci} 823d0407baSopenharmony_ci 833d0407baSopenharmony_cistatic inline bool cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) 843d0407baSopenharmony_ci{ 853d0407baSopenharmony_ci if (cpusets_enabled()) { 863d0407baSopenharmony_ci return __cpuset_zone_allowed(z, gfp_mask); 873d0407baSopenharmony_ci } 883d0407baSopenharmony_ci return true; 893d0407baSopenharmony_ci} 903d0407baSopenharmony_ci 913d0407baSopenharmony_ciextern int cpuset_mems_allowed_intersects(const struct task_struct *tsk1, const struct task_struct *tsk2); 923d0407baSopenharmony_ci 933d0407baSopenharmony_ci#define cpuset_memory_pressure_bump() \ 943d0407baSopenharmony_ci do { \ 953d0407baSopenharmony_ci if (cpuset_memory_pressure_enabled) \ 963d0407baSopenharmony_ci _cpuset_memory_pressure_bump(); \ 973d0407baSopenharmony_ci } while (0) 983d0407baSopenharmony_ciextern int cpuset_memory_pressure_enabled; 993d0407baSopenharmony_ciextern void _cpuset_memory_pressure_bump(void); 1003d0407baSopenharmony_ci 1013d0407baSopenharmony_ciextern void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task); 1023d0407baSopenharmony_ciextern int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *tsk); 1033d0407baSopenharmony_ci 1043d0407baSopenharmony_ciextern int cpuset_mem_spread_node(void); 1053d0407baSopenharmony_ciextern int cpuset_slab_spread_node(void); 1063d0407baSopenharmony_ci 1073d0407baSopenharmony_cistatic inline int cpuset_do_page_mem_spread(void) 1083d0407baSopenharmony_ci{ 1093d0407baSopenharmony_ci return task_spread_page(current); 1103d0407baSopenharmony_ci} 1113d0407baSopenharmony_ci 1123d0407baSopenharmony_cistatic inline int cpuset_do_slab_mem_spread(void) 1133d0407baSopenharmony_ci{ 1143d0407baSopenharmony_ci return task_spread_slab(current); 1153d0407baSopenharmony_ci} 1163d0407baSopenharmony_ci 1173d0407baSopenharmony_ciextern bool current_cpuset_is_being_rebound(void); 1183d0407baSopenharmony_ci 1193d0407baSopenharmony_ciextern void rebuild_sched_domains(void); 1203d0407baSopenharmony_ci 1213d0407baSopenharmony_ciextern void cpuset_print_current_mems_allowed(void); 1223d0407baSopenharmony_ci 1233d0407baSopenharmony_ci/* 1243d0407baSopenharmony_ci * read_mems_allowed_begin is required when making decisions involving 1253d0407baSopenharmony_ci * mems_allowed such as during page allocation. mems_allowed can be updated in 1263d0407baSopenharmony_ci * parallel and depending on the new value an operation can fail potentially 1273d0407baSopenharmony_ci * causing process failure. A retry loop with read_mems_allowed_begin and 1283d0407baSopenharmony_ci * read_mems_allowed_retry prevents these artificial failures. 1293d0407baSopenharmony_ci */ 1303d0407baSopenharmony_cistatic inline unsigned int read_mems_allowed_begin(void) 1313d0407baSopenharmony_ci{ 1323d0407baSopenharmony_ci if (!static_branch_unlikely(&cpusets_pre_enable_key)) { 1333d0407baSopenharmony_ci return 0; 1343d0407baSopenharmony_ci } 1353d0407baSopenharmony_ci 1363d0407baSopenharmony_ci return read_seqcount_begin(¤t->mems_allowed_seq); 1373d0407baSopenharmony_ci} 1383d0407baSopenharmony_ci 1393d0407baSopenharmony_ci/* 1403d0407baSopenharmony_ci * If this returns true, the operation that took place after 1413d0407baSopenharmony_ci * read_mems_allowed_begin may have failed artificially due to a concurrent 1423d0407baSopenharmony_ci * update of mems_allowed. It is up to the caller to retry the operation if 1433d0407baSopenharmony_ci * appropriate. 1443d0407baSopenharmony_ci */ 1453d0407baSopenharmony_cistatic inline bool read_mems_allowed_retry(unsigned int seq) 1463d0407baSopenharmony_ci{ 1473d0407baSopenharmony_ci if (!static_branch_unlikely(&cpusets_enabled_key)) { 1483d0407baSopenharmony_ci return false; 1493d0407baSopenharmony_ci } 1503d0407baSopenharmony_ci 1513d0407baSopenharmony_ci return read_seqcount_retry(¤t->mems_allowed_seq, seq); 1523d0407baSopenharmony_ci} 1533d0407baSopenharmony_ci 1543d0407baSopenharmony_cistatic inline void set_mems_allowed(nodemask_t nodemask) 1553d0407baSopenharmony_ci{ 1563d0407baSopenharmony_ci unsigned long flags; 1573d0407baSopenharmony_ci 1583d0407baSopenharmony_ci task_lock(current); 1593d0407baSopenharmony_ci local_irq_save(flags); 1603d0407baSopenharmony_ci write_seqcount_begin(¤t->mems_allowed_seq); 1613d0407baSopenharmony_ci current->mems_allowed = nodemask; 1623d0407baSopenharmony_ci write_seqcount_end(¤t->mems_allowed_seq); 1633d0407baSopenharmony_ci local_irq_restore(flags); 1643d0407baSopenharmony_ci task_unlock(current); 1653d0407baSopenharmony_ci} 1663d0407baSopenharmony_ci 1673d0407baSopenharmony_ciextern void cpuset_hotplug_workfn(struct work_struct *work); 1683d0407baSopenharmony_ci 1693d0407baSopenharmony_ci#else /* !CONFIG_CPUSETS */ 1703d0407baSopenharmony_ci 1713d0407baSopenharmony_cistatic inline bool cpusets_enabled(void) 1723d0407baSopenharmony_ci{ 1733d0407baSopenharmony_ci return false; 1743d0407baSopenharmony_ci} 1753d0407baSopenharmony_ci 1763d0407baSopenharmony_cistatic inline int cpuset_init(void) 1773d0407baSopenharmony_ci{ 1783d0407baSopenharmony_ci return 0; 1793d0407baSopenharmony_ci} 1803d0407baSopenharmony_cistatic inline void cpuset_init_smp(void) 1813d0407baSopenharmony_ci{ 1823d0407baSopenharmony_ci} 1833d0407baSopenharmony_ci 1843d0407baSopenharmony_cistatic inline void cpuset_force_rebuild(void) 1853d0407baSopenharmony_ci{ 1863d0407baSopenharmony_ci} 1873d0407baSopenharmony_ci 1883d0407baSopenharmony_cistatic inline void cpuset_update_active_cpus(void) 1893d0407baSopenharmony_ci{ 1903d0407baSopenharmony_ci partition_sched_domains(1, NULL, NULL); 1913d0407baSopenharmony_ci} 1923d0407baSopenharmony_ci 1933d0407baSopenharmony_cistatic inline void cpuset_wait_for_hotplug(void) 1943d0407baSopenharmony_ci{ 1953d0407baSopenharmony_ci} 1963d0407baSopenharmony_ci 1973d0407baSopenharmony_cistatic inline void cpuset_read_lock(void) 1983d0407baSopenharmony_ci{ 1993d0407baSopenharmony_ci} 2003d0407baSopenharmony_cistatic inline void cpuset_read_unlock(void) 2013d0407baSopenharmony_ci{ 2023d0407baSopenharmony_ci} 2033d0407baSopenharmony_ci 2043d0407baSopenharmony_cistatic inline void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask) 2053d0407baSopenharmony_ci{ 2063d0407baSopenharmony_ci cpumask_copy(mask, task_cpu_possible_mask(p)); 2073d0407baSopenharmony_ci} 2083d0407baSopenharmony_ci 2093d0407baSopenharmony_cistatic inline void cpuset_cpus_allowed_fallback(struct task_struct *p) 2103d0407baSopenharmony_ci{ 2113d0407baSopenharmony_ci} 2123d0407baSopenharmony_ci 2133d0407baSopenharmony_cistatic inline nodemask_t cpuset_mems_allowed(struct task_struct *p) 2143d0407baSopenharmony_ci{ 2153d0407baSopenharmony_ci return node_possible_map; 2163d0407baSopenharmony_ci} 2173d0407baSopenharmony_ci 2183d0407baSopenharmony_ci#define cpuset_current_mems_allowed (node_states[N_MEMORY]) 2193d0407baSopenharmony_cistatic inline void cpuset_init_current_mems_allowed(void) 2203d0407baSopenharmony_ci{ 2213d0407baSopenharmony_ci} 2223d0407baSopenharmony_ci 2233d0407baSopenharmony_cistatic inline int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask) 2243d0407baSopenharmony_ci{ 2253d0407baSopenharmony_ci return 1; 2263d0407baSopenharmony_ci} 2273d0407baSopenharmony_ci 2283d0407baSopenharmony_cistatic inline bool cpuset_node_allowed(int node, gfp_t gfp_mask) 2293d0407baSopenharmony_ci{ 2303d0407baSopenharmony_ci return true; 2313d0407baSopenharmony_ci} 2323d0407baSopenharmony_ci 2333d0407baSopenharmony_cistatic inline bool __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) 2343d0407baSopenharmony_ci{ 2353d0407baSopenharmony_ci return true; 2363d0407baSopenharmony_ci} 2373d0407baSopenharmony_ci 2383d0407baSopenharmony_cistatic inline bool cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) 2393d0407baSopenharmony_ci{ 2403d0407baSopenharmony_ci return true; 2413d0407baSopenharmony_ci} 2423d0407baSopenharmony_ci 2433d0407baSopenharmony_cistatic inline int cpuset_mems_allowed_intersects(const struct task_struct *tsk1, const struct task_struct *tsk2) 2443d0407baSopenharmony_ci{ 2453d0407baSopenharmony_ci return 1; 2463d0407baSopenharmony_ci} 2473d0407baSopenharmony_ci 2483d0407baSopenharmony_cistatic inline void cpuset_memory_pressure_bump(void) 2493d0407baSopenharmony_ci{ 2503d0407baSopenharmony_ci} 2513d0407baSopenharmony_ci 2523d0407baSopenharmony_cistatic inline void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task) 2533d0407baSopenharmony_ci{ 2543d0407baSopenharmony_ci} 2553d0407baSopenharmony_ci 2563d0407baSopenharmony_cistatic inline int cpuset_mem_spread_node(void) 2573d0407baSopenharmony_ci{ 2583d0407baSopenharmony_ci return 0; 2593d0407baSopenharmony_ci} 2603d0407baSopenharmony_ci 2613d0407baSopenharmony_cistatic inline int cpuset_slab_spread_node(void) 2623d0407baSopenharmony_ci{ 2633d0407baSopenharmony_ci return 0; 2643d0407baSopenharmony_ci} 2653d0407baSopenharmony_ci 2663d0407baSopenharmony_cistatic inline int cpuset_do_page_mem_spread(void) 2673d0407baSopenharmony_ci{ 2683d0407baSopenharmony_ci return 0; 2693d0407baSopenharmony_ci} 2703d0407baSopenharmony_ci 2713d0407baSopenharmony_cistatic inline int cpuset_do_slab_mem_spread(void) 2723d0407baSopenharmony_ci{ 2733d0407baSopenharmony_ci return 0; 2743d0407baSopenharmony_ci} 2753d0407baSopenharmony_ci 2763d0407baSopenharmony_cistatic inline bool current_cpuset_is_being_rebound(void) 2773d0407baSopenharmony_ci{ 2783d0407baSopenharmony_ci return false; 2793d0407baSopenharmony_ci} 2803d0407baSopenharmony_ci 2813d0407baSopenharmony_cistatic inline void rebuild_sched_domains(void) 2823d0407baSopenharmony_ci{ 2833d0407baSopenharmony_ci partition_sched_domains(1, NULL, NULL); 2843d0407baSopenharmony_ci} 2853d0407baSopenharmony_ci 2863d0407baSopenharmony_cistatic inline void cpuset_print_current_mems_allowed(void) 2873d0407baSopenharmony_ci{ 2883d0407baSopenharmony_ci} 2893d0407baSopenharmony_ci 2903d0407baSopenharmony_cistatic inline void set_mems_allowed(nodemask_t nodemask) 2913d0407baSopenharmony_ci{ 2923d0407baSopenharmony_ci} 2933d0407baSopenharmony_ci 2943d0407baSopenharmony_cistatic inline unsigned int read_mems_allowed_begin(void) 2953d0407baSopenharmony_ci{ 2963d0407baSopenharmony_ci return 0; 2973d0407baSopenharmony_ci} 2983d0407baSopenharmony_ci 2993d0407baSopenharmony_cistatic inline bool read_mems_allowed_retry(unsigned int seq) 3003d0407baSopenharmony_ci{ 3013d0407baSopenharmony_ci return false; 3023d0407baSopenharmony_ci} 3033d0407baSopenharmony_ci 3043d0407baSopenharmony_cistatic inline void cpuset_hotplug_workfn(struct work_struct *work) 3053d0407baSopenharmony_ci{ 3063d0407baSopenharmony_ci} 3073d0407baSopenharmony_ci 3083d0407baSopenharmony_ci#endif /* !CONFIG_CPUSETS */ 3093d0407baSopenharmony_ci 3103d0407baSopenharmony_ci#endif /* _LINUX_CPUSET_H */ 311