Linux-rt下卡死之hrtimer分析

news2025/1/28 1:07:11

Linux-rt下卡死之hrtimer分析

日志

在这里插入图片描述

超时读过程分析

#define readl_poll_timeout(addr, val, cond, delay_us, timeout_us) \
 	  	readx_poll_timeout(readl, addr, val, cond, delay_us, timeout_us)
 	  	
34  #define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us)	\
35  ({ \
36  	u64 __timeout_us = (timeout_us); \
37  	unsigned long __sleep_us = (sleep_us); \
38  	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
39  	might_sleep_if((__sleep_us) != 0); \
40  	for (;;) { \
41  		(val) = op(addr); \
42  		if (cond) \
43  			break; \
44  		if (__timeout_us && \
45  		    ktime_compare(ktime_get(), __timeout) > 0) { \
46  			(val) = op(addr); \
47  			break; \
48  		} \
49  		if (__sleep_us) \
50  			usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
51  	} \
52  	(cond) ? 0 : -ETIMEDOUT; \
53  })

2375  void __sched usleep_range(unsigned long min, unsigned long max)
2376  {
2377  	ktime_t exp = ktime_add_us(ktime_get(), min);
2378  	u64 delta = (u64)(max - min) * NSEC_PER_USEC;
2379  
2380  	for (;;) {
2381  		__set_current_state(TASK_UNINTERRUPTIBLE);			 //设置当前进程为不可中断状态
2382  		/* Do not return before the requested sleep time has elapsed */
2383  		if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS)) //注意这个hrtimer_mode 在rt-linux中有很大用处
2384  			break;
2385  	}
2386  }
2387  EXPORT_SYMBOL(usleep_range);

2172  int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta, const enum hrtimer_mode mode)
2174  {
2175  	return schedule_hrtimeout_range_clock(expires, delta, mode,  CLOCK_MONOTONIC);	//CLOCK_MONOTONIC:clock_id
2177  }
2178  EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);

2275  int __sched
2276  schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
2277  			       const enum hrtimer_mode mode, clockid_t clock_id)
2278  {
2279  	struct hrtimer_sleeper t;
2280  
2281  	/*
2282  	 * Optimize when a zero timeout value is given. It does not
2283  	 * matter whether this is an absolute or a relative time.
2284  	 */
2285  	if (expires && *expires == 0) {
2286  		__set_current_state(TASK_RUNNING);
2287  		return 0;
2288  	}
2289  
2290  	/*
2291  	 * A NULL parameter means "infinite"
2292  	 */
2293  	if (!expires) {
2294  		schedule();
2295  		return -EINTR;
2296  	}
		//	实时任务,设置延迟时间为0,时间更精确 
2302  	if (rt_task(current))
2303  		delta = 0;
2304  
2305  	hrtimer_init_sleeper_on_stack(&t, clock_id, mode);
2306  	hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
2307  	hrtimer_sleeper_start_expires(&t, mode);
2308  
2309  	if (likely(t.task))
2310  		schedule();
2311  
2312  	hrtimer_cancel(&t.timer);
2313  	destroy_hrtimer_on_stack(&t.timer);
2314  
2315  	__set_current_state(TASK_RUNNING);
2316  
2317  	return !t.task ? 0 : -EINTR;
2318  }
2319  EXPORT_SYMBOL_GPL(schedule_hrtimeout_range_clock);

hrtimer定时器分析

1、定义struct hrtimer_sleeper t;
135  struct hrtimer_sleeper {
136  	struct hrtimer timer;
137  	struct task_struct *task;
138  };
38  enum hrtimer_mode {
39  	HRTIMER_MODE_ABS	= 0x00,
40  	HRTIMER_MODE_REL	= 0x01,
41  	HRTIMER_MODE_PINNED	= 0x02,
42  	HRTIMER_MODE_SOFT	= 0x04,
43  	HRTIMER_MODE_HARD	= 0x08,

2hrtimer_init_sleeper_on_stack(&t, clock_id, mode);
443  void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl,
444  				   clockid_t clock_id, enum hrtimer_mode mode)
445  {
446  	debug_object_init_on_stack(&sl->timer, &hrtimer_debug_descr);
447  	__hrtimer_init_sleeper(sl, clock_id, mode);
448  }
449  EXPORT_SYMBOL_GPL(hrtimer_init_sleeper_on_stack);


1799  static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
1800  				   clockid_t clock_id, enum hrtimer_mode mode)
1801  {
1821  	if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
1822  		if (task_is_realtime(current) && !(mode & HRTIMER_MODE_SOFT))
1823  			mode |= HRTIMER_MODE_HARD;			//根据上边的分析,此处会设置为硬中断上下文进行回调
1824  	}
1825  
1826  	__hrtimer_init(&sl->timer, clock_id, mode);	//初始化hrtimer
1827  	sl->timer.function = hrtimer_wakeup;		//唤醒函数
1828  	sl->task = current;							//当前进程
1829  }

