首页 > 其他分享 >RCU-55——RCU案例汇总

RCU-55——RCU案例汇总

时间:2023-04-27 21:25:23浏览次数:29  
标签:55 RCU 汇总 new int key rcu test entry

基于 Linux-5.10

一、经典(可抢占)RCU

1. 例子-RCU链表

假设链表节点和头结点如下:

typedef struct {
    struct list_head link;
    struct rcu_head rcu; //used for call_rcu()
    int key;
    int val;
} test_entry;

struct list_head test_head;

读者访问链表方法如下:

int test_read(int key, int *val_ptr)
{
    test_entry *entry;
    int found = 0;

    rcu_read_lock();
    list_for_each_entry_rcu(entry, &test_head, link) {
        if (entry->key == key) {
            *val_ptr = entry->val;
            found = 1;
            break;
        }
    }
    rcu_read_unlock();

    return found;
}

1.1. 如果只有一个写者,那么写者是不需要使用锁进行保护的,添加、更新、删除的操作实现方法如下:

(1) 写者添加一个节点到链表尾部

void test_add_node(test_entry *entry)
{
    list_add_tail_rcu(&entry->link, &test_head);
}

(2) 写者更新一个节点

更新的过程是:首先把旧的节点复制更新,然后使用新节点替换旧节点,最后使用函数 call_rcu() 注册回调函数,延后释放旧节点。

void test_update_node(int key, int new_val)
{
    test_entry *entry, *new_entry;
    int ret = -ENOENT;

    list_for_each_entry(entry, &test_head, link) {
        if (entry->key == key) {
            new_entry = kmalloc(sizeof(test_entry), GFP_ATOMIC);
            if (new_entry == NULL) {
                ret = -ENOMEM;
                break;
            }

            *new_entry = *entry;
            new_entry->val = new_val;
            list_replace_rcu(&entry->link, &new_entry->link);
            call_rcu(&entry->rcu, test_free_node);
            ret = 0;
            break;
        }
    }

    return ret;
}

void test_free_node(struct rcu_head *head)
{
    test_entry *entry = container_of(head, test_entry, rcu);
    kfree(entry);
}

(3) 写者删除一个节点

第一种方法:首先将节点从链表中删除,然后使用函数 call_rcu() 注册回调函数延后释放节点。

int test_del_node(int key)
{
    test_entry *entry;
    int found = 0;

    list_for_each_entry(entry, &test_head, link) {
        if (entry->key == key) {
            list_del_rcu(&entry->link);
            call_rcu(&entry->rcu, test_free_node); //不会休眠
            found = 1;
            break;
        }
    }

    return found;
}

第二种方法:首先把节点从链表中删除,然后使用 synchronize_rcu() 等待宽限期结束,最后释放节点。

int test_del_node(int key)
{
    test_entry *entry;
    int found = 0;

    list_for_each_entry(entry, &test_head, link) {
        if (entry->key == key) {
            list_del_rcu(&entry->link);
            synchronize_rcu(); //会休眠
            kfree(entry);
            found = 1;
            break;
        }
    }

    return found;
}

 

1.2. 如果有多个写者,那么写者之间必须使用锁互斥,添加、更新、删除的操作实现方法如下:

(1) 写者添加一个节点到链表尾部,假设使用 spin_lock 保护链表,视情况也可以使用其它互斥锁。

void test_add_node(test_entry *entry)
{
    spin_lock(&test_lock); //struct spinlock test_lock;
    list_add_tail_rcu(&entry->link, &test_head);
    spin_unlock(&test_lock);
}

(2) 写者更新一个节点

void test_update_node(int key, int new_val)
{
    test_entry *entry, *new_entry;
    int ret = -ENOENT;

    spin_lock(&test_lock);
    list_for_each_entry(entry, &test_head, link) {
        if (entry->key == key) {
            new_entry = kmalloc(sizeof(test_entry), GFP_ATOMIC);
            if (new_entry == NULL) {
                ret = -ENOMEM;
                break;
            }

            *new_entry = *entry;
            new_entry->val = new_val;
            list_replace_rcu(&entry->link, &new_entry->link);
            call_rcu(&entry->rcu, test_free_node);
            ret = 0;
            break;
        }
    }
    spin_unlock(&test_lock);

    return ret;
}

