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