SMP处理器中要用到cpu位图,用来维护系统内CPU的状态信息,具有代表性的有:

cpu_possible_map、cpu_online_map、cpu_present_map。

static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly
static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly
static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly

DECLARE_BITMAP宏定义如下

#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]

所以上面定义了三个unsigned long数组,数组大小有BITS_TO_LONGS宏确定,1~31个cpu,则为1;32~63个cpu,则为2。

目前的多核处理器还没有超过31个的,所以这个数组大小一般为1.

unsigned long cpu_possible_map[BITS_TO_LONGS(CONFIG_NR_CPUS)]
unsigned long cpu_online_map[BITS_TO_LONGS(CONFIG_NR_CPUS)]
unsigned long cpu_present_map [BITS_TO_LONGS(CONFIG_NR_CPUS)]

内核中还是用下面的一种结构体,用来表示cpu位图,于上面的结构基本等价。

typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
/*
struct cpumask { unsigned long bits[BITS_TO_LONGS(NR_CPUS)] }
*/

并且定义了to_cpumask宏用于从bit_map数组转换到cpumask结构体。

const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);
const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);
#define to_cpumask(bitmap)                        \
((struct cpumask *)( ? (bitmap) \
: (void *)sizeof(__check_is_bitmap(bitmap)))) static inline int __check_is_bitmap(const unsigned long *bitmap)
{
return ;
}

内核中bitmap的设置与清除

static inline void set_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long flags; _atomic_spin_lock_irqsave(p, flags);
*p |= mask;
_atomic_spin_unlock_irqrestore(p, flags);
} static inline void clear_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long flags; _atomic_spin_lock_irqsave(p, flags);
*p &= ~mask;
_atomic_spin_unlock_irqrestore(p, flags);
} static inline void change_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long flags; _atomic_spin_lock_irqsave(p, flags);
*p ^= mask;
_atomic_spin_unlock_irqrestore(p, flags);
} static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old;
unsigned long flags; _atomic_spin_lock_irqsave(p, flags);
old = *p;
*p = old | mask;
_atomic_spin_unlock_irqrestore(p, flags); return (old & mask) != ;
} static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old;
unsigned long flags; _atomic_spin_lock_irqsave(p, flags);
old = *p;
*p = old & ~mask;
_atomic_spin_unlock_irqrestore(p, flags); return (old & mask) != ;
} static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old;
unsigned long flags; _atomic_spin_lock_irqsave(p, flags);
old = *p;
*p = old ^ mask;
_atomic_spin_unlock_irqrestore(p, flags); return (old & mask) != ;
}

最后几个bitmap中常用的宏

#define BIT(nr)            (1UL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BITS_PER_BYTE 8
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))

把位图中所有bit设置为1

static inline void bitmap_fill(unsigned long *dst, int nbits)
{
size_t nlongs = BITS_TO_LONGS(nbits);
if (!small_const_nbits(nbits)) {
int len = (nlongs - ) * sizeof(unsigned long);
memset(dst, 0xff, len);
}
dst[nlongs - ] = BITMAP_LAST_WORD_MASK(nbits);
}

上面用到两个宏,先判断nbis是否超过32,即表示位图的数组元素是否多余1个

#define small_const_nbits(nbits) \
(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)

最后一个32位可能没有全用到,下面的后过滤出使用到的bit

#define BITMAP_LAST_WORD_MASK(nbits)                    \
( \
((nbits) % BITS_PER_LONG) ? \
(1UL<<((nbits) % BITS_PER_LONG))- : ~0UL \
)

遍历多cpu

#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)

展开为

/**
* for_each_cpu - iterate over every cpu in a mask
* @cpu: the (optionally unsigned) integer iterator
* @mask: the cpumask pointer
*
* After the loop, cpu is >= nr_cpu_ids.
*/
#define for_each_cpu(cpu, mask) \
for ((cpu) = -; \
(cpu) = cpumask_next((cpu), (mask)), \
(cpu) < nr_cpu_ids;)
/**
* cpumask_next - get the next cpu in a cpumask
* @n: the cpu prior to the place to search (ie. return will be > @n)
* @srcp: the cpumask pointer
*
* Returns >= nr_cpu_ids if no further cpus set.
*/
static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
{
/* -1 is a legal arg here. */
if (n != -)
cpumask_check(n);
return find_next_bit(cpumask_bits(srcp), nr_cpumask_bits, n+);
}

最新文章

  1. 深入学习HBase架构原理
  2. 【javaweb学习】解析XML
  3. [转]解决a different object with the same identifier value was already associated with the session错误
  4. django开发的社区和博客
  5. 解决 ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)异常
  6. vc++编译libtiff4.0.4
  7. 百度地图实现车辆轨迹移动播放(baidu map api)
  8. Openjudge-计算概论(A)-整数奇偶排序
  9. Python源码分析
  10. vbs的一些入门基础。。。
  11. Python基础_如何用pip安装文件
  12. 【网络流24题22】最长k可重线段集问题
  13. Dockerfile 中的 multi-stage(多阶段构建)
  14. Confluence 6 通过 SSL 或 HTTPS 运行 - 确定你的证书路径
  15. 基于ASP.NET高职学生工作管理系统--文献随笔(八)
  16. struts2框架学习笔记6:拦截器
  17. {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证
  18. bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门
  19. GreenPlum 初始化配置报错:gpadmin-[ERROR]:-[Errno 12] Cannot allocate memory
  20. oracle Plsql 执行update或者delete时卡死问题解决办法

热门文章

  1. mysql8.0数据库忘记密码时进行修改方法
  2. Codeforces Round #375 (Div. 2) D. Lakes in Berland 并查集
  3. Log4j输出格式log4j的PatternLayout参数含义
  4. H5的storage(sessionstorage&amp;localStorage)简单存储删除
  5. jQuery中slim版本与普通版本的区别
  6. C# List的使用
  7. Linux下如何修改用户默认目录
  8. UVA11090 Going in Cycle (二分+判负环)
  9. 10.1 plan
  10. APT和它的超级牛力