(3) 写者删除一个节点

int test_del_node(int key)
{
    test_entry *entry;
    int found = 0;

    spin_lock(&test_lock);
    list_for_each_entry(entry, &test_head, link) {
        if (entry->key == key) {
            list_del_rcu(&entry->link);
            call_rcu(&entry->rcu, test_free_node); //不会休眠
            found = 1;
            break;
        }
    }
    spin_unlock(&test_lock);

    return found;
}

使用 spin_lock 进行保护,释放就不能使用会导致睡眠的同步等待宽限期结束的 synchronize_rcu() 函数了。

 

二、加速RCU

TODO


三、可抢占RCU

TODO


四、可休眠RCU

TODO

 

标签:55,RCU,汇总,new,int,key,rcu,test,entry
From: https://www.cnblogs.com/hellokitty2/p/17360230.html

相关文章

  • RCU-3——经典(可抢占)RCU代码分析
    基于Linux-5.10一、相关数据结构1.structrcu_statercu_state用于描述RCU全局状态。structrcu_state{structrcu_nodenode[NUM_RCU_NODES];/*Hierarchy.*/structrcu_node*level[RCU_NUM_LVLS+1];/*Hierarchylevels(+1toshutbogusgccwarning)......
  • RCU-4——不可抢占RCU代码分析
    基于Linux-5.10一、不可抢占RCU1.不可抢占RCU不允许进程在读端临界区被其它进程抢占,使用函数rcu_read_lock_sched()/rcu_read_unlock_sched()标记读临界区。前者禁止内核抢占,后者开启内核抢占。staticinlinevoidrcu_read_lock_sched(void)//include/linux/rcupdate.h......
  • RCU-2——RCU初探
    一、RCU简介RCU(Read-Copy-Update)的意思是读-复制-更新,是根据原理命名的。写者修改对象的逻辑是:首先复制一个副本,然后更新这个副本,最后使用新的对象替换旧的对象。在写者执行复制更新的时候读者可以读数据。写者删除对象,必须要等到所有读者结束访问,才能执行销毁操作。RCU的关......
  • 55. 跳跃游戏
    给定一个非负整数数组nums,你最初位于数组的第一个下标。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标。>贪心解法classSolution{public:boolcanJump(vector<int>&nums){intcover=0;if(nums.size......
  • Python12类内置函数大汇总
    内置函数就是python给你提供的,拿来直接用的函数,比如print.,input等。截止到python版本3.6.2python一共提供了68个内置函数,我将它们分成12类,方便你学习。#68个内置函数abs()dict()help()min()setattr()all()dir()hex()next()slice()any()......
  • 55. 跳跃游戏
    55.跳跃游戏开始想暴力递归,超时classSolution{public:boolcanJump(vector<int>&nums){//一步一步走,如果跳着没有走的快,肯定过不去//k是跳着走能够到达的最远的地方intk=0;for(inti=0;i<nums.size();i++){......
  • 汇总|React Native 开发工具一赏
    传统的开发中,按照平台划分为iOS,Android,Windows和Mac。其中,随着移动设备的使用移动端应用的开发也越来越多。传统上iOS应用使用Xcode工具、Objective-C和Swift语言进行开发,Android应用使用AndroidStudio工具、Java和kotlin语言进行开发。随着开发的普及......
  • H3C S5560S 修改VLAN Address
    <SW1>sysSystemView:returntoUserViewwithCtrl+Z.[SW1]discu#version7.1.070,Release6126P20#sysnameSW1#interfaceVlan-interface1ipaddress192.168.3.51255.255.255.0<SW1>undo ipaddress192.168.3.51#Restorethedefaultsetting......
  • mybatis与jstl异常汇总
    1,roblemaccessing/moviePlay/goMoviePlay/1/1/1.Reason:  /WEB-INF/views/workdetail.jsp(92,15)PWC6031:Unterminated<c:settagCausedby:org.apache.jasper.JasperException:/WEB-INF/views/workdetail.jsp(92,15)PWC6031:Unt......
  • 数据挖掘算法汇总
    参考:http://wenku.baidu.com/view/c79058d480eb6294dd886c8c.html     http://www.doc88.com/p-7344376788072.html......