Linux hrtimer 数据结构

文章目录

  • [1. 前言](#1. 前言)
  • [2. hrtimer 数据结构](#2. hrtimer 数据结构)

1. 前言

限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。

2. hrtimer 数据结构

Linux hrtimer 核心数据结构主要由 struct hrtimer_cpu_basestruct hrtimer_clock_base 构成(摘自 Linux 4.14.336 内核):

c 复制代码
// include/linux/hrtimer.h

/**
 * struct hrtimer_cpu_base - the per cpu clock bases
 * @lock:		lock protecting the base and associated clock bases
 *			and timers
 * @cpu:		cpu number
 * @active_bases:	Bitfield to mark bases with active timers
 * @clock_was_set_seq:	Sequence counter of clock was set events
 * @hres_active:	State of high resolution mode
 * @in_hrtirq:		hrtimer_interrupt() is currently executing
 * @hang_detected:	The last hrtimer interrupt detected a hang
 * @softirq_activated:	displays, if the softirq is raised - update of softirq
 *			related settings is not required then.
 * @nr_events:		Total number of hrtimer interrupt events
 * @nr_retries:		Total number of hrtimer interrupt retries
 * @nr_hangs:		Total number of hrtimer interrupt hangs
 * @max_hang_time:	Maximum time spent in hrtimer_interrupt
 * @softirq_expiry_lock: Lock which is taken while softirq based hrtimer are
 *			 expired
 * @expires_next:	absolute time of the next event, is required for remote
 *			hrtimer enqueue; it is the total first expiry time (hard
 *			and soft hrtimer are taken into account)
 * @next_timer:		Pointer to the first expiring timer
 * @softirq_expires_next: Time to check, if soft queues needs also to be expired
 * @softirq_next_timer: Pointer to the first expiring softirq based timer
 * @clock_base:		array of clock bases for this cpu
 *
 * Note: next_timer is just an optimization for __remove_hrtimer().
 *	 Do not dereference the pointer because it is not reliable on
 *	 cross cpu removals.
 */
struct hrtimer_cpu_base {
	raw_spinlock_t			lock;
	unsigned int			cpu;
	unsigned int			active_bases;
	unsigned int			clock_was_set_seq;
	unsigned int			hres_active		: 1,
					in_hrtirq		: 1,
					hang_detected		: 1,
					softirq_activated       : 1;
#ifdef CONFIG_HIGH_RES_TIMERS
	unsigned int			nr_events;
	/*
	 * tick 中断中, 按下一个到期 hrtimer 时间编程 tick 设备重试的
	 * 累加次数, 期间可能出错了. 每个 tick 中断最多重试 3 次.
	 */
	unsigned short			nr_retries;
	/* tick 中断中, 按下一个到期 hrtimer 时间编程 tick 设备出错的 累加次数 */
	unsigned short			nr_hangs;
	unsigned int			max_hang_time;
#endif
	spinlock_t			softirq_expiry_lock;
	/*
	 * hrtimer_cpu_base 的所有(类型(包括 hard,soft) hrtimer_clock_base 
	 * clock_base[]) 的 hrtimer 红黑树队列中, 下一个到期时间最早的 hrtimer 
	 * 的 超时时间点.
	 */
	ktime_t				expires_next;
	struct hrtimer			*next_timer; /* 下一个到期的 hrtimer */
	ktime_t				softirq_expires_next; /* 下一个最早到期的 soft hrtimer 时间点 */
	struct hrtimer			*softirq_next_timer; /* 下一个最早到期的 soft hrtimer */
	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
} ____cacheline_aligned;

/**
 * struct hrtimer_clock_base - the timer base for a specific clock
 * @cpu_base:		per cpu clock base
 * @index:		clock type index for per_cpu support when moving a
 *			timer to a base on another cpu.
 * @clockid:		clock id for per_cpu support
 * @seq:		seqcount around __run_hrtimer
 * @running:		pointer to the currently running hrtimer
 * @active:		red black tree root node for the active timers
 * @get_time:		function to retrieve the current time of the clock
 * @offset:		offset of this clock to the monotonic base
 */
struct hrtimer_clock_base {
	/*
	 * 一个 hrtimer 关联的 一个 每 cpu 的 tick 设备, 这是 一对一 的关系, 
	 * 基于该 cpu 的 tick 设备的 cycle 来作为时间基准, 这在系统初始化时
	 * 就已经设定好了, 后续不会变更:
	 * 1) boot CPU
	 *    start_kernel()
	 *      hrtimers_init()
	 *        hrtimers_prepare_cpu(smp_processor_id());
	 *          struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
	 *           int i;
	 *
	 *           // 为当前 CPU @cpu 所有类型的 hrtimer_clock_base 设定 hrtimer_cpu_base
	 *           for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
	 *             cpu_base->clock_base[i].cpu_base = cpu_base;
	 *             timerqueue_init_head(&cpu_base->clock_base[i].active);
	 *           }
	 * 2) 非 BOOT CPU
	 *    CPU 热插拔状态 CPUHP_HRTIMERS_PREPARE 触发 hrtimers_prepare_cpu()
	 */
	struct hrtimer_cpu_base	*cpu_base;
	unsigned int		index;
	clockid_t		clockid;
	seqcount_t		seq;
	struct hrtimer		*running; /* 当前正在运行的 hrtimer (回调), NULL 表示没有正在运行的 hrtimer */
	struct timerqueue_head	active; /* 激活 hrtimer 的红黑树(根) */
	ktime_t			(*get_time)(void);
	ktime_t			offset; /* 每个 hrtimer_clock_base 都维护自身独立的时间线 */
} __hrtimer_clock_base_align;

struct hrtimer_cpu_base 是 per-cpu 的数据结构,为其包含的各种类型的 struct hrtimer_clock_base 定义时钟基准:

c 复制代码
// include/linux/hrtimer.h
enum  hrtimer_base_type {
	HRTIMER_BASE_MONOTONIC,
	HRTIMER_BASE_REALTIME,
	HRTIMER_BASE_BOOTTIME,
	HRTIMER_BASE_TAI,
	HRTIMER_BASE_MONOTONIC_SOFT,
	HRTIMER_BASE_REALTIME_SOFT,
	HRTIMER_BASE_BOOTTIME_SOFT,
	HRTIMER_BASE_TAI_SOFT,
	HRTIMER_MAX_CLOCK_BASES,
};

// kernel/time/hrtimer.c
/*
 * The timer bases:
 *
 * There are more clockids than hrtimer bases. Thus, we index
 * into the timer bases by the hrtimer_base_type enum. When trying
 * to reach a base using a clockid, hrtimer_clockid_to_base()
 * is used to convert from clockid to the proper hrtimer_base_type.
 */
DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
{
	.lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
	.clock_base =
	{
		{
			.index = HRTIMER_BASE_MONOTONIC,
			.clockid = CLOCK_MONOTONIC,
			.get_time = &ktime_get,
		},
		{
			.index = HRTIMER_BASE_REALTIME,
			.clockid = CLOCK_REALTIME,
			.get_time = &ktime_get_real,
		},
		{
			.index = HRTIMER_BASE_BOOTTIME,
			.clockid = CLOCK_BOOTTIME,
			.get_time = &ktime_get_boottime,
		},
		{
			.index = HRTIMER_BASE_TAI,
			.clockid = CLOCK_TAI,
			.get_time = &ktime_get_clocktai,
		},
		{
			.index = HRTIMER_BASE_MONOTONIC_SOFT,
			.clockid = CLOCK_MONOTONIC,
			.get_time = &ktime_get,
		},
		{
			.index = HRTIMER_BASE_REALTIME_SOFT,
			.clockid = CLOCK_REALTIME,
			.get_time = &ktime_get_real,
		},
		{
			.index = HRTIMER_BASE_BOOTTIME_SOFT,
			.clockid = CLOCK_BOOTTIME,
			.get_time = &ktime_get_boottime,
		},
		{
			.index = HRTIMER_BASE_TAI_SOFT,
			.clockid = CLOCK_TAI,
			.get_time = &ktime_get_clocktai,
		},
	}
};

最终形成的数据结构如下图:

相关推荐
HLC++10 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室11 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy14 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕15 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫16 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生16 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1117 小时前
linux基础IO
linux·运维·服务器
BelongPanda19 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯19 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_7779983420 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器