我应该如何混合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()而不是rcu_dereference()制作一个全新版本的find_foo(),因为它有太多重复的代码,所以我想知道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. */
}

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

实际上,c()的第一个变体是正确的(不需要在更新端进行特定的解引用),但是它使rcu检查器感到困惑(检查器期望rcu_dereference出现在rcu_read section下)。

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

另一种让rcu检查器高兴的方法是使用
rcu_dereference_check(<pointer>, <condition-when-in-updater>)
不是

rcu_dereference(<pointer>)

内部foo实现。因此,检查器不会报错foo()在rcu_read部分之外的调用,直到它可以证明在这种情况下条件是false

对于这样的foo()实现,c()的第一个变体是OK的。

相关内容

  • 没有找到相关文章

最新更新