我将RCU保护的指针MyStruct *存储在RCU保护的哈希表MyHash中。当通过散列表读取/更新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锁吗?
发布于 2019-11-26 14:49:46
不,嵌套rcu_read_lock()是不需要的。
与其他“嵌套”关键部分类似,嵌套rcu_read_lock的唯一效果是增加锁级别。也就是说,进一步说,rcu_read_unlock不会立即结束关键部分,而只是将锁级别恢复回来。
但是,支持嵌套锁定被视为RCU锁定机制的advantage。支持嵌套操作之后,可以独立地开发组件,一个独立于其他组件。
例如,您可能有不需要RCU锁就可以安全调用的object_increment函数:
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'*/https://stackoverflow.com/questions/59043242
复制相似问题