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(&current->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(&current->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(&current->mems_allowed_seq);
1613d0407baSopenharmony_ci    current->mems_allowed = nodemask;
1623d0407baSopenharmony_ci    write_seqcount_end(&current->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