kernel/sched/topology.c

Source file repositories/reference/linux-study-clean/kernel/sched/topology.c

File Facts

System
Linux kernel
Corpus path
kernel/sched/topology.c
Extension
.c
Size
90731 bytes
Lines
3505
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct s_data {
	struct sched_domain_shared * __percpu *sds;
	struct sched_domain * __percpu *sd;
	struct root_domain	*rd;
};

enum s_alloc {
	sa_rootdomain,
	sa_sd,
	sa_sd_shared,
	sa_sd_storage,
	sa_none,
};

#ifdef CONFIG_SCHED_CACHE
/* hardware support for cache aware scheduling */
DEFINE_STATIC_KEY_FALSE(sched_cache_present);
/*
 * Indicator of whether cache aware scheduling
 * is active, used by the scheduler.
 */
DEFINE_STATIC_KEY_FALSE(sched_cache_active);
/* user wants cache aware scheduling [0 or 1] */
int sysctl_sched_cache_user = 1;

/*
 * Get the effective LLC size in bytes that @cpu's bottom sched_domain
 * can use. A CPU within a cpuset partition can only use a proportion
 * of the physical LLC, scaled by the ratio of the partition's span
 * weight to the hardware LLC sharing weight. @sd should be the
 * topmost domain with SD_SHARE_LLC.
 *
 * Returns 0 if cacheinfo is not yet populated. This happens during
 * early boot when build_sched_domains() runs before the generic
 * cacheinfo framework has been initialized (cacheinfo_cpu_online()
 * is a device_initcall cpuhp callback). In that case,
 * cacheinfo_cpu_online() will later call sched_update_llc_bytes()
 * to fill in the bottom domain's llc_bytes once the cache attributes
 * are available.
 */
static unsigned long get_effective_llc_bytes(int cpu,
					     struct sched_domain *sd)
{
	struct cacheinfo *ci;
	unsigned int hw_weight;

	ci = get_cpu_cacheinfo_llc(cpu);
	if (!ci)
		return 0;

	hw_weight = cpumask_weight(&ci->shared_cpu_map);
	if (!hw_weight)
		return 0;

	return div_u64((u64)ci->size * sd->span_weight, hw_weight);
}

static bool alloc_sd_llc(const struct cpumask *cpu_map,
			 struct s_data *d)
{
	struct sched_domain *sd, *top_llc, *parent;
	unsigned int *p;
	int i;

	for_each_cpu(i, cpu_map) {
		sd = *per_cpu_ptr(d->sd, i);
		if (!sd)
			goto err;

		p = kcalloc_node(max_lid + 1, sizeof(unsigned int),
				 GFP_KERNEL, cpu_to_node(i));
		if (!p)
			goto err;

		top_llc = sd;
		/*
		 * Find the topmost SD_SHARE_LLC domain.
		 * Not yet attached to the CPU, so per_cpu(sd_llc, i)
		 * can not be used.
		 */
		while ((parent = rcu_dereference_protected(top_llc->parent, true)) &&
		       (parent->flags & SD_SHARE_LLC))
			top_llc = parent;

		if (top_llc->flags & SD_SHARE_LLC) {
			sd->llc_max = max_lid + 1;
			sd->llc_counts = p;
			sd->llc_bytes = get_effective_llc_bytes(i, top_llc);
		} else {
			/* avoid memory leak */

Annotation

Implementation Notes