linux内核锁机制-不可睡眠锁之RCU

RCU

 Read-Copy-Update

linux内核RCU的演变


 下面是一个使用rcu做读写的演示


#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/rcupdate.h>


#include "tmain.h"
MODULE_DESCRIPTION("The module is only used for test");
MODULE_VERSION("1.0.0");
MODULE_AUTHOR("David Zhang");
MODULE_LICENSE("GPL");


#define MAX_KTHREAD  10
static unsigned long reader_bitmap;
static void set_reader_number(int reader)
{
  WARN_ON((MAX_KTHREAD-reader) != 1);


  reader_bitmap=0;
  while(reader){
    reader_bitmap |= (1 << --reader);
  }
}
/*
unsigned int testpar= 0;
module_param(testpar, uint, S_IRUGO | S_IWUSR);
//static DEFINE_SPINLOCK(threads_lock);
static spinlock_t threads_lock;


static void threads_lock_init(void)
{
    //spin_lock_init
  spin_lock_init(&threads_lock);
}


*/


struct our_data{
  int count1;
  int count2;
};


static struct our_data my_data;

//to tell reader this pointer is protected by rcu
//linux kernel will check staticly when you use rcu_dereference, and source code is friendly to reader 
static struct our_data __rcu *pmy_data=&my_data;


static void reader_do(void)
{
   struct our_data *data;
   rcu_read_lock();
   data = rcu_dereference(pmy_data);
   printk("read count1 %d, count2 %d.\n",data->count1,data->count2);
   rcu_read_unlock();
}


static void writer_do(void)
{
  struct our_data *data, *tmp=pmy_data;
  data = kmalloc(sizeof(*data),GFP_KERNEL);
  if(!data)
    return;
  //Read + Copy. */
  memcpy(data,pmy_data,sizeof(*data));
  data->count1++;
  data->count2 +=10;
  
  rcu_assign_pointer(pmy_data,data);
  if(tmp != &my_data)
  {
    synchronize_rcu();
    kfree(tmp);
    printk("write completed!");


  }
  //Update


}

static struct task_struct *threads[MAX_KTHREAD];


static int thread_do(void *data)
{
long i=(long)data;
int isReader=reader_bitmap & (1 << i);
printk("run ...%ld %s \n",i,isReader?"reader":"writer");
while(!kthread_should_stop())
{
 if(isReader)
   reader_do();
   else
   writer_do();
 msleep(10);
}
return 0;
}


static void show_my_data(void)
{
   printk("my_data,count1:%d,count2:%d\n",pmy_data->count1,pmy_data->count2);
   
}


static int create_threads(void)
{
int i;
for(i=0;i<MAX_KTHREAD;i++){
struct task_struct *thread;
thread=kthread_run(thread_do,(void *)(long)i,"thread-%d",i);
if(IS_ERR(thread))
 return -1;
threads[i]=thread;


}
return 0;
}


static void cleanup_threads(void)
{
int i;
for(i=0;i<MAX_KTHREAD;i++)
{
 if(threads[i]){
   kthread_stop(threads[i]);
 }
}
}


static __init int minit(void)
{
// printk("testpar= %#x.\n",testpar);
printk("call %s.\n",__FUNCTION__);
// other_function();
set_reader_number(9);
if(create_threads())
{
 cleanup_threads();
 return -1;
}
return 0;
}


static __exit void mexit(void)
{
printk("call %s.\n",__FUNCTION__);
show_my_data();
}


module_init(minit)
module_exit(mexit)


//

sudo dmesg -c

sudo rmmod rcumain

sudo dmesg -c

sudo insmod rcumain.ko

sudo dmesg -c

