xref: /openbmc/linux/lib/cpumask.c (revision 2d3854a37e8b767a51aba38ed6d22817b0631e33)
1ccb46000SAndrew Morton #include <linux/kernel.h>
2ccb46000SAndrew Morton #include <linux/bitops.h>
3ccb46000SAndrew Morton #include <linux/cpumask.h>
4ccb46000SAndrew Morton #include <linux/module.h>
5*2d3854a3SRusty Russell #include <linux/bootmem.h>
6ccb46000SAndrew Morton 
7ccb46000SAndrew Morton int __first_cpu(const cpumask_t *srcp)
8ccb46000SAndrew Morton {
9ccb46000SAndrew Morton 	return min_t(int, NR_CPUS, find_first_bit(srcp->bits, NR_CPUS));
10ccb46000SAndrew Morton }
11ccb46000SAndrew Morton EXPORT_SYMBOL(__first_cpu);
12ccb46000SAndrew Morton 
133d18bd74SAndrew Morton int __next_cpu(int n, const cpumask_t *srcp)
143d18bd74SAndrew Morton {
153d18bd74SAndrew Morton 	return min_t(int, NR_CPUS, find_next_bit(srcp->bits, NR_CPUS, n+1));
163d18bd74SAndrew Morton }
173d18bd74SAndrew Morton EXPORT_SYMBOL(__next_cpu);
1886302820SAndrew Morton 
1941df0d61SMike Travis #if NR_CPUS > 64
2041df0d61SMike Travis int __next_cpu_nr(int n, const cpumask_t *srcp)
2141df0d61SMike Travis {
2241df0d61SMike Travis 	return min_t(int, nr_cpu_ids,
2341df0d61SMike Travis 				find_next_bit(srcp->bits, nr_cpu_ids, n+1));
2441df0d61SMike Travis }
2541df0d61SMike Travis EXPORT_SYMBOL(__next_cpu_nr);
2641df0d61SMike Travis #endif
2741df0d61SMike Travis 
2896a9b4d3SAndrew Morton int __any_online_cpu(const cpumask_t *mask)
2996a9b4d3SAndrew Morton {
3096a9b4d3SAndrew Morton 	int cpu;
3196a9b4d3SAndrew Morton 
3296a9b4d3SAndrew Morton 	for_each_cpu_mask(cpu, *mask) {
3396a9b4d3SAndrew Morton 		if (cpu_online(cpu))
3496a9b4d3SAndrew Morton 			break;
3596a9b4d3SAndrew Morton 	}
3696a9b4d3SAndrew Morton 	return cpu;
3796a9b4d3SAndrew Morton }
3896a9b4d3SAndrew Morton EXPORT_SYMBOL(__any_online_cpu);
39*2d3854a3SRusty Russell 
40*2d3854a3SRusty Russell /**
41*2d3854a3SRusty Russell  * cpumask_next_and - get the next cpu in *src1p & *src2p
42*2d3854a3SRusty Russell  * @n: the cpu prior to the place to search (ie. return will be > @n)
43*2d3854a3SRusty Russell  * @src1p: the first cpumask pointer
44*2d3854a3SRusty Russell  * @src2p: the second cpumask pointer
45*2d3854a3SRusty Russell  *
46*2d3854a3SRusty Russell  * Returns >= nr_cpu_ids if no further cpus set in both.
47*2d3854a3SRusty Russell  */
48*2d3854a3SRusty Russell int cpumask_next_and(int n, const struct cpumask *src1p,
49*2d3854a3SRusty Russell 		     const struct cpumask *src2p)
50*2d3854a3SRusty Russell {
51*2d3854a3SRusty Russell 	while ((n = cpumask_next(n, src1p)) < nr_cpu_ids)
52*2d3854a3SRusty Russell 		if (cpumask_test_cpu(n, src2p))
53*2d3854a3SRusty Russell 			break;
54*2d3854a3SRusty Russell 	return n;
55*2d3854a3SRusty Russell }
56*2d3854a3SRusty Russell EXPORT_SYMBOL(cpumask_next_and);
57*2d3854a3SRusty Russell 
58*2d3854a3SRusty Russell /**
59*2d3854a3SRusty Russell  * cpumask_any_but - return a "random" in a cpumask, but not this one.
60*2d3854a3SRusty Russell  * @mask: the cpumask to search
61*2d3854a3SRusty Russell  * @cpu: the cpu to ignore.
62*2d3854a3SRusty Russell  *
63*2d3854a3SRusty Russell  * Often used to find any cpu but smp_processor_id() in a mask.
64*2d3854a3SRusty Russell  * Returns >= nr_cpu_ids if no cpus set.
65*2d3854a3SRusty Russell  */
66*2d3854a3SRusty Russell int cpumask_any_but(const struct cpumask *mask, unsigned int cpu)
67*2d3854a3SRusty Russell {
68*2d3854a3SRusty Russell 	unsigned int i;
69*2d3854a3SRusty Russell 
70*2d3854a3SRusty Russell 	for_each_cpu(i, mask)
71*2d3854a3SRusty Russell 		if (i != cpu)
72*2d3854a3SRusty Russell 			break;
73*2d3854a3SRusty Russell 	return i;
74*2d3854a3SRusty Russell }
75*2d3854a3SRusty Russell 
76*2d3854a3SRusty Russell /* These are not inline because of header tangles. */
77*2d3854a3SRusty Russell #ifdef CONFIG_CPUMASK_OFFSTACK
78*2d3854a3SRusty Russell bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
79*2d3854a3SRusty Russell {
80*2d3854a3SRusty Russell 	if (likely(slab_is_available()))
81*2d3854a3SRusty Russell 		*mask = kmalloc(cpumask_size(), flags);
82*2d3854a3SRusty Russell 	else {
83*2d3854a3SRusty Russell #ifdef CONFIG_DEBUG_PER_CPU_MAPS
84*2d3854a3SRusty Russell 		printk(KERN_ERR
85*2d3854a3SRusty Russell 			"=> alloc_cpumask_var: kmalloc not available!\n");
86*2d3854a3SRusty Russell 		dump_stack();
87*2d3854a3SRusty Russell #endif
88*2d3854a3SRusty Russell 		*mask = NULL;
89*2d3854a3SRusty Russell 	}
90*2d3854a3SRusty Russell #ifdef CONFIG_DEBUG_PER_CPU_MAPS
91*2d3854a3SRusty Russell 	if (!*mask) {
92*2d3854a3SRusty Russell 		printk(KERN_ERR "=> alloc_cpumask_var: failed!\n");
93*2d3854a3SRusty Russell 		dump_stack();
94*2d3854a3SRusty Russell 	}
95*2d3854a3SRusty Russell #endif
96*2d3854a3SRusty Russell 	return *mask != NULL;
97*2d3854a3SRusty Russell }
98*2d3854a3SRusty Russell EXPORT_SYMBOL(alloc_cpumask_var);
99*2d3854a3SRusty Russell 
100*2d3854a3SRusty Russell void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask)
101*2d3854a3SRusty Russell {
102*2d3854a3SRusty Russell 	*mask = alloc_bootmem(cpumask_size());
103*2d3854a3SRusty Russell }
104*2d3854a3SRusty Russell 
105*2d3854a3SRusty Russell void free_cpumask_var(cpumask_var_t mask)
106*2d3854a3SRusty Russell {
107*2d3854a3SRusty Russell 	kfree(mask);
108*2d3854a3SRusty Russell }
109*2d3854a3SRusty Russell EXPORT_SYMBOL(free_cpumask_var);
110*2d3854a3SRusty Russell #endif
111