我应该如何混合RCU阅读器和更新程序代码?

时间:2015-08-13 17:55:01

标签: linux linux-kernel rcu

我有一个样板函数,可以在树状数据库中找到一个结构:

struct foo {
    struct foo *child1; /* RCU-protected. */
    struct foo *child2; /* RCU-protected. */

    ... /* Other stuff */
}

static struct foo *find_foo(int arg)
{
    struct foo *parent;
    ... /* Do something to find parent. */
    return rcu_dereference(parent->child1); /* or child2. Whatever. */
}

然后我有几个函数可以解决这个问题:

void a(int arg)
{
    struct foo *bar;
    rcu_read_lock();
    bar = find_foo(arg);
    ... /* Read something from bar and do something with it. */
    rcu_read_unlock();
}

然后我有一个更新器/取料器。它需要像“a”函数一样找到对象(假设它已经从外部进行了互斥):

void c(int arg)
{
    struct foo *bar;

    bar = find_foo(arg);

    ... /* make a backup pointer of bar->child1. */

    rcu_assign_pointer(bar->child1, ...);

    ... /* free the old child or whatever. */
}

我的问题是,rcu_dereference()的文档说它必须在读取方的关键部分(即rcu_read_lock()rcu_read_unlock()之间)进行调用。 c()通过调用find_foo()违反此规则。

我犹豫是否制作了使用rcu_dereference_protected()代替find_foo()的{​​{1}}的全新版本,因为它的代码太重了,所以我想知道这个实现是否rcu_dereference()是合法的:

c()

如果这不合法,我应该如何混合使用读者和更新程序代码?

1 个答案:

答案 0 :(得分:1)

实际上, if *something involving sys.argv[1]*: print line 的第一个变体是正确的(在更新程序方面不需要特定的解引用),但它会使rcu检查器混淆(检查器期望在{{1}下发生c() })。

即使从rcu检查器的角度来看,rcu_dereference的第二个变体也是正确的,但不需要rcu_readc()已经是rcu_dereference_protected的结果。

让rcu checker高兴的另一种方法是使用

bar

而不是

rcu_dereference

rcu_dereference_check(<pointer>, <condition-when-in-updater>) 内实施。所以检查员不会在rcu_dereference(<pointer>) 部分之外的foo()调用上投诉,直到它可以证明在这种情况下条件是foo

通过此rcu_read实施,false的第一个变体就可以了。