1

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

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()

我很犹豫要不要制作一个全新的版本,find_foo()它使用rcu_dereference_protected()而不是rcu_dereference(),因为它有太多重复的代码,所以我想知道这个实现c()是否合法:

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

    rcu_read_lock();
    bar = find_foo(arg);
    bar = rcu_dereference_protected(bar, ...); /* THIS. */
    rcu_read_unlock();

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

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

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

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

4

1 回答 1

1

实际上, 的第一个变体c()是正确的(更新程序端不需要特定的取消引用),但它使 rcu 检查器感到困惑(检查器期望rcu_dereference发生在rcu_readsection 下)。

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

让 rcu checker 开心的另一种方法是使用

rcu_dereference_check(<pointer>, <condition-when-in-updater>)

代替

rcu_dereference(<pointer>)

内部foo执行。所以检查器不会在rcu_read节外的 foo() 调用上抱怨,直到它可以证明条件是false在这种情况下。

有了这样foo()的实现,第一个变体c()就可以了。

于 2015-08-13T22:25:51.657 回答