以下分析的源码是在kernel4.14中
一、 struct cpumask 结构
typedef struct cpumask {
DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
//kernel4.14/include/linux/types.h
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
//kernel4.14/include/linux/bitops.h
#define BITS_PER_BYTE 8
#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
已知 NR_CPUS = 8 ,结构体 struct cpumask 内实现
(1) 如果cpu的核数为8,则NR_CPUS = 8; BITS_PER_BYTE = 8,sizeof(long) = 8, 则DIV_ROUND_UP 中 n=8,d=64,展开为(8+64-1)/64=1。
(2) DECLARE_BITMAP(name,bits) 展开后为 unsigned long name[1]。
(3) 结构体 struct cpumask 展开为
struct cpumask {
unsigned long bits[1];
}
结构体 struct cpumask 宏展开
struct cpumask {
DECLARE_BITMAP(bits,NR_CPUS)
=>unsigned long bits[BITS_TO_LONGS(NR_CPUS)]
=>unsigned long bits[DIV_ROUND_UP(NR_CPUS, BITS_PER_BYTE * sizeof(long))]
=>unsigned long bits[(((NR_CPUS) + (BITS_PER_BYTE * sizeof(long)) - 1) / (BITS_PER_BYTE * sizeof(long)))]
}
总之:
一般情况下,最终拿到的是unsigned long形的一个bits[1] 。需要的是unsigned long形里的不同的位。
二、给 struct cpumask 结构 赋值
1. cpumask_set_cpu (unsigned int cpu, struct cpumask *dstp)
根据cpu值,把对应 struct cpumask 结构 值置上
举例:
struct cpumask cpu_mask;
cpumask_set_cpu(1, &cpu_mask);
/**
* cpumask_set_cpu - set a cpu in a cpumask
* @cpu: cpu number (< nr_cpu_ids)
* @dstp: the cpumask pointer
*/
static inline void cpumask_set_cpu(unsigned int cpu, struct cpumask *dstp)
{
set_bit(cpumask_check(cpu), cpumask_bits(dstp));
}
static inline unsigned int cpumask_check(unsigned int cpu)
{
#ifdef CONFIG_DEBUG_PER_CPU_MAPS