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. NET CORE 基础

    NET CORE 基础管理系统 [SF]开源的.NET CORE 基础管理系统 - 安装篇   [SF]开源的.NET CORE 基础管理系统 -系列导航 1.开发必备工具 IDE:VS2017 运行 ...

  2. windows下指定端口号起步memcached

    双击.exe启动的话,默认启动的端口是11211 ,要指定端口的话加 -p + 端口号,如: E:\tools\memcached-1.4.5-win32>memcached-1.4.5.exe ...

  3. 执行ng build --prod --aot命令报错

    D:\git\**\src\main\iui>ng build --prod --aotHash: 257ab60feca43633b6f7Time: 25358mschunk {0} poly ...

  4. 一个很好用的侧滑框架ICSDrawerController实现的 QQ 侧滑及换肤功能

    使用ICSDrawerController 实现侧滑功能 在ICSDrawerController 第三方上做了修改实现,QQ 点击头像打开关抽屉头像渐变的效果 - (void)hiddenHeadV ...

  5. Java基础:(五)Object通用方法

    一.Object对象的九个方法 getClass():hashCode():equals():clone():toString():notify():notifyAll():wait():finali ...

  6. Java基础知识 ——JDK,JRE和JVM

    1.开发简单的Java程序过程: 名词解释: JDK:JDK是 Java 语言的软件开发工具包,主要用于移动设备.嵌入式设备上的java应用程序.JDK是整个java开发的核心,它包含了JAVA的运行 ...

  7. Spring的七种事务传播机制

    概述 当我们调用一个基于Spring的Service接口方法(如UserService#addUser())时,它将运行于Spring管理的事务环境中,Service接口方法可能会在内部调用其它的Se ...

  8. 韦东山笔记之安装arm-linux-gcc交叉编译环境详细步骤。

    1在关盘主目录tools下复制arm-linux-gcc-3.4.5-glibc-2.3.6.tar.bz2到虚拟机上     解压 tar xjf arm-linux-gcc-3.4.5-glibc ...

  9. 洛谷P2606 [ZJOI2010]排列计数(组合数 dp)

    题意 题目链接 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案 ...

  10. uva 10328 - Coin Toss 投硬币(dp递推,大数)

    题意:抛出n次硬币(有顺序),求至少k个以上的连续正面的情况的种数. 思路:转换成求抛n个硬币,至多k-1个连续的情况种数,用所有可能出现的情况种数减去至多k-1个的情况,就得到答案了.此题涉及大数加 ...