cpu位图
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位图的更多相关文章
- Linux CPU Hotplug CPU热插拔
http://blog.chinaunix.net/uid-15007890-id-106930.html CPU hotplug Support in Linux(tm) Kernel Linu ...
- linux tricks 之 bitmap分析.
------------------------------------------- 本文系作者原创, 欢迎大家转载! 转载请注明出处:netwalker.blog.chinaunix.net -- ...
- 【转】Linux模式设计5-位图操作
通过位图提供的两种状态可以在非常节约内存的情况下表示开关变量,并且同类这类变量可以紧凑而高效的统一进行处理.有很多内核子系统都需要位图的支持,但是不同的情况又需要不同的位图个数,比如SMP系统上的CP ...
- 浅析Linux的软中断的实现
參考: http://bbs.chinaunix.net/thread-2333484-1-1.html http://liu1227787871.blog.163.com/blog/static/2 ...
- Linux内核跟踪之trace框架分析【转】
转自:http://blog.chinaunix.net/uid-20543183-id-1930846.html ---------------------------------------- ...
- Linux内核跟踪之ring buffer的实现【转】
转自:http://blog.chinaunix.net/uid-20543183-id-1930845.html ---------------------------------------- ...
- ARM Linux内核源码剖析索引
start_kernel -->asm-offset.h 生成 -->proc_info_list -->machine_desc -->__vet_atags --> ...
- 扩展Linux网络栈
扩展Linux网络栈 来自Linux内核文档.之前看过这篇文章,一直好奇,问什么一条网络流会固定在一个CPU上进行处理,本文档可以解决这个疑问.为了更好地理解本文章中的功能,将这篇文章穿插入内. 简介 ...
- [源码解析] PyTorch 分布式(8) -------- DistributedDataParallel之论文篇
[源码解析] PyTorch 分布式(8) -------- DistributedDataParallel之论文篇 目录 [源码解析] PyTorch 分布式(8) -------- Distrib ...
随机推荐
- NET Core Web发布包
给ASP.NET Core Web发布包做减法 https://www.cnblogs.com/sheng-jie/p/9122582.html 1.引言 紧接上篇:ASP.NET Core Web ...
- NET Core容器
NET Core容器化之多容器应用部署@Docker-Compose 1.引言 紧接上篇.NET Core容器化@Docker,这一节我们先来介绍如何使用Nginx来完成.NET Core应用的反 ...
- ABP框架和NET CORE实战
http://www.fishpro.com.cn/2017/09/ ABP实战系列 ABP实战 ABP-第一个Asp.net core 示例(7)AutoMapper的使用 我们为什么需要使用DDD ...
- 关于使用rancher部署k8s集群的一些小问题的解决
问题一: 在rancher的ui上,不能创建k8s的master节点的高可用集群.创建k8s集群,添加节点的时候,可以添加多个master,但是多个master又没有高可用,只要其中一个出问题了,那么 ...
- 剖析js中的数据类型
首先说一下八种常见的数据类型:五种简单的数据类型和三种复杂数据类型. 简单数据类型 Number:数字类型 String:字符串 Boolean:布尔类型 Undefined:未定义 Null:空 复 ...
- 040 Combination Sum II 组合总和 II
给定候选号码数组 (C) 和目标总和数 (T),找出 C 中候选号码总和为 T 的所有唯一组合.C 中的每个数字只能在组合中使用一次.注意: 所有数字(包括目标)都是正整数. 解决方案集不 ...
- 《javascript设计模式》笔记之第十二章:装饰者模式
一.装饰者模式的作用 为函数或者对象的方法添加一些行为. 二.装饰者模式的原理 装饰者模式不是直接修改对象,而是以要修改的对象为基础,新建一个对象.不过这个新建的对象看起来就像在原对象的基础上 ...
- Quartz.NET基础入门
Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等. Quartz.NET允许开发人员根据时间间隔(或天)来调度作业.它实现了作业和 ...
- 第12届D2前端技术论坛
第12届D2前端技术论坛 最近参加了阿里的D2前端技术论坛,听了一天的报告,收获良多,下面对几场报告做一个记录. 自己选择听的主线也是从: 实践应用 -> 管理 -> 性能 -> 新 ...
- nodejs 实践:express 最佳实践(七) 改造模块 connect2 解析
nodejs 实践:express 最佳实践(七) 改造模块 connect2 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的 ...