C语言 Nesting of rcu_read_locks



我将一个受RCU保护的指针存储在一个受RCU保护的哈希表MyHashMyStruct *中。通过哈希表读取/更新MyStruct时,我如下所示。

rcu_read_lock() /* For hashtable 'MyHash' */
hash_for_each_possible_rcu(MyHash, obj, member, key)
{
rcu_read_lock(); /* For RCU protected data(MyStruct*) stored in hashtable */
Mystruct* s = rcu_dereference_pointer(obj->s);
if(s) 
{
s->read++;
}
rcu_read_unlock(); /* For RCU protected data(MyStruct*) stored in hashtable */
}
rcu_read_unlock() /* For hashtable 'MyHash'*/

请注意,MyStruct本身是另一个RCU保护列表的一部分(即它是另一个列表的RCU保护节点(,该列表存储在MyHash中以便更快地查找。

据我了解,rcu_read_lock需要确保在所有读取端关键部分完成之前,任何编写器更新都不会释放内存。那么,真的有必要嵌套rcu_read_lock还是仅仅拥有外部rcu_read_lock/rcu_read_unlock就足够了?

IOW,由于 RCU 锁不绑定到任何单个对象,因此在同时访问多个 RCU 保护对象时,我们真的需要嵌套的 rcu 锁吗?

不,嵌套rcu_read_lock()不是必需的。

与其他"嵌套"关键部分类似,嵌套rcu_read_lock的唯一影响是锁定级别的增量。也就是说,进一步的rcu_read_unlock不会立即结束关键部分,而只是将锁定级别恢复回原位。

但是,支持嵌套锁定被视为 RCU 锁定机制的一个优点。在支持嵌套操作后,可以独立于其他组件开发组件。

例如,您可能object_increment函数,可以在没有RCU锁定的情况下安全地调用:

void object_increment(Object obj)
{
rcu_read_lock();
Mystruct* s = obj->s;
if(s) 
{
s->read++;
}
rcu_read_unlock();
}

然后在 RCU 锁定下调用此函数:

rcu_read_lock(); /* For hashtable 'MyHash' */
hash_for_each_possible_rcu(MyHash, obj, member, key)
{
// It is perfectly valid to use the function even with RCU lock already taken
object_increment(obj);
}
rcu_read_unlock(); /* For hashtable 'MyHash'*/

简单的设计几乎总是超过嵌套调用对rcu_read_lock的小性能影响。


如果不允许嵌套调用,则需要实现另一个组件的功能才能使用 RCU 锁进行访问:

void object_increment_locked(Object obj)
{
Mystruct* s = obj->s;
if(s) 
{
s->read++;
}
}

并仔细选择在特定情况下使用哪种功能 - 锁定或非锁定:

rcu_read_lock(); /* For hashtable 'MyHash' */
hash_for_each_possible_rcu(MyHash, obj, member, key)
{
// Already have a lock taken, so use _locked version of the function.
object_increment_locked(obj);
}
rcu_read_unlock(); /* For hashtable 'MyHash'*/

相关内容

  • 没有找到相关文章

最新更新