当前位置: 首页 > news >正文

Linux-rt下卡死之hrtimer分析

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.lryc.cn/news/526346.html

相关文章:

  • 【AI日记】25.01.24
  • React 中hooks之useSyncExternalStore使用总结
  • C++11新特性之decltype
  • 二叉树相关oj题 1. 检查两颗树是否相同。
  • element tbas增加下拉框
  • 新浪安卓(Android)开发面试题及参考答案(68道题,9道手撕题)
  • Zbrush导入笔刷
  • 实战演示:利用ChatGPT高效撰写论文
  • 大数据学习之SCALA分布式语言三
  • k8s简介,k8s环境搭建
  • 深入理解MySQL事务(万字详)
  • 微信小程序使用picker根据接口给的省市区的数据实现省市区三级联动或者省市区街道等多级联动
  • Go Fx 框架使用指南:深入理解 Provide 和 Invoke 的区别
  • VSCode+Continue实现AI辅助编程
  • 阿里云服务器在Ubuntu上安装redis并使用
  • Blazor-Blazor呈现概念
  • 14-6-2C++的list
  • StarRocks常用命令
  • 激光雷达和相机早期融合
  • PMP–一、二、三模–分类–12.采购管理
  • C++ 标准模板库 (STL, Standard Template Library)
  • 从spec到iso的koji使用
  • 【记录自开发的SQL工具】工具字符拼接、Excel转sql、生成编码、生成测试数据
  • Cesium特效——城市白模的科技动效的各种效果
  • VS Code i18n国际化组件代码code显示中文配置 i18n ally
  • C++ —— 智能指针 unique_ptr (上)
  • 技术 · 创作 · 生活 | 我的 2024 全面复盘
  • 表的增删改查(MySQL)
  • 【设计模式】JAVA 策略 工厂 模式 彻底告别switch if 等
  • 基于Springboot用axiospost请求接收字符串参数为null的解决方案