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+);
}

cpu位图的更多相关文章

  1. Linux CPU Hotplug CPU热插拔

    http://blog.chinaunix.net/uid-15007890-id-106930.html   CPU hotplug Support in Linux(tm) Kernel Linu ...

  2. linux tricks 之 bitmap分析.

    ------------------------------------------- 本文系作者原创, 欢迎大家转载! 转载请注明出处:netwalker.blog.chinaunix.net -- ...

  3. 【转】Linux模式设计5-位图操作

    通过位图提供的两种状态可以在非常节约内存的情况下表示开关变量,并且同类这类变量可以紧凑而高效的统一进行处理.有很多内核子系统都需要位图的支持,但是不同的情况又需要不同的位图个数,比如SMP系统上的CP ...

  4. 浅析Linux的软中断的实现

    參考: http://bbs.chinaunix.net/thread-2333484-1-1.html http://liu1227787871.blog.163.com/blog/static/2 ...

  5. Linux内核跟踪之trace框架分析【转】

    转自:http://blog.chinaunix.net/uid-20543183-id-1930846.html   ---------------------------------------- ...

  6. Linux内核跟踪之ring buffer的实现【转】

      转自:http://blog.chinaunix.net/uid-20543183-id-1930845.html ---------------------------------------- ...

  7. ARM Linux内核源码剖析索引

    start_kernel -->asm-offset.h 生成 -->proc_info_list   -->machine_desc -->__vet_atags --> ...

  8. 扩展Linux网络栈

    扩展Linux网络栈 来自Linux内核文档.之前看过这篇文章,一直好奇,问什么一条网络流会固定在一个CPU上进行处理,本文档可以解决这个疑问.为了更好地理解本文章中的功能,将这篇文章穿插入内. 简介 ...

  9. [源码解析] PyTorch 分布式(8) -------- DistributedDataParallel之论文篇

    [源码解析] PyTorch 分布式(8) -------- DistributedDataParallel之论文篇 目录 [源码解析] PyTorch 分布式(8) -------- Distrib ...

随机推荐

  1. 破解百度翻译页面api参数加密

    我们的目标 https://fanyi.baidu.com/      找到获取翻译的请求 是这个 https://fanyi.baidu.com/v2transapi 查看一下post提交的表单,是 ...

  2. csrf攻击实例

    CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作.比如说,受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 ht ...

  3. wepy开发踩坑记录

    与vue的不同 methods对象只存放tap等事件触发时的方法 events对象只存放$emit及$broadcast方法触发的事件 自定义方法及属性放在与methods平级的位置 props是动态 ...

  4. P4869 罪犯分组

    思路: 明显的dp,虽然我想到了二进制模拟,想到了转移,但还是先看了题解,原来真是这样,,,,不是第三题吗? 用f[i]表示,对于前i个罪犯最少需要分几组. 对于每个状态用二进制表示,第i位上1,0表 ...

  5. sql、linq和lambda查询语句比较inner join和group by组合使用及匿名类型的处理

    使用EF自己做的小功能需要遇到inner join和group by组合使用及匿名类型的处理,搜了很多,基本不能满足自己的需要,所以总结了也实现了就自己写出来,已备查看及伙伴查询参考(一般的语句查询就 ...

  6. Linux下常用的数据恢复工具

    一.数据删除 命令:rm -rf,将任何数据直接从硬盘删除,且没有任何提示 建议做法: 把命令参数放到后面:rm -rfi 将删除的东西通过mv命令移动到系统下的/temp目录下,然后写个脚 本定期执 ...

  7. 多线程-Thread-Runnable

    一.多线程     1.基本概念         进程:正在运行中的程序,一个进程中至少包含一个线程         线程:进程的任务,执行任务的一个通道,一个进程中可以包含多个线程     2.多线 ...

  8. Android Framework中的Application Framework层介绍

    Android的四层架构相比大家都很清楚,老生常谈的说一下分别为:Linux2.6内核层,核心库层,应用框架层,应用层.我今天重点介绍一下应用框架层Framework,其实也是我自己的学习心得. Fr ...

  9. BZOJ 4777: [Usaco2017 Open]Switch Grass

    4777: [Usaco2017 Open]Switch Grass Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 46  Solved: 10[Su ...

  10. 撤销git pull命令

    比如:在master分支上执行了git pull命令,想回到pull之前分支所在的commit位置. 步骤一:用 git reflog master 查看master分支的历史变动记录,其中有一个就是 ...