Chinaunix首页 | 论坛 | 博客
  • 博客访问: 81652
  • 博文数量: 19
  • 博客积分: 1635
  • 博客等级: 上尉
  • 技术积分: 231
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-18 08:13
文章分类

全部博文(19)

文章存档

2013年(1)

2012年(7)

2011年(3)

2010年(3)

2008年(5)

我的朋友

分类: LINUX

2012-08-29 15:27:34

call_rcu定义在linux/kernel/rcupdate.c定义:

  1. 117void fastcall call_rcu(struct rcu_head *head,
  2. 118 void (*func)(struct rcu_head *rcu))
  3. 119{
  4. 120 unsigned long flags;
  5. 121 struct rcu_data *rdp;
  6. 122
  7. 123 head->func = func;
  8. 124 head->next = NULL;
  9. 125 local_irq_save(flags);
  10. 126 rdp = &__get_cpu_var(rcu_data);
  11. 127 *rdp->nxttail = head;
  12. 128 rdp->nxttail = &head->next;
  13. 129 if (unlikely(++rdp->qlen > qhimark)) {
  14. 130 rdp->blimit = INT_MAX;
  15. 131 force_quiescent_state(rdp, &rcu_ctrlblk);
  16. 132 }
  17. 133 local_irq_restore(flags);
  18. 134}

首先会把回调函数注册到rcu_head结构,head->func = func
   local_irq_save(flags);屏蔽中断,并保存当前CPU的状态。
   而local_irq_restore(flags);重新开中断,并恢复到屏蔽中断前状态。
   rdp = &__get_cpu_var(rcu_data);

访问本CPU的私有数据,相当于取出CPU的私有数据,per_cpu__rcu_data。
    并把回调函数注册per_cpu__rcu_data链表中。
      
likely和unlikely是用来编译优化的,其实都可以没有。
我们知道很多cpu里面有高速缓存,且有预读机制,likely和unlikely就是增加执行判断语句时的命中率
如果是if(likely(a)),说明a条件发生的可能性大,那么a为真的语句在编译成二进制的时候就应该紧跟在前面程序的后面,这样就会被cache预读取进去,增加程序执行速度。 unlikely则是正好相反。


最让我犯迷糊的是
  1. 127 *rdp->nxttail = head;
  2. 128 rdp->nxttail = &head->next;
二级指针的含义弄混了,贴段代码复习下

  1. int fun(){
  2.     int a = 0x100;
  3.     int b = 0x200;
  4.     int *p = &a;
  5.     int *p1 = &b;
  6.     int **pp = &p1;
  7.     printf("a %X \n",a);
  8.     printf("&a %X \n",(int*) &a);
  9.     printf("p %X\n",p);
  10.     printf("&p %X\n",&p);
  11.     printf("*p %X\n",*p);
  12.     printf("\n");
  13.     printf("b %X \n",b);
  14.     printf("&b %X \n",(int*) &b);
  15.     printf("p1 %X\n",p1);
  16.     printf("&p1 %X\n",&p1);
  17.     printf("*p1 %X\n",*p1);
  18.     printf("************************************\n");
  19.     printf("First change\n");
  20.     *pp = p;
  21.     printf("b %X \n",b);
  22.     printf("&b %X \n",(int*) &b);
  23.     printf("p1 %X\n",p1);
  24.     printf("&p1 %X\n",&p1);
  25.     printf("*p1 %X\n",*p1);
  26.     printf("\n");    
  27.     printf("&pp %X\n",(int *)&pp);
  28.     printf("pp %X\n", pp);
  29.     printf("*pp %X\n",*pp);
  30.     printf("**pp %X\n",**pp);
  31.     printf("************************************\n");
  32.     printf("Second change\n");
  33.     pp = &p;
  34.     printf("&pp %X\n",(int *)&pp);
  35.     printf("pp %X\n", pp);
  36.     printf("*pp %X\n",*pp);
  37.     printf("**pp %X\n",**pp);
  38.     printf("************************************\n");
  39.     return 0;
  40. }

附上两个结构体的定义

  1. #define GP_STAGES 2
  2. struct rcu_data {
  3.          spinlock_t lock; //保护此结构中字段的自旋锁
  4.          long completed; //总的阶段计数器
  5.          int waitlistcount;
  6.          struct rcu_head *nextlist; //一些链表,记录更新回调函数
  7.          struct rcu_head **nexttail;
  8.          struct rcu_head *waitlist[GP_STAGES];
  9.          struct rcu_head **waittail[GP_STAGES];
  10.          struct rcu_head *donelist;
  11.          struct rcu_head **donetail;
  12.          long rcu_flipctr[2]; //这个很重要
  13.          struct rcu_head *nextschedlist;
  14.          struct rcu_head **nextschedtail;
  15.          struct rcu_head *waitschedlist;
  16.          struct rcu_head **waitschedtail;
  17.          int rcu_sched_sleeping;
  18. };


  1. struct rcu_head {
  2.     struct rcu_head *next;
  3.     void (*func)(struct rcu_head *head);
  4. };

阅读(570) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~