1376  static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
1377  			   enum hrtimer_mode mode)
1378  {
1379  	bool softtimer = !!(mode & HRTIMER_MODE_SOFT);		//由上可知此处为false
1380  	struct hrtimer_cpu_base *cpu_base;
1381  	int base;

1389  	if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(mode & HRTIMER_MODE_HARD))
1390  		softtimer = true;
1391  
1392  	memset(timer, 0, sizeof(struct hrtimer));
1393  
1394  	cpu_base = raw_cpu_ptr(&hrtimer_bases);
1395  

1401  	if (clock_id == CLOCK_REALTIME && mode & HRTIMER_MODE_REL)
1402  		clock_id = CLOCK_MONOTONIC;
1403  
1404  	base = softtimer ? HRTIMER_MAX_CLOCK_BASES / 2 : 0;
1405  	base += hrtimer_clockid_to_base(clock_id);
1406  	timer->is_soft = softtimer;							//false
1407  	timer->is_hard = !softtimer;						//true
1408  	timer->base = &cpu_base->clock_base[base];
1409  	timerqueue_init(&timer->node);						//加入定时队列
1410  }

3hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
251  static inline void hrtimer_set_expires_range_ns(struct hrtimer *timer, ktime_t time, u64 delta)
252  {
253  	timer->_softexpires = time;		//软超时时间
254  	timer->node.expires = ktime_add_safe(time, ns_to_ktime(delta)); //超时范围
255  }

4hrtimer_sleeper_start_expires(&t, mode);
1782  void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl,
1783  				   enum hrtimer_mode mode)
1784  {
1792  	if (IS_ENABLED(CONFIG_PREEMPT_RT) && sl->timer.is_hard)
1793  		mode |= HRTIMER_MODE_HARD;
1794  
1795  	hrtimer_start_expires(&sl->timer, mode);
1796  }
1797  EXPORT_SYMBOL_GPL(hrtimer_sleeper_start_expires);

426  static inline void hrtimer_start_expires(struct hrtimer *timer,
427  					 enum hrtimer_mode mode)
428  {
429  	u64 delta;
430  	ktime_t soft, hard;
431  	soft = hrtimer_get_softexpires(timer);
432  	hard = hrtimer_get_expires(timer);
433  	delta = ktime_to_ns(ktime_sub(hard, soft));
434  	hrtimer_start_range_ns(timer, soft, delta, mode);
435  }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2282979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PHP防伪溯源一体化管理系统小程序

