Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31936
  • 博文数量: 7
  • 博客积分: 250
  • 博客等级: 二等列兵
  • 技术积分: 82
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-10 08:44
文章分类

全部博文(7)

文章存档

2011年(2)

2008年(5)

我的朋友
最近访客

分类: LINUX

2008-09-25 17:06:12

.date.percpu是汇编中的一个数据段:

#define DEFINE_PER_CPU(type, name) __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name


上面这段宏,将被扩展为:

_attribute__((__section__(".data.percpu"))) __typeof__(struct runqueue) per_cpu__runqueues


就是在 .data.percpu段中定义了一个类型为 struct runqueue 的变量 per_cpu__runqueues ;
这个变量就是一个偏移量,标识该变量的地址。

而 ## 作为连接符, 把宏参数 name 链接成变量 per_cpu__name;

在系统启动后,start_kernel()函数会对每个cpu进行设置:
  1. 为每一个cpu分配一段专有数据区,然后把 .data.percpu段中的数据拷贝到其中,每个cpu各一份。
  2. 由于复制给了每个cpu各一份,所以存取其中的值就不能再直接用per_cpu__runqueues做偏移量了,而要 + __per_cpu_offset[i],i表示cpuid。


如何存取per cpu的变量:
  1.  对于 __get_cpu_var(runqueues),等效扩展为:                          

__per_cpu_offset[smp_processor_id()] + per_cpu__runqueues

这正好是上述per_cpu__runqueues变量在对应CPU的专有数据区中的新地址。
由于不同的per cpu变量有不同的偏移量,并且不同的CPU其专有数据区首地址不同,
因此,通过__get_cpu_var()便访问到了不同的变量。


                      likely()  &&  unlikely()

#define likely(x) __buildin_expect(!!(x),1) /*x 大多数不为0*/
#define unlikely(x) __buildin_expect(!!(x),0) /*x 大多数为0*/

这是gcc的扩展,目的是增加条件分支预测的准确性,cpu会提前装载后面的指令,遇到条件转移指令时会提前预测并装载某个分支的指令。
unlikely 表示你可以确认该条件是极少发生的;
相反likely表示该条件多数情况下会发生。编译器会产生相应的代码来优化cpu执行效率。

cpumask_of_cpu(cpu)
根据处理器编号cpu,将处理器位图的相应位置置为1(其它位为0):
既:如果CPU == 3,则cpumask_of_cpu(cpu)把cpu位图第三位置1,其他为置0.

#define cpumask_of_cpu(cpu) \
({ \
    typeof(_unused_cpumask_arg_) m; \
    if (sizeof(m) == sizeof(unsigned long)) { \
        m.bits[0] = 1UL<<(cpu); \
    } else { \
        cpus_clear(m); \
        cpu_set((cpu), m); \
    } \
    m; \
})


阅读(963) | 评论(0) | 转发(0) |
0

上一篇:linux 中的时钟

下一篇:存储管理

给主人留下些什么吧!~~