[21685.846012] read count1 736, count2 7360.
[21685.846026] read count1 736, count2 7360.
[21685.846048] read count1 736, count2 7360.
[21685.849910] read count1 736, count2 7360.
[21685.849920] read count1 736, count2 7360.
[21685.857896] read count1 736, count2 7360.
[21685.857917] read count1 737, count2 7370.
[21685.861919] read count1 737, count2 7370.
[21685.861930] read count1 737, count2 7370.
[21685.861934] read count1 737, count2 7370.
[21685.861942] read count1 737, count2 7370.
[21685.861950] read count1 737, count2 7370.
[21685.865947] read count1 737, count2 7370.
[21685.865951] read count1 737, count2 7370.
[21685.873999] read count1 737, count2 7370.
[21685.874012] read count1 737, count2 7370.
[21685.878018] read count1 737, count2 7370.
[21685.878042] write completed!
[21685.878042] read count1 737, count2 7370.
[21685.878052] read count1 737, count2 7370.
[21685.878058] read count1 737, count2 7370.
[21685.878071] read count1 737, count2 7370.
[21685.881994] read count1 737, count2 7370.
[21685.882041] read count1 737, count2 7370.
[21685.889995] read count1 737, count2 7370.
[21685.890014] read count1 737, count2 7370.
[21685.894022] read count1 737, count2 7370.
[21685.894030] read count1 737, count2 7370.
[21685.894034] read count1 737, count2 7370.
[21685.894047] read count1 737, count2 7370.
[21685.894071] read count1 738, count2 7380.
[21685.898010] read count1 738, count2 7380.
[21685.898032] read count1 738, count2 7380.
[21685.906007] read count1 738, count2 7380.
[21685.906039] read count1 738, count2 7380.
[21685.910028] read count1 738, count2 7380.
[21685.910033] read count1 738, count2 7380.
[21685.910054] read count1 738, count2 7380.
[21685.910059] read count1 738, count2 7380.
[21685.910087] read count1 738, count2 7380.
[21685.913979] write completed!
[21685.913980] read count1 738, count2 7380.
[21685.913992] read count1 738, count2 7380.
[21685.922028] read count1 738, count2 7380.
[21685.922039] read count1 738, count2 7380.
[21685.926040] read count1 738, count2 7380.
[21685.926056] read count1 738, count2 7380.
[21685.926060] read count1 738, count2 7380.
[21685.926069] read count1 738, count2 7380.
[21685.926081] read count1 739, count2 7390.
[21685.929972] read count1 739, count2 7390.
[21685.929983] read count1 739, count2 7390.
[21685.938034] read count1 739, count2 7390.
[21685.938050] read count1 739, count2 7390.
[21685.942048] read count1 739, count2 7390.
[21685.942056] read count1 739, count2 7390.
[21685.942070] read count1 739, count2 7390.
[21685.942095] read count1 739, count2 7390.
[21685.942106] write completed!
[21685.942107] read count1 739, count2 7390.
[21685.946061] read count1 739, count2 7390.
[21685.946067] read count1 739, count2 7390.
[21685.954022] read count1 739, count2 7390.
[21685.954039] read count1 739, count2 7390.
[21685.958001] read count1 739, count2 7390.
[21685.958010] read count1 739, count2 7390.
[21685.958038] read count1 739, count2 7390.
[21685.958055] read count1 739, count2 7390.
[21685.962051] read count1 739, count2 7390.
[21685.962071] read count1 739, count2 7390.
[21685.962083] read count1 739, count2 7390.
[21685.970068] read count1 740, count2 7400.
[21685.970106] read count1 740, count2 7400.
[21685.974073] read count1 740, count2 7400.
[21685.974108] read count1 740, count2 7400.
[21685.974140] read count1 740, count2 7400.
[21685.974156] read count1 740, count2 7400.
[21685.978060] read count1 740, count2 7400.
[21685.978081] read count1 740, count2 7400.
[21685.978084] read count1 740, count2 7400.
[21685.986083] read count1 740, count2 7400.
[21685.986091] read count1 740, count2 7400.
[21685.989117] write completed!
[21685.990030] read count1 740, count2 7400.
[21685.990039] read count1 740, count2 7400.
[21685.990046] read count1 740, count2 7400.
[21685.990056] read count1 740, count2 7400.
[21685.994081] read count1 740, count2 7400.
[21685.994088] read count1 740, count2 7400.
[21685.994104] read count1 740, count2 7400.
[21686.002038] read count1 740, count2 7400.
[21686.002045] read count1 740, count2 7400.
[21686.006030] read count1 741, count2 7410.
[21686.006050] read count1 741, count2 7410.
[21686.006059] read count1 741, count2 7410.
[21686.006070] read count1 741, count2 7410.
[21686.010040] read count1 741, count2 7410.
[21686.010074] read count1 741, count2 7410.
[21686.010084] read count1 741, count2 7410.
[21686.014687] write completed!
[21686.018046] read count1 741, count2 7410.
[21686.018053] read count1 741, count2 7410.
[21686.022043] read count1 741, count2 7410.
[21686.022059] read count1 741, count2 7410.
[21686.022061] read count1 741, count2 7410.
[21686.022073] read count1 741, count2 7410.
[21686.026037] read count1 741, count2 7410.
[21686.026048] read count1 741, count2 7410.
[21686.026075] read count1 741, count2 7410.