🔍 防伪溯源一体化管理系统,品质之光,根源之锁 🚀 引领防伪技术革命,重塑品牌信任基石 我们自豪地站在防伪技术的前沿,为您呈现基于ThinkPHP和Uniapp精心锻造的多平台(微信小程序、H5网页&…

WPF2-在xaml为对象的属性赋值

1. AttributeValue方式 1.1. 简单属性赋值1.2. 对象属性赋值 2. 属性标签的方式给属性赋值3. 标签扩展 (Markup Extensions) 3.1. StaticResource3.2. Binding 3.2.1. 普通 Binding3.2.2. ElementName Binding3.2.3. RelativeSource Binding3.2.4. StaticResource Binding (带参…

uart iic spi三种总线的用法

1、uart串口通信 这种连接方式抗干扰能力弱,旁边有干扰源就会对收发的电平数据造成干扰,进而导致数据失真 这种连接方式一般适用于一块板子上面的两个芯片之间进行数据传输 ,属于异步全双工模式。 1.空闲位:当不进行数据收发时&am…

Java 高级工程师面试高频题:JVM+Redis+ 并发 + 算法 + 框架

前言 在过 2 个月即将进入 3 月了,然而面对今年的大环境而言,跳槽成功的难度比往年高了很多,很明显的感受就是:对于今年的 java 开发朋友跳槽面试,无论一面还是二面,都开始考验一个 Java 程序员的技术功底…

【图文详解】lnmp架构搭建Discuz论坛

安装部署LNMP 系统及软件版本信息 软件名称版本nginx1.24.0mysql5.7.41php5.6.27安装nginx 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客: 关闭防火墙 systemctl stop firewalld &&a…

【番外篇】排列组合实现算法2(Java版)

一、说明 在牛客网的很多算法试题中,很多试题底层都是基于排列组合算法实现的,比如动态规划、最优解、最大值等常见问题。排列组合算法有一定的难度,并不能用一般的多重嵌套循环解决,没有提前做针对性的学习和研究,考…

PAT甲级-1020 Tree Traversals

题目 题目大意 给出一棵树的后序遍历和中序遍历,要求输出该树的层序遍历。 思路 非常典型的树的构建与遍历问题。后序遍历和中序遍历可以得出一个树的结构,用递归锁定根节点,然后再遍历左右子树,我之前发过类似题目的博客&…

GIS 中的 SQLAlchemy:空间数据与数据库之间的桥梁

利用 SQLAlchemy 在现代应用程序中无缝集成地理空间数据导言 地理信息系统(GIS)在管理城市规划、环境监测和导航系统等各种应用的空间数据方面发挥着至关重要的作用。虽然 PostGIS 或 SpatiaLite 等专业地理空间数据库在处理空间数据方面非常出色&#…

【AppleID】注册M区AppleID 2025年

注册(一台电脑一天只能注册一个) https://account.apple.com/ 需任意邮箱,任意手机 手机上登录后填地址 示例

frida的常用api

1、Hook普通方法、打印参数和修改返回值 Hook函数 Hook代码 function hookTest1(){var utils Java.use("com.zj.wuaipojie.Demo");utils.a.implementation function(str){// a "test";var retval this.a(str);console.log(str , retval);return retva…

基于C语言的数组从入门到精通

简介:本篇文章主要介绍了一维数组,二维数组,字符数组的定义,数组的应用,数组的核心代码解析,适用于0基础的初学者. C语言数组 1.一维数组 1.1定义 1.1.1声明 语法:数据类型 数组名[数组大小];示例:int arr[5]; 1.1.2初始化 a.静态初始化 完全初始化:int arr[5] {1…

【Elasticsearch】inference ingest pipeline

Elasticsearch 的 Ingest Pipeline 功能允许你在数据索引之前对其进行预处理。通过使用 Ingest Pipeline,你可以执行各种数据转换和富化操作,包括使用机器学习模型进行推理(inference)。这在处理词嵌入、情感分析、图像识别等场景…

【线性代数】基础版本的高斯消元法

[精确算法] 高斯消元法求线性方程组 线性方程组 考虑线性方程组, 已知 A ∈ R n , n , b ∈ R n A\in \mathbb{R}^{n,n},b\in \mathbb{R}^n A∈Rn,n,b∈Rn, 求未知 x ∈ R n x\in \mathbb{R}^n x∈Rn A 1 , 1 x 1 A 1 , 2 x 2 ⋯ A 1 , n x n b 1…

漏洞修复:Apache Tomcat 安全漏洞(CVE-2024-50379) | Apache Tomcat 安全漏洞(CVE-2024-52318)

文章目录 引言I Apache Tomcat 安全漏洞(CVE-2024-50379)漏洞描述修复建议升级Tomcat教程II Apache Tomcat 安全漏洞(CVE-2024-52318)漏洞描述修复建议III 安全警告引言 解决方案:升级到最新版Tomcat https://blog.csdn.net/z929118967/article/details/142934649 service in…

算法每日双题精讲 —— 二分查找(山脉数组的峰顶索引,寻找峰值)

🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 别再犹豫了!快来订阅我们的算法每日双题精讲专栏,一起踏上算法学习的精彩之旅吧💪 在算法的…

mapbox加载geojson,鼠标移入改变颜色,设置样式以及vue中的使用

全国地图json数据下载地址 目录 html加载全部代码 方式一:使用html方式加载geojson 1. 初始化地图 2. 加载geojson数据 设置geojson图层样式,设置type加载数据类型 设置线条 鼠标移入改变颜色,设置图层属性,此处是fill-extru…

衡量算法性能的量级标准:算法复杂度

今天开始数据结构的学习!作为一大重点,拿出态度很重要,想要真实掌握,博客笔记自然少不了!重点全部上色!避免疏忽 下面我们从0基础开始学习今天的第一节!不用担心看不懂,拒绝枯燥的理…

IDE提示:因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170

问题情况 不知道为什么我的IDE终端运行命令的时候总提示以下内容: Import-Module : 无法加载文件 D:\Anaconda3\shell\condabin\Conda.psm1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID1351…

DRF开发避坑指南01

在当今快速发展的Web开发领域,Django REST Framework(DRF)以其强大的功能和灵活性成为了众多开发者的首选。然而,错误的使用方法不仅会导致项目进度延误,还可能影响性能和安全性。本文将从我个人本身遇到的相关坑来给大…

GD32的GD库开发

所有的Cortex-M处理器都有相同的SysTick定时器,因为CMSIS-Core头文件中定义了一个名为SysTick的结构体。 这个定时器可以用作延时函数,不管是STM32的芯片还是GD32,AT32的芯片,delay函数都可以这么写,只要它是cortex-M…