jinxinxin163 发表于 2015-01-21 22:44

对per-cpu变量tvec_bases的疑问

///定义了一个per cpu变量.这里要知道定时器的注册和触发执行一定是在相同的cpu上的.
struct tvec_base boot_tvec_bases;
static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
疑问:
tvec_bases虽然是per cpu变量,但是指向的都是&boot_tvec_bases,也就是说不同的cpu其实操作的都是同一个变量,这样做有什么意义呢?能避免同步问题么?

super皮波 发表于 2015-01-21 23:36

启动的时候,会将这个变量做一个偏移处理,实际上每个tvec_base指向的都是不同的值,只是要基于boot_tvec_bases这个变量去找本节点的变量,不知道说清楚没

瀚海书香 发表于 2015-01-22 08:40

回复 1# jinxinxin163

///定义了一个per cpu变量.这里要知道定时器的注册和触发执行一定是在相同的cpu上的.
struct tvec_base boot_tvec_bases;
static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
疑问:
tvec_bases虽然是per cpu变量,但是指向的都是&boot_tvec_bases,也就是说不同的cpu其实操作的都是同一个变量,这样做有什么意义呢?能避免同步问题么?

你是这么理解per_cpu的?

per_cpu的含义是同一个变量名,对应多个存储地址,当每个CPU访问的时候,根据CPUID便宜到相应的地址,所以不同的CPU访问同一个变量名,但实际上却是不同的物理地址。

   

Tinnal 发表于 2015-01-22 08:42

回复 1# jinxinxin163


真的tvec_bases会在static int __cpuinit init_timers_cpu(int cpu)函数里进行重新赋值,这样,每个CPU的tvec_base就不一样了。boot_tvec_bases这个base,最终只会留给启动核来用。

static int __cpuinit init_timers_cpu(int cpu)
{
        int j;
        struct tvec_base *base;
        static char __cpuinitdata tvec_base_done;

        if (!tvec_base_done) {
                static char boot_done;

                if (boot_done) {
                        /*
                       * The APs use this path later in boot
                       */
                        base = kmalloc_node(sizeof(*base),
                                                GFP_KERNEL | __GFP_ZERO,
                                                cpu_to_node(cpu));
                        《。。。》
                        per_cpu(tvec_bases, cpu) = base;
                } else {
                        /*
                       * This is for the boot CPU - we use compile-time
                       * static initialisation because per-cpu memory isn't
                       * ready yet and because the memory allocators are not
                       * initialised either.
                       */
                        boot_done = 1;
                        base = &boot_tvec_bases;
                }
                spin_lock_init(&base->lock);
                tvec_base_done = 1;
        } else {
                base = per_cpu(tvec_bases, cpu);
        }

      《。。。》
}

Tinnal 发表于 2015-01-22 08:49

@瀚海书香@super皮波
我想两位可能理解错了楼主的意思了。

tvec_bases是PerCPU没错。会有多份物理地址不同,但变量名叫tvec_bases的也没错。但每一份的的副本里头的存内容是什么?楼主可以关心的是这个,关心的是这个核的这个PerCPU是不是都同时指向boot_tvec_bases。

super皮波 发表于 2015-01-22 09:42

这种问题,只要知道per-cpu变量是如何存放的就知道了,初始化的时候会拷贝n份(n是cpu的个数),在使用的时候,每个cpu节点使用自己的那份拷贝

jinxinxin163 发表于 2015-02-11 11:43

回复 2# super皮波

那按照你的意思,其实把boot_tvec_bases赋值过去就好了,没必要是&boot_tvec_bases把
   

jinxinxin163 发表于 2015-02-11 11:48

回复 3# 瀚海书香


    感谢啊,这里我主要是对&boot_tvec_bases不太理解,我的理解是boot_tvec_bases就好了

    既然,这里是指针,那么不同cpu都有一个指针指向&boot_tvec_bases,那么其实还是一个变量,对否?

事实不是,所以,我的理解肯定不对

super皮波 发表于 2015-02-11 11:55

回复 7# jinxinxin163

那按照你的意思,其实把boot_tvec_bases赋值过去就好了,没必要是&boot_tvec_bases把

tvec_bases是基于boot_tvec_bases的地址来去分配和查找当前cpu上的tvec_bases变量的
你直接找文档看看,per-cpu变量的分配和查找过程,看完了,你肯定就没有疑问了
   
页: [1]
查看完整版本: 对per-cpu变量tvec_bases的疑问