=============

call_rcu vs. synchronize_rcu



static void rcu_free(struct rcu_head *head)
{
   struct our_data *data;
   data =container_of(head,struct our_data,rhead);
   printk("rcu_free is called!");
   kfree(data);
}
static void writer_do(void)
{
  struct our_data *data, *tmp=pmy_data;
  data = kmalloc(sizeof(*data),GFP_KERNEL);
  if(!data)
    return;
  //Read + Copy. */
  memcpy(data,pmy_data,sizeof(*data));
  data->count1++;
  data->count2 +=10;
  
  rcu_assign_pointer(pmy_data,data);
  if(tmp != &my_data)
  {
    call_rcu(&tmp->rhead,rcu_free);
  }
  //Update


}

[  140.690494] read count1 49, count2 490.
[  140.690505] read count1 49, count2 490.
[  140.690526] read count1 50, count2 500.
[  140.706419] rcu_free is called!
[  140.706462] read count1 50, count2 500.
[  140.706466] read count1 50, count2 500.
[  140.706471] read count1 50, count2 500.
[  140.706484] read count1 50, count2 500.
[  140.706488] read count1 50, count2 500.
[  140.706497] read count1 50, count2 500.
[  140.706510] read count1 50, count2 500.
[  140.706511] read count1 50, count2 500.
[  140.706515] read count1 50, count2 500.
[  140.722388] rcu_free is called!
[  140.722439] read count1 51, count2 510.
[  140.722444] read count1 51, count2 510.
[  140.722447] read count1 51, count2 510.
[  140.722452] read count1 51, count2 510.
[  140.722465] read count1 51, count2 510.
[  140.722473] read count1 51, count2 510.
[  140.722480] read count1 51, count2 510.
[  140.722487] read count1 52, count2 520.
[  140.722508] read count1 52, count2 520.
[  140.738443] rcu_free is called!
[  140.738478] rcu_free is called!read count1 52, count2 520.
[  140.738495] read count1 52, count2 520.
[  140.738521] read count1 52, count2 520.
[  140.738525] read count1 52, count2 520.
[  140.738529] read count1 52, count2 520.
[  140.738536] read count1 52, count2 520.
[  140.738542] read count1 52, count2 520.
[  140.738557] read count1 52, count2 520.
[  140.738560] read count1 52, count2 520.
[  140.754488] read count1 53, count2 530.
[  140.754494] read count1 53, count2 530.
[  140.754513] read count1 53, count2 530.
[  140.754528] read count1 53, count2 530.
[  140.754546] read count1 53, count2 530.
[  140.754558] read count1 53, count2 530.
[  140.754562] read count1 53, count2 530.
[  140.754587] read count1 54, count2 540.
[  140.754590] read count1 54, count2 540.
[  140.770496] rcu_free is called!
[  140.770497] read count1 54, count2 540.
[  140.770510] read count1 54, count2 540.
[  140.770518] read count1 54, count2 540.
[  140.770523] read count1 54, count2 540.
[  140.770529] read count1 54, count2 540.
[  140.770539] read count1 54, count2 540.
[  140.770543] read count1 54, count2 540.
[  140.770556] read count1 54, count2 540.
[  140.770589] read count1 54, count2 540.
[  140.786502] rcu_free is called!
[  140.786503] read count1 55, count2 550.
[  140.786543] read count1 55, count2 550.
[  140.786547] read count1 55, count2 550.
[  140.786557] read count1 55, count2 550.
[  140.786563] read count1 55, count2 550.
[  140.786569] read count1 55, count2 550.
[  140.786574] read count1 55, count2 550.
[  140.786618] read count1 56, count2 560.
[  140.786644] read count1 56, count2 560.
[  140.802465] read count1 56, count2 560.
[  140.802491] rcu_free is called!
[  140.802523] read count1 56, count2 560.
[  140.802526] read count1 56, count2 560.
[  140.802529] read count1 56, count2 560.
[  140.802538] read count1 56, count2 560.
[  140.802544] read count1 56, count2 560.
[  140.802560] read count1 56, count2 560.
[  140.802563] read count1 56, count2 560.
[  140.802573] read count1 56, count2 560.
[  140.818512] rcu_free is called!
[  140.818512] read count1 57, count2 570.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值