⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 domain.c

📁 h内核
💻 C
字号:
/* * arch/ia64/kernel/domain.c * Architecture specific sched-domains builder. * * Copyright (C) 2004 Jesse Barnes * Copyright (C) 2004 Silicon Graphics, Inc. */#include <linux/sched.h>#include <linux/percpu.h>#include <linux/slab.h>#include <linux/cpumask.h>#include <linux/init.h>#include <linux/topology.h>#include <linux/nodemask.h>#define SD_NODES_PER_DOMAIN 6#ifdef CONFIG_NUMA/** * find_next_best_node - find the next node to include in a sched_domain * @node: node whose sched_domain we're building * @used_nodes: nodes already in the sched_domain * * Find the next node to include in a given scheduling domain.  Simply * finds the closest node not already in the @used_nodes map. * * Should use nodemask_t. */static int __devinit find_next_best_node(int node, unsigned long *used_nodes){	int i, n, val, min_val, best_node = 0;	min_val = INT_MAX;	for (i = 0; i < MAX_NUMNODES; i++) {		/* Start at @node */		n = (node + i) % MAX_NUMNODES;		if (!nr_cpus_node(n))			continue;		/* Skip already used nodes */		if (test_bit(n, used_nodes))			continue;		/* Simple min distance search */		val = node_distance(node, n);		if (val < min_val) {			min_val = val;			best_node = n;		}	}	set_bit(best_node, used_nodes);	return best_node;}/** * sched_domain_node_span - get a cpumask for a node's sched_domain * @node: node whose cpumask we're constructing * @size: number of nodes to include in this span * * Given a node, construct a good cpumask for its sched_domain to span.  It * should be one that prevents unnecessary balancing, but also spreads tasks * out optimally. */static cpumask_t __devinit sched_domain_node_span(int node){	int i;	cpumask_t span, nodemask;	DECLARE_BITMAP(used_nodes, MAX_NUMNODES);	cpus_clear(span);	bitmap_zero(used_nodes, MAX_NUMNODES);	nodemask = node_to_cpumask(node);	cpus_or(span, span, nodemask);	set_bit(node, used_nodes);	for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {		int next_node = find_next_best_node(node, used_nodes);		nodemask = node_to_cpumask(next_node);		cpus_or(span, span, nodemask);	}	return span;}#endif/* * At the moment, CONFIG_SCHED_SMT is never defined, but leave it in so we * can switch it on easily if needed. */#ifdef CONFIG_SCHED_SMTstatic DEFINE_PER_CPU(struct sched_domain, cpu_domains);static struct sched_group sched_group_cpus[NR_CPUS];static int __devinit cpu_to_cpu_group(int cpu){	return cpu;}#endifstatic DEFINE_PER_CPU(struct sched_domain, phys_domains);static struct sched_group sched_group_phys[NR_CPUS];static int __devinit cpu_to_phys_group(int cpu){#ifdef CONFIG_SCHED_SMT	return first_cpu(cpu_sibling_map[cpu]);#else	return cpu;#endif}#ifdef CONFIG_NUMA/* * The init_sched_build_groups can't handle what we want to do with node * groups, so roll our own. Now each node has its own list of groups which * gets dynamically allocated. */static DEFINE_PER_CPU(struct sched_domain, node_domains);static struct sched_group *sched_group_nodes[MAX_NUMNODES];static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);static struct sched_group sched_group_allnodes[MAX_NUMNODES];static int __devinit cpu_to_allnodes_group(int cpu){	return cpu_to_node(cpu);}#endif/* * Set up scheduler domains and groups.  Callers must hold the hotplug lock. */void __devinit arch_init_sched_domains(void){	int i;	cpumask_t cpu_default_map;	/*	 * Setup mask for cpus without special case scheduling requirements.	 * For now this just excludes isolated cpus, but could be used to	 * exclude other special cases in the future.	 */	cpus_complement(cpu_default_map, cpu_isolated_map);	cpus_and(cpu_default_map, cpu_default_map, cpu_online_map);	/*	 * Set up domains. Isolated domains just stay on the dummy domain.	 */	for_each_cpu_mask(i, cpu_default_map) {		int group;		struct sched_domain *sd = NULL, *p;		cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));		cpus_and(nodemask, nodemask, cpu_default_map);#ifdef CONFIG_NUMA		if (num_online_cpus()				> SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {			sd = &per_cpu(allnodes_domains, i);			*sd = SD_ALLNODES_INIT;			sd->span = cpu_default_map;			group = cpu_to_allnodes_group(i);			sd->groups = &sched_group_allnodes[group];			p = sd;		} else			p = NULL;		sd = &per_cpu(node_domains, i);		*sd = SD_NODE_INIT;		sd->span = sched_domain_node_span(cpu_to_node(i));		sd->parent = p;		cpus_and(sd->span, sd->span, cpu_default_map);#endif		p = sd;		sd = &per_cpu(phys_domains, i);		group = cpu_to_phys_group(i);		*sd = SD_CPU_INIT;		sd->span = nodemask;		sd->parent = p;		sd->groups = &sched_group_phys[group];#ifdef CONFIG_SCHED_SMT		p = sd;		sd = &per_cpu(cpu_domains, i);		group = cpu_to_cpu_group(i);		*sd = SD_SIBLING_INIT;		sd->span = cpu_sibling_map[i];		cpus_and(sd->span, sd->span, cpu_default_map);		sd->parent = p;		sd->groups = &sched_group_cpus[group];#endif	}#ifdef CONFIG_SCHED_SMT	/* Set up CPU (sibling) groups */	for_each_cpu_mask(i, cpu_default_map) {		cpumask_t this_sibling_map = cpu_sibling_map[i];		cpus_and(this_sibling_map, this_sibling_map, cpu_default_map);		if (i != first_cpu(this_sibling_map))			continue;		init_sched_build_groups(sched_group_cpus, this_sibling_map,						&cpu_to_cpu_group);	}#endif	/* Set up physical groups */	for (i = 0; i < MAX_NUMNODES; i++) {		cpumask_t nodemask = node_to_cpumask(i);		cpus_and(nodemask, nodemask, cpu_default_map);		if (cpus_empty(nodemask))			continue;		init_sched_build_groups(sched_group_phys, nodemask,						&cpu_to_phys_group);	}#ifdef CONFIG_NUMA	init_sched_build_groups(sched_group_allnodes, cpu_default_map,				&cpu_to_allnodes_group);	for (i = 0; i < MAX_NUMNODES; i++) {		/* Set up node groups */		struct sched_group *sg, *prev;		cpumask_t nodemask = node_to_cpumask(i);		cpumask_t domainspan;		cpumask_t covered = CPU_MASK_NONE;		int j;		cpus_and(nodemask, nodemask, cpu_default_map);		if (cpus_empty(nodemask))			continue;		domainspan = sched_domain_node_span(i);		cpus_and(domainspan, domainspan, cpu_default_map);		sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);		sched_group_nodes[i] = sg;		for_each_cpu_mask(j, nodemask) {			struct sched_domain *sd;			sd = &per_cpu(node_domains, j);			sd->groups = sg;			if (sd->groups == NULL) {				/* Turn off balancing if we have no groups */				sd->flags = 0;			}		}		if (!sg) {			printk(KERN_WARNING			"Can not alloc domain group for node %d\n", i);			continue;		}		sg->cpu_power = 0;		sg->cpumask = nodemask;		cpus_or(covered, covered, nodemask);		prev = sg;		for (j = 0; j < MAX_NUMNODES; j++) {			cpumask_t tmp, notcovered;			int n = (i + j) % MAX_NUMNODES;			cpus_complement(notcovered, covered);			cpus_and(tmp, notcovered, cpu_default_map);			cpus_and(tmp, tmp, domainspan);			if (cpus_empty(tmp))				break;			nodemask = node_to_cpumask(n);			cpus_and(tmp, tmp, nodemask);			if (cpus_empty(tmp))				continue;			sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);			if (!sg) {				printk(KERN_WARNING				"Can not alloc domain group for node %d\n", j);				break;			}			sg->cpu_power = 0;			sg->cpumask = tmp;			cpus_or(covered, covered, tmp);			prev->next = sg;			prev = sg;		}		prev->next = sched_group_nodes[i];	}#endif	/* Calculate CPU power for physical packages and nodes */	for_each_cpu_mask(i, cpu_default_map) {		int power;		struct sched_domain *sd;#ifdef CONFIG_SCHED_SMT		sd = &per_cpu(cpu_domains, i);		power = SCHED_LOAD_SCALE;		sd->groups->cpu_power = power;#endif		sd = &per_cpu(phys_domains, i);		power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *				(cpus_weight(sd->groups->cpumask)-1) / 10;		sd->groups->cpu_power = power;#ifdef CONFIG_NUMA		sd = &per_cpu(allnodes_domains, i);		if (sd->groups) {			power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *				(cpus_weight(sd->groups->cpumask)-1) / 10;			sd->groups->cpu_power = power;		}#endif	}#ifdef CONFIG_NUMA	for (i = 0; i < MAX_NUMNODES; i++) {		struct sched_group *sg = sched_group_nodes[i];		int j;		if (sg == NULL)			continue;next_sg:		for_each_cpu_mask(j, sg->cpumask) {			struct sched_domain *sd;			int power;			sd = &per_cpu(phys_domains, j);			if (j != first_cpu(sd->groups->cpumask)) {				/*				 * Only add "power" once for each				 * physical package.				 */				continue;			}			power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *				(cpus_weight(sd->groups->cpumask)-1) / 10;			sg->cpu_power += power;		}		sg = sg->next;		if (sg != sched_group_nodes[i])			goto next_sg;	}#endif	/* Attach the domains */	for_each_online_cpu(i) {		struct sched_domain *sd;#ifdef CONFIG_SCHED_SMT		sd = &per_cpu(cpu_domains, i);#else		sd = &per_cpu(phys_domains, i);#endif		cpu_attach_domain(sd, i);	}}void __devinit arch_destroy_sched_domains(void){#ifdef CONFIG_NUMA	int i;	for (i = 0; i < MAX_NUMNODES; i++) {		struct sched_group *oldsg, *sg = sched_group_nodes[i];		if (sg == NULL)			continue;		sg = sg->next;next_sg:		oldsg = sg;		sg = sg->next;		kfree(oldsg);		if (oldsg != sched_group_nodes[i])			goto next_sg;		sched_group_nodes[i] = NULL;	}#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -