rcu的学习记录
crash> p rcu_sched_state.node[0]
$13 = {
lock = {
raw_lock = {
slock = 748760225
}
},
gpnum = 21141468,
completed = 21141467,
qsmask = 1,
expmask = 0,
wakemask = {
counter = 0
},
qsmaskinit = 1,
grpmask = 0,
grplo = 0,
grphi = 4095,
grpnum = 0 '\000',
level = 0 '\000',---------------来自灵魂的拷问,你的level编号,root是0级
parent = 0x0,
blkd_tasks = {
next = 0xffffffff81a28e58,
prev = 0xffffffff81a28e58
},
gp_tasks = 0x0,
exp_tasks = 0x0,
node_kthread_task = 0x0,
node_kthread_status = 0
}
crash> p rcu_sched_state.node[1]
$14 = {
lock = {
raw_lock = {
slock = 2634718474
}
},
gpnum = 21141468,
completed = 21141467,
qsmask = 1073741823,
expmask = 0,
wakemask = {
counter = 0
},
qsmaskinit = 4294967295,
grpmask = 1,-------------常量
grplo = 0,
grphi = 63,
grpnum = 0 '\000',
level = 1 '\001',
parent = 0xffffffff81a28e00,------这个就是node[0]的地址
blkd_tasks = {
next = 0xffffffff81a28f58,
prev = 0xffffffff81a28f58
},
gp_tasks = 0x0,
exp_tasks = 0x0,
node_kthread_task = 0x0,
node_kthread_status = 0
}
crash> p &rcu_sched_state.node[0]
$15 = (struct rcu_node *) 0xffffffff81a28e00
4还会记录gp的历史最大值,即gp_max,
p rcu_sched_state
rcu_sched_state = $22 = {
struct rcu_node node[65]-----省略
level = {0xffffffff81a28e00, 0xffffffff81a28f00},
levelcnt = {1, 64, 4096, 0, 0},
levelspread = "@@",
rda = 0xce00,
signaled = 2 '\002',
fqs_active = 0 '\000',
fqs_need_gp = 0 '\000',
boost = 0 '\000',
gpnum = 21141468,
completed = 21141467,
onofflock = {
raw_lock = {
slock = 2569574696
}
},
fqslock = {
raw_lock = {
slock = 659040072
}
},
jiffies_force_qs = 4447515504,
n_force_qs = 36185678,
n_force_qs_lh = 219254,
n_force_qs_ngp = 7,
gp_start = 4447515501,
jiffies_stall = 4447530501,
gp_max = 54,
name = 0xffffffff8178a4e7 "rcu_sched_state"
}
/*
* Dynticks per-CPU state.
*/
struct rcu_dynticks {
int dynticks_nesting; /* Track irq/process nesting level. */
int dynticks_nmi_nesting; /* Track NMI nesting level. */
atomic_t dynticks; /* 偶数代表处于dyntick-idle*/
};
crash> rcu_sched_data
PER-CPU DATA TYPE:
struct rcu_data rcu_sched_data;
PER-CPU ADDRESSES:
[0]: ffff88207fc0ce00
[1]: ffff88207fc2ce00
[2]: ffff88207fc4ce00
[3]: ffff88207fc6ce00
[4]: ffff88207fc8ce00
[5]: ffff88207fcace00
[6]: ffff88207fccce00
[7]: ffff88207fcece00
[8]: ffff88407fc0ce00
[9]: ffff88407fc2ce00
[10]: ffff88407fc4ce00
[11]: ffff88407fc6ce00
[12]: ffff88407fc8ce00
[13]: ffff88407fcace00
[14]: ffff88407fccce00
[15]: ffff88407fcece00
[16]: ffff88207fd0ce00
[17]: ffff88207fd2ce00
[18]: ffff88207fd4ce00
[19]: ffff88207fd6ce00
[20]: ffff88207fd8ce00
[21]: ffff88207fdace00
[22]: ffff88207fdcce00
[23]: ffff88207fdece00
[24]: ffff88407fd0ce00
[25]: ffff88407fd2ce00
[26]: ffff88407fd4ce00
[27]: ffff88407fd6ce00
[28]: ffff88407fd8ce00
[29]: ffff88407fdace00
[30]: ffff88407fdcce00
[31]: ffff88407fdece00
crash> rcu_data ffff88407fd0ce00
struct rcu_data {
completed = 21141467,
gpnum = 21141468,
passed_quiesc_completed = 21141466,
passed_quiesc = false,
qs_pending = true,
beenonline = true,
preemptible = false,
mynode = 0xffffffff81a28f00,
grpmask = 16777216,
nxtlist = 0xffff8831017b1280,
nxttail = {0xffff88407fd0ce30, 0xffff88407fd0ce30, 0xffff88055065ab48, 0xffff88055065ab48},
qlen = 0,
qlen_last_fqs_check = 0,
n_cbs_invoked = 292196490,
n_cbs_orphaned = 0,
n_cbs_adopted = 0,
n_force_qs_snap = 0,
blimit = 10,
dynticks = 0xffff88407fd0cde0,
dynticks_snap = 834727793,
dynticks_fqs = 1555945,
offline_fqs = 0,
resched_ipi = 1016,
n_rcu_pending = 130520066,
n_rp_qs_pending = 24570,
n_rp_report_qs = 19693251,
n_rp_cb_ready = 8253,
n_rp_cpu_needs_gp = 270805,
n_rp_gp_completed = 19229197,
n_rp_gp_started = 124913,
n_rp_need_fqs = 16071,
n_rp_need_nothing = 91177576,
cpu = 24
}
crash> struct rcu_dynticks 0xffff88407fd0cde0
struct rcu_dynticks {
dynticks_nesting = 2,
dynticks_nmi_nesting = 0,
dynticks = {
counter = 834728091--------奇数
}
}
对于level的个数和node的个数:
crash> !grep CONFIG_RCU_FANOUT /boot/config-3.0.101-0.47.90-default
CONFIG_RCU_FANOUT=64
CONFIG_RCU_FANOUT_LEAF没有设置,则走代码默认设置
在给定由RCU_FANOUT 和RCU_FANOUT_LEAF指定的扇出的情况下,第21-24行分别计算单级(包含单个rcu_node结构),两级,三级和四级rcu_node树支持的最大CPU数量。这些数量的CPU分别保留在RCU_FANOUT_1, RCU_FANOUT_2, RCU_FANOUT_3和 RCU_FANOUT_4 C预处理器变量中。
心得:
在rcu的回调中,一般是引用计数为0再挂rcu,然后在执行rcu的时候,用bugon判断一下计数。
static void release_tgcred(struct cred *cred)
{
#ifdef CONFIG_KEYS
struct thread_group_cred *tgcred = cred->tgcred; if (atomic_dec_and_test(&tgcred->usage))
call_rcu(&tgcred->rcu, release_tgcred_rcu);
#endif
}
如上,可以见到 atomic_dec_and_test ,这通过将引用计数-1然后和0比较,如果相等,则返回1,否则返回0,那么其实就是原子判断引用计数是否为1,
然后在rcu的回调中,通过BUG_ON的方式,确定是可以释放的,这样可以保证资源释放的时候,不会有其他的人在用这块内存了。这是一个好的编码习惯,减少了内存踩来踩去
的风险。
static void release_tgcred_rcu(struct rcu_head *rcu)
{
struct thread_group_cred *tgcred =
container_of(rcu, struct thread_group_cred, rcu); BUG_ON(atomic_read(&tgcred->usage) != 0); key_put(tgcred->session_keyring);
key_put(tgcred->process_keyring);
kfree(tgcred);
}
rcu的嵌套问题,后面补充。
rcu的学习记录的更多相关文章
- Quartz 学习记录1
原因 公司有一些批量定时任务可能需要在夜间执行,用的是quartz和spring batch两个框架.quartz是个定时任务框架,spring batch是个批处理框架. 虽然我自己的小玩意儿平时不 ...
- Java 静态内部类与非静态内部类 学习记录.
目的 为什么会有这篇文章呢,是因为我在学习各种框架的时候发现很多框架都用到了这些内部类的小技巧,虽然我平时写代码的时候基本不用,但是看别人代码的话至少要了解基本知识吧,另外到底内部类应该应用在哪些场合 ...
- Apache Shiro 学习记录4
今天看了教程的第三章...是关于授权的......和以前一样.....自己也研究了下....我觉得看那篇教程怎么说呢.....总体上是为数不多的精品教程了吧....但是有些地方确实是讲的太少了.... ...
- UWP学习记录12-应用到应用的通信
UWP学习记录12-应用到应用的通信 1.应用间通信 “共享”合约是用户可以在应用之间快速交换数据的一种方式. 例如,用户可能希望使用社交网络应用与其好友共享网页,或者将链接保存在笔记应用中以供日后参 ...
- UWP学习记录11-设计和UI
UWP学习记录11-设计和UI 1.输入和设备 通用 Windows 平台 (UWP) 中的用户交互组合了输入和输出源(例如鼠标.键盘.笔.触摸.触摸板.语音.Cortana.控制器.手势.注视等)以 ...
- UWP学习记录10-设计和UI之控件和模式7
UWP学习记录10-设计和UI之控件和模式7 1.导航控件 Hub,中心控件,利用它你可以将应用内容整理到不同但又相关的区域或类别中. 中心的各个区域可按首选顺序遍历,并且可用作更具体体验的起始点. ...
- UWP学习记录9-设计和UI之控件和模式6
UWP学习记录9-设计和UI之控件和模式6 1.图形和墨迹 InkCanvas是接收和显示墨迹笔划的控件,是新增的比较复杂的控件,这里先不深入. 而形状(Shape)则是可以显示的各种保留模式图形对象 ...
- UWP学习记录8-设计和UI之控件和模式5
UWP学习记录8-设计和UI之控件和模式5 1.日历.日期和时间控件 日期和时间控件提供了标准的本地化方法,可供用户在应用中查看并设置日期和时间值. 有四个日期和时间控件可供选择,选择的依据如下: 日 ...
- UWP学习记录7-设计和UI之控件和模式4
UWP学习记录7-设计和UI之控件和模式4 1.翻转视图 使用翻转视图浏览集合中的图像或其他项目(例如相册中的照片或产品详细信息页中的项目),一次显示一个项目. 对于触摸设备,轻扫某个项将在整个集合中 ...
随机推荐
- App上看到就忍不住点的小红点是如何实现的?
你有没有发现,我们解锁手机后桌面上App右上角总能看到一个小红点,这就是推送角标.推送角标指的是移动设备上App图标右上角的红色圆圈,圆圈内的白色数字表示未读消息数量.角标是一种比较轻的提醒方式,通过 ...
- while循环结构
一.循环: 1.场景: ①.用户名和密码,反复输入 ②.计算1-100之间 ③.游戏,重生 ④.-- 2.方式 ①.while ②.for 3.while格式 while 条件:要循环执行的代码 布尔 ...
- flink-执行模式
flink的执行模式 flink既能处理离线数据,也能处理实时数据,在1.12.0版本以前,批数据返回的数据集合是dataSet,对应一套dataSet的api,从1.12.0版本以后,flink实现 ...
- 第六章、PXE高效网络装机、Kickstart无人值守安装
目录 一.部署PXE远程安装服务 1PXE定义 2PXE服务优点 3搭建网络体系前提条件 4PXE实现过程讲解 二.搭建PXE远程安装服务器 三.Kickstart无人值守安装 一.部署PXE远程安装 ...
- Node.js精进(3)——流
在 JavaScript 中,一般只处理字符串层面的数据,但是在 Node.js 中,需要处理网络.文件等二进制数据. 由此,引入了Buffer和Stream的概念,两者都是字节层面的操作. Buff ...
- opencv-python获取视频信息
代码 import cv2 if __name__ == '__main__': # 读取视频 capture = cv2.VideoCapture('./videos/person.mp4') # ...
- nifi从入门到实战(保姆级教程)——环境篇
背景: 公司领导决定将各种基础数据的导入从代码中分离出来,用Apache Nifi替换.使开发者们更关注在业务上,而不用关心基础的由来. Apache Nifi对于整个团队都是一个全新的工具,之前大家 ...
- Python教程——常用的os操作详情
Python自动的os库是和操作系统交互的库,常用的操作包括文件/目录操作,路径操作,环境变量操作和执行系统命令等. 文件/目录操作 获取当前目录(pwd): os.getcwd() 切换目录(cd) ...
- React key究竟有什么作用?深入源码不背概念,五个问题刷新你对于key的认知
壹 ❀ 引 我在[react]什么是fiber?fiber解决了什么问题?从源码角度深入了解fiber运行机制与diff执行一文中介绍了react对于fiber处理的协调与提交两个阶段,而在介绍协调时 ...
- CentOS查看操作系统安装时间信息:
CentOS查看系统安装时间信息: 方法1:[root@logserver ~]# ll /boot/|egrep -i "(grub|lost\+found)" 方法2:[ro ...