*/ static inline void list_add_rcu(struct list_head *new, struct list_head *head) { __list_add_rcu(new, head, head->next); } 源码路径 : linux-5.6.18\include\linux\rculist.h#105 二、RCU 模式下删除链表项 list_del_rcu 函数 在Linux 源码 linux-5.6.18\include\linux\rculist.h 头...
2. qsmask:这个位图掩码跟踪哪些CPU(rcu_node 叶子节点)或者CPU组(rcu_node 非叶子节点)仍然需要经历一个静止状态,以结束当前优雅周期。 3. qsmaskinit:这个位图掩码跟踪哪些CPU (rcu_node 叶子节点)或者CPU组(rcu_node 非叶子节点)仍然需要经历一个静止状态,以结束后续的优雅周期。CPU热插拔代码维护qsmaskinit ...
staticinlinevoidlist_del_rcu(structlist_head*entry) 1. 函数, 就是 从 链表中 删除元素 的 函数 ; list_del_rcu 函数中 , 主要是调用了 __list_del_entry 函数 , 在__list_del_entry 函数中 , 又调用了 __list_del 函数 ; ...
hlist_nulls_add_head_rcu/hlist_nulls_del_rcu 以上的这些接口可以同时和同版本的for_each遍历同时进行而不会出现并发问题!也就是说,在保证不会同时add和del的前提下,可以实现无锁遍历。 有了上面的理解,我们再看看del操作的流程: 和add操作一样,这也是个实实在在的RCU操作,其核心在于最后更新! 关于rcu,我们...
__list_add_rcu(new, head->prev,head); } 3. 从双向链表删除项目: 3.1:基本删除函数: static inline void __list_del(structlist_head * prev, struct list_head * next) { next->prev = prev; prev->next = next; }//只是将前一个和后一个互指 ...
本文从最基本的内核链表出发,引出初始化INIT_LIST_HEAD函数,然后介绍list_add,通过改变链表位置的问题引出list_for_each函数,然后为了获取容器结构地址,引出offsetof和container_of宏,并对内核链表设计原因作出了解释,一步步引导到list_for_each_entry,然后介绍list_del函数,通过在遍历时list_del链表的不安全行为,引出li...
源码路径 : linux-5.6.18\include\linux\rculist.h#198 二、链表操作时使用 smp_wmb() 函数保证代码执行顺序编译器 和CPU 优化 代码时 , 有时会将 代码执行顺序改变 , 在链表操作时 , 代码的执行顺序必须得到保证 , 否则会得到不可预知的结果 ; 使用smp_wmb() 函数 , 可以保证该函数 前两行 的代码 ...
static inline void list_del_rcu(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->prev = LIST_POISON2; //仅仅设置前一个指针 } /** * list_replace - replace old entry by new one * list_replace - 使用新的条目替换旧的条目 ...
尽管这里使用2.6内核作为讲解的基础,但实际上2.4内核中的链表结构和2.6并没有什么区别。不同之处在于2.6扩充了两种链表数据结构:链表的读拷贝更新(rcu)和HASH链表(hlist)。这两种扩展都是基于最基本的list结构,因此,本文主要介绍基本链表结构,然后再简要介绍一下rcu和hlist。
list_del_rcu(&mod->list); module_bug_cleanup(mod); wake_up_all(&module_wq); ddebug: dynamic_debug_remove(info->debug); unlock: mutex_unlock(&module_mutex); ddebug_cleanup: dynamic_debug_remove(info->debug); synchronize_sched(); kfree(mod->args); ...