xref: /linux-6.15/include/linux/cpumask_types.h (revision eb4faa36)
1*eb4faa36SYury Norov /* SPDX-License-Identifier: GPL-2.0 */
2*eb4faa36SYury Norov #ifndef __LINUX_CPUMASK_TYPES_H
3*eb4faa36SYury Norov #define __LINUX_CPUMASK_TYPES_H
4*eb4faa36SYury Norov 
5*eb4faa36SYury Norov #include <linux/bitops.h>
6*eb4faa36SYury Norov #include <linux/threads.h>
7*eb4faa36SYury Norov 
8*eb4faa36SYury Norov /* Don't assign or return these: may not be this big! */
9*eb4faa36SYury Norov typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
10*eb4faa36SYury Norov 
11*eb4faa36SYury Norov /**
12*eb4faa36SYury Norov  * cpumask_bits - get the bits in a cpumask
13*eb4faa36SYury Norov  * @maskp: the struct cpumask *
14*eb4faa36SYury Norov  *
15*eb4faa36SYury Norov  * You should only assume nr_cpu_ids bits of this mask are valid.  This is
16*eb4faa36SYury Norov  * a macro so it's const-correct.
17*eb4faa36SYury Norov  */
18*eb4faa36SYury Norov #define cpumask_bits(maskp) ((maskp)->bits)
19*eb4faa36SYury Norov 
20*eb4faa36SYury Norov /*
21*eb4faa36SYury Norov  * cpumask_var_t: struct cpumask for stack usage.
22*eb4faa36SYury Norov  *
23*eb4faa36SYury Norov  * Oh, the wicked games we play!  In order to make kernel coding a
24*eb4faa36SYury Norov  * little more difficult, we typedef cpumask_var_t to an array or a
25*eb4faa36SYury Norov  * pointer: doing &mask on an array is a noop, so it still works.
26*eb4faa36SYury Norov  *
27*eb4faa36SYury Norov  * i.e.
28*eb4faa36SYury Norov  *	cpumask_var_t tmpmask;
29*eb4faa36SYury Norov  *	if (!alloc_cpumask_var(&tmpmask, GFP_KERNEL))
30*eb4faa36SYury Norov  *		return -ENOMEM;
31*eb4faa36SYury Norov  *
32*eb4faa36SYury Norov  *	  ... use 'tmpmask' like a normal struct cpumask * ...
33*eb4faa36SYury Norov  *
34*eb4faa36SYury Norov  *	free_cpumask_var(tmpmask);
35*eb4faa36SYury Norov  *
36*eb4faa36SYury Norov  *
37*eb4faa36SYury Norov  * However, one notable exception is there. alloc_cpumask_var() allocates
38*eb4faa36SYury Norov  * only nr_cpumask_bits bits (in the other hand, real cpumask_t always has
39*eb4faa36SYury Norov  * NR_CPUS bits). Therefore you don't have to dereference cpumask_var_t.
40*eb4faa36SYury Norov  *
41*eb4faa36SYury Norov  *	cpumask_var_t tmpmask;
42*eb4faa36SYury Norov  *	if (!alloc_cpumask_var(&tmpmask, GFP_KERNEL))
43*eb4faa36SYury Norov  *		return -ENOMEM;
44*eb4faa36SYury Norov  *
45*eb4faa36SYury Norov  *	var = *tmpmask;
46*eb4faa36SYury Norov  *
47*eb4faa36SYury Norov  * This code makes NR_CPUS length memcopy and brings to a memory corruption.
48*eb4faa36SYury Norov  * cpumask_copy() provide safe copy functionality.
49*eb4faa36SYury Norov  *
50*eb4faa36SYury Norov  * Note that there is another evil here: If you define a cpumask_var_t
51*eb4faa36SYury Norov  * as a percpu variable then the way to obtain the address of the cpumask
52*eb4faa36SYury Norov  * structure differently influences what this_cpu_* operation needs to be
53*eb4faa36SYury Norov  * used. Please use this_cpu_cpumask_var_t in those cases. The direct use
54*eb4faa36SYury Norov  * of this_cpu_ptr() or this_cpu_read() will lead to failures when the
55*eb4faa36SYury Norov  * other type of cpumask_var_t implementation is configured.
56*eb4faa36SYury Norov  *
57*eb4faa36SYury Norov  * Please also note that __cpumask_var_read_mostly can be used to declare
58*eb4faa36SYury Norov  * a cpumask_var_t variable itself (not its content) as read mostly.
59*eb4faa36SYury Norov  */
60*eb4faa36SYury Norov #ifdef CONFIG_CPUMASK_OFFSTACK
61*eb4faa36SYury Norov typedef struct cpumask *cpumask_var_t;
62*eb4faa36SYury Norov #else
63*eb4faa36SYury Norov typedef struct cpumask cpumask_var_t[1];
64*eb4faa36SYury Norov #endif /* CONFIG_CPUMASK_OFFSTACK */
65*eb4faa36SYury Norov 
66*eb4faa36SYury Norov #endif /* __LINUX_CPUMASK_TYPES_H */
67