sched/topology: Define and assign sched_domain flag metadata

commit b6e862f386 upstream.

------------------------------------------------------------------------

There are some expectations regarding how sched domain flags should be laid
out, but none of them are checked or asserted in
sched_domain_debug_one(). After staring at said flags for a while, I've
come to realize there's two repeating patterns:

- Shared with children: those flags are set from the base CPU domain
  upwards. Any domain that has it set will have it set in its children. It
  hints at "some property holds true / some behaviour is enabled until this
  level".

- Shared with parents: those flags are set from the topmost domain
  downwards. Any domain that has it set will have it set in its parents. It
  hints at "some property isn't visible / some behaviour is disabled until
  this level".

There are two outliers that (currently) do not map to either of these:

o SD_PREFER_SIBLING, which is cleared below levels with
  SD_ASYM_CPUCAPACITY. The change was introduced by commit:

    9c63e84db2 ("sched/core: Disable SD_PREFER_SIBLING on asymmetric CPU capacity domains")

  as it could break misfit migration on some systems. In light of this, we
  might want to change it back to make it fit one of the two categories and
  fix the issue another way.

o SD_ASYM_CPUCAPACITY, which gets set on a single level and isn't
  propagated up nor down. From a topology description point of view, it
  really wants to be SDF_SHARED_PARENT; this will be rectified in a later
  patch.

Tweak the sched_domain flag declaration to assign each flag an expected
layout, and include the rationale for each flag "meta type" assignment as a
comment. Consolidate the flag metadata into an array; the index of a flag's
metadata can easily be found with log2(flag), IOW __ffs(flag).

Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: https://lore.kernel.org/r/20200817113003.20802-5-valentin.schneider@arm.com
Signed-off-by: Xue Sinian <tangyuan911@yeah.net>
This commit is contained in:
Valentin Schneider 2020-08-17 12:29:50 +01:00 committed by XueSinian
parent d400332b6c
commit af30444737
2 changed files with 134 additions and 28 deletions

View File

@ -7,29 +7,124 @@
# error "Incorrect import of SD flags definitions" # error "Incorrect import of SD flags definitions"
#endif #endif
/* Balance when about to become idle */ /*
SD_FLAG(SD_BALANCE_NEWIDLE) * Expected flag uses
/* Balance on exec */ *
SD_FLAG(SD_BALANCE_EXEC) * SHARED_CHILD: These flags are meant to be set from the base domain upwards.
/* Balance on fork, clone */ * If a domain has this flag set, all of its children should have it set. This
SD_FLAG(SD_BALANCE_FORK) * is usually because the flag describes some shared resource (all CPUs in that
/* Balance on wakeup */ * domain share the same resource), or because they are tied to a scheduling
SD_FLAG(SD_BALANCE_WAKE) * behaviour that we want to disable at some point in the hierarchy for
/* Wake task to waking CPU */ * scalability reasons.
SD_FLAG(SD_WAKE_AFFINE) *
/* Domain members have different CPU capacities */ * In those cases it doesn't make sense to have the flag set for a domain but
SD_FLAG(SD_ASYM_CPUCAPACITY) * not have it in (some of) its children: sched domains ALWAYS span their child
/* Domain members share CPU capacity */ * domains, so operations done with parent domains will cover CPUs in the lower
SD_FLAG(SD_SHARE_CPUCAPACITY) * child domains.
/* Domain members share CPU pkg resources */ *
SD_FLAG(SD_SHARE_PKG_RESOURCES) *
/* Only a single load balancing instance */ * SHARED_PARENT: These flags are meant to be set from the highest domain
SD_FLAG(SD_SERIALIZE) * downwards. If a domain has this flag set, all of its parents should have it
/* Place busy groups earlier in the domain */ * set. This is usually for topology properties that start to appear above a
SD_FLAG(SD_ASYM_PACKING) * certain level (e.g. domain starts spanning CPUs outside of the base CPU's
/* Prefer to place tasks in a sibling domain */ * socket).
SD_FLAG(SD_PREFER_SIBLING) */
/* sched_domains of this level overlap */ #define SDF_SHARED_CHILD 0x1
SD_FLAG(SD_OVERLAP) #define SDF_SHARED_PARENT 0x2
/* cross-node balancing */
SD_FLAG(SD_NUMA) /*
* Balance when about to become idle
*
* SHARED_CHILD: Set from the base domain up to cpuset.sched_relax_domain_level.
*/
SD_FLAG(SD_BALANCE_NEWIDLE, SDF_SHARED_CHILD)
/*
* Balance on exec
*
* SHARED_CHILD: Set from the base domain up to the NUMA reclaim level.
*/
SD_FLAG(SD_BALANCE_EXEC, SDF_SHARED_CHILD)
/*
* Balance on fork, clone
*
* SHARED_CHILD: Set from the base domain up to the NUMA reclaim level.
*/
SD_FLAG(SD_BALANCE_FORK, SDF_SHARED_CHILD)
/*
* Balance on wakeup
*
* SHARED_CHILD: Set from the base domain up to cpuset.sched_relax_domain_level.
*/
SD_FLAG(SD_BALANCE_WAKE, SDF_SHARED_CHILD)
/*
* Consider waking task on waking CPU.
*
* SHARED_CHILD: Set from the base domain up to the NUMA reclaim level.
*/
SD_FLAG(SD_WAKE_AFFINE, SDF_SHARED_CHILD)
/*
* Domain members have different CPU capacities
*/
SD_FLAG(SD_ASYM_CPUCAPACITY, 0)
/*
* Domain members share CPU capacity (i.e. SMT)
*
* SHARED_CHILD: Set from the base domain up until spanned CPUs no longer share
* CPU capacity.
*/
SD_FLAG(SD_SHARE_CPUCAPACITY, SDF_SHARED_CHILD)
/*
* Domain members share CPU package resources (i.e. caches)
*
* SHARED_CHILD: Set from the base domain up until spanned CPUs no longer share
* the same cache(s).
*/
SD_FLAG(SD_SHARE_PKG_RESOURCES, SDF_SHARED_CHILD)
/*
* Only a single load balancing instance
*
* SHARED_PARENT: Set for all NUMA levels above NODE. Could be set from a
* different level upwards, but it doesn't change that if a domain has this flag
* set, then all of its parents need to have it too (otherwise the serialization
* doesn't make sense).
*/
SD_FLAG(SD_SERIALIZE, SDF_SHARED_PARENT)
/*
* Place busy tasks earlier in the domain
*
* SHARED_CHILD: Usually set on the SMT level. Technically could be set further
* up, but currently assumed to be set from the base domain upwards (see
* update_top_cache_domain()).
*/
SD_FLAG(SD_ASYM_PACKING, SDF_SHARED_CHILD)
/*
* Prefer to place tasks in a sibling domain
*
* Set up until domains start spanning NUMA nodes. Close to being a SHARED_CHILD
* flag, but cleared below domains with SD_ASYM_CPUCAPACITY.
*/
SD_FLAG(SD_PREFER_SIBLING, 0)
/*
* sched_groups of this level overlap
*
* SHARED_PARENT: Set for all NUMA levels above NODE.
*/
SD_FLAG(SD_OVERLAP, SDF_SHARED_PARENT)
/*
* Cross-node balancing
*
* SHARED_PARENT: Set for all NUMA levels above NODE.
*/
SD_FLAG(SD_NUMA, SDF_SHARED_PARENT)

View File

@ -12,19 +12,30 @@
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Generate SD flag indexes */ /* Generate SD flag indexes */
#define SD_FLAG(name) __##name, #define SD_FLAG(name, mflags) __##name,
enum { enum {
#include <linux/sched/sd_flags.h> #include <linux/sched/sd_flags.h>
__SD_FLAG_CNT, __SD_FLAG_CNT,
}; };
#undef SD_FLAG #undef SD_FLAG
/* Generate SD flag bits */ /* Generate SD flag bits */
#define SD_FLAG(name) name = 1 << __##name, #define SD_FLAG(name, mflags) name = 1 << __##name,
enum { enum {
#include <linux/sched/sd_flags.h> #include <linux/sched/sd_flags.h>
}; };
#undef SD_FLAG #undef SD_FLAG
#ifdef CONFIG_SCHED_DEBUG
#define SD_FLAG(_name, mflags) [__##_name] = { .meta_flags = mflags, .name = #_name },
static const struct {
unsigned int meta_flags;
char *name;
} sd_flag_debug[] = {
#include <linux/sched/sd_flags.h>
};
#undef SD_FLAG
#endif
#ifdef CONFIG_SCHED_SMT #ifdef CONFIG_SCHED_SMT
static inline int cpu_smt_flags(void) static inline int cpu_smt_flags(void)
{ {