High-Resolution Timers

2024-02-18 14:08
文章标签 high resolution timers

本文主要是介绍High-Resolution Timers,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通常软时钟是建立在周期性的时钟中断的基础之上的,为了获取精度较高的软时钟中断,不得不提高时钟中断频率,但是过高的中断频率会造成CPU运算周期的浪费。High-Resolution机制,通过可编程的硬件定时器,把它的到期时间设置为软定时器队列中最早到期的时间,当时钟到期时,再把剩余的软定时器队列的最早到期时间编程到硬件定时器中,这样既能提高软时钟的精度,也不至于影响系统的性能。

High-Resolution Timers管理结构:

/*** struct hrtimer - the basic hrtimer structure* @node:	timerqueue node, which also manages node.expires,*		the absolute expiry time in the hrtimers internal*		representation. The time is related to the clock on*		which the timer is based. Is setup by adding*		slack to the _softexpires value. For non range timers*		identical to _softexpires.* @_softexpires: the absolute earliest expiry time of the hrtimer.*		The time which was given as expiry time when the timer*		was armed.* @function:	timer expiry callback function* @base:	pointer to the timer base (per cpu and per clock)* @state:	state information (See bit values above)* @start_site:	timer statistics field to store the site where the timer*		was started* @start_comm: timer statistics field to store the name of the process which*		started the timer* @start_pid: timer statistics field to store the pid of the task which*		started the timer** The hrtimer structure must be initialized by hrtimer_init()*/
struct hrtimer {struct timerqueue_node		node;  ktime_t				_softexpires;enum hrtimer_restart		(*function)(struct hrtimer *);struct hrtimer_clock_base	*base;unsigned long			state;
#ifdef CONFIG_TIMER_STATSint				start_pid;void				*start_site;char				start_comm[16];
#endif
};struct timerqueue_node {struct rb_node node; //采用红黑树进行管理ktime_t expires; //定时器到期时间
};/*** 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* @active:        red black tree root node for the active timers* @resolution:        the resolution of the clock, in nanoseconds* @get_time:        function to retrieve the current time of the clock* @softirq_time:    the time when running the hrtimer queue in the softirq* @offset:        offset of this clock to the monotonic base*/
struct hrtimer_clock_base {struct hrtimer_cpu_base    *cpu_base;int            index;clockid_t        clockid;struct timerqueue_head    active;ktime_t            resolution;ktime_t            (*get_time)(void);ktime_t            softirq_time;ktime_t            offset;
};

High-Resolution Timers的初始化:
void __init hrtimers_init(void)
{hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,(void *)(long)smp_processor_id());register_cpu_notifier(&hrtimers_nb);
#ifdef CONFIG_HIGH_RES_TIMERSopen_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
#endif
}//最终调用/** Functions related to boot-time initialization:*/
static void __cpuinit init_hrtimers_cpu(int cpu)
{struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);int i;raw_spin_lock_init(&cpu_base->lock);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);}hrtimer_init_hres(cpu_base);
}
内核初始化之初,并没有启动High-Resolution Timers,每当执行时钟软中断时,会检查能否需要进入High-Resolution Timers模式,如果能,则进行进一步的初始化工作:


/*
* This function runs timers and the timer-tq in bottom half context.
*/
static void run_timer_softirq(struct softirq_action *h)
{
struct tvec_base *base = __this_cpu_read(tvec_bases);
hrtimer_run_pending();
if (time_after_eq(jiffies, base->timer_jiffies))
__run_timers(base);
}
/*
* Called from timer softirq every jiffy, expire hrtimers:
*
* For HRT its the fall back code to run the softirq in the timer
* softirq context in case the hrtimer initialization failed or has
* not been done yet.
*/
void hrtimer_run_pending(void)
{
if (hrtimer_hres_active())  //如果已经启用了hrtimer机制,则返回。
return;
/*
* This _is_ ugly: We have to check in the softirq context,
* whether we can switch to highres and / or nohz mode. The
* clocksource switch happens in the timer interrupt with
* xtime_lock held. Notification from there only sets the
* check bit in the tick_oneshot code, otherwise we might
* deadlock vs. xtime_lock.
*/
if (tick_check_oneshot_change(!hrtimer_is_hres_enabled()))  
/*hrtimer_is_hres_enabled: query if the highres mode is enabled      
* tick_check_oneshot_change: Check, if a change happened, which makes oneshot possible.    
*/ 
hrtimer_switch_to_hres(); //Switch to high resolution mode
}
/*
* Switch to high resolution mode
*/
static int hrtimer_switch_to_hres(void)
{
int i, cpu = smp_processor_id();
struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu);
unsigned long flags;
if (base->hres_active)  //如果已经启用了hres机制,则返回
return 1;
local_irq_save(flags);
if (tick_init_highres()) {
local_irq_restore(flags);
printk(KERN_WARNING "Could not switch to high resolution "
"mode on CPU %d\n", cpu);
return 0;
}
base->hres_active = 1;
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
base->clock_base[i].resolution = KTIME_HIGH_RES;
tick_setup_sched_timer();  // setup the tick emulation timer
/* "Retrigger" the interrupt to get things going */
retrigger_next_event(NULL);
local_irq_restore(flags);
return 1;
}
/**
* tick_init_highres - switch to high resolution mode
*
* Called with interrupts disabled.
*/
int tick_init_highres(void)
{
return tick_switch_to_oneshot(hrtimer_interrupt);
}
/**
* tick_switch_to_oneshot - switch to oneshot mode
*/
int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
{
struct tick_device *td = &__get_cpu_var(tick_cpu_device);
struct clock_event_device *dev = td->evtdev;
if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
!tick_device_is_functional(dev)) {
printk(KERN_INFO "Clockevents: "
"could not switch to one-shot mode:");
if (!dev) {
printk(" no tick device\n");
} else {
if (!tick_device_is_functional(dev))
printk(" %s is not functional.\n", dev->name);
else
printk(" %s does not support one-shot mode.\n",
dev->name);
}
return -EINVAL;
}
td->mode = TICKDEV_MODE_ONESHOT;
/*
把CPU本地clock event device的event handler设置为hrtimer_interrupt()
*/
dev->event_handler = handler;
clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
tick_broadcast_switch_to_oneshot();
return 0;
}
/*
* Select oneshot operating mode for the broadcast device
*/
void tick_broadcast_switch_to_oneshot(void)
{
struct clock_event_device *bc;
unsigned long flags;
raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
/*
把全局broadcast device的event_handler设置为tick_broadcast_setup_oneshot.de
*/
tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT;
bc = tick_broadcast_device.evtdev;
if (bc)
tick_broadcast_setup_oneshot(bc);
raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
}
/*
*切换到High-Resolution Timers后,时钟中断设备主要不是为了周期性的tick而发出中断,所以每一个CPU有一个虚拟tick定时器。
*/
/**
* struct tick_sched - sched tick emulation and no idle tick control/stats
* @sched_timer:    hrtimer to schedule the periodic tick in high
*            resolution mode
* @idle_tick:        Store the last idle tick expiry time when the tick
*            timer is modified for idle sleeps. This is necessary
*            to resume the tick timer operation in the timeline
*            when the CPU returns from idle
* @tick_stopped:    Indicator that the idle tick has been stopped
* @idle_jiffies:    jiffies at the entry to idle for idle time accounting
* @idle_calls:        Total number of idle calls
* @idle_sleeps:    Number of idle calls, where the sched tick was stopped
* @idle_entrytime:    Time when the idle call was entered
* @idle_waketime:    Time when the idle was interrupted
* @idle_exittime:    Time when the idle state was left
* @idle_sleeptime:    Sum of the time slept in idle with sched tick stopped
* @iowait_sleeptime:    Sum of the time slept in idle with sched tick stopped, with IO outstanding
* @sleep_length:    Duration of the current idle sleep
* @do_timer_lst:    CPU was the last one doing do_timer before going idle
*/
struct tick_sched {
struct hrtimer            sched_timer;
unsigned long            check_clocks;
enum tick_nohz_mode        nohz_mode;
ktime_t                idle_tick;
int                inidle;
int                tick_stopped;
unsigned long            idle_jiffies;
unsigned long            idle_calls;
unsigned long            idle_sleeps;
int                idle_active;
ktime_t                idle_entrytime;
ktime_t                idle_waketime;
ktime_t                idle_exittime;
ktime_t                idle_sleeptime;
ktime_t                iowait_sleeptime;
ktime_t                sleep_length;
unsigned long            last_jiffies;
unsigned long            next_jiffies;
ktime_t                idle_expires;
int                do_timer_last;
};
/**
* tick_setup_sched_timer - setup the tick emulation timer
*/
void tick_setup_sched_timer(void)
{
struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
ktime_t now = ktime_get();
/*
* Emulate tick processing via per-CPU hrtimers:
*/
hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
ts->sched_timer.function = tick_sched_timer;
/* Get the next period (per cpu) */
hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update());
/*
*添加hrtimer
*/
for (;;) {
hrtimer_forward(&ts->sched_timer, now, tick_period);
hrtimer_start_expires(&ts->sched_timer,
HRTIMER_MODE_ABS_PINNED);
/* Check, if the timer was already in the past */
if (hrtimer_active(&ts->sched_timer))
break;
now = ktime_get();
}
#ifdef CONFIG_NO_HZ
if (tick_nohz_enabled) {
ts->nohz_mode = NOHZ_MODE_HIGHRES;
printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id());
}
#endif
}
/** Called from hardirq context every jiffy*/
void hrtimer_run_queues(void)
{struct timerqueue_node *node;struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);struct hrtimer_clock_base *base;int index, gettime = 1;
/*如果已经启用了hrtimer,则返回*/if (hrtimer_hres_active())return;for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) { //处理CPU上所有的hr_clock_basebase = &cpu_base->clock_base[index];if (!timerqueue_getnext(&base->active))continue;if (gettime) {hrtimer_get_softirq_time(cpu_base);gettime = 0;}raw_spin_lock(&cpu_base->lock);while ((node = timerqueue_getnext(&base->active))) { //处理base上所有到期的定时器struct hrtimer *timer;timer = container_of(node, struct hrtimer, node);if (base->softirq_time.tv64 <=                     //如果发现一个定时器未到期,则其后的定时器肯定没有到期,则breakhrtimer_get_expires_tv64(timer))break;__run_hrtimer(timer, &base->softirq_time);  //如果已经到期,则执行High-Resolution Timers的软中断函数}raw_spin_unlock(&cpu_base->lock);}
}static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
{struct hrtimer_clock_base *base = timer->base;struct hrtimer_cpu_base *cpu_base = base->cpu_base;enum hrtimer_restart (*fn)(struct hrtimer *);int restart;WARN_ON(!irqs_disabled());debug_deactivate(timer);__remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0); //将传递过来的事件从红黑树中删除timer_stats_account_hrtimer(timer);fn = timer->function;                                     //获取到期时钟的处理函数/** Because we run timers from hardirq context, there is no chance* they get migrated to another cpu, therefore its safe to unlock* the timer base.*/raw_spin_unlock(&cpu_base->lock);trace_hrtimer_expire_entry(timer, now);restart = fn(timer);                                      //处理timertrace_hrtimer_expire_exit(timer);raw_spin_lock(&cpu_base->lock);/** Note: We clear the CALLBACK bit after enqueue_hrtimer and* we do not reprogramm the event hardware. Happens either in* hrtimer_start_range_ns() or in hrtimer_interrupt()*/if (restart != HRTIMER_NORESTART) {BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);enqueue_hrtimer(timer, base);}WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK));timer->state &= ~HRTIMER_STATE_CALLBACK;
}



这篇关于High-Resolution Timers的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/721389

相关文章

Kafka【十一】数据一致性与高水位(HW :High Watermark)机制

【1】数据一致性 Kafka的设计目标是:高吞吐、高并发、高性能。为了做到以上三点,它必须设计成分布式的,多台机器可以同时提供读写,并且需要为数据的存储做冗余备份。 图中的主题有3个分区,每个分区有3个副本,这样数据可以冗余存储,提高了数据的可用性。并且3个副本有两种角色,Leader和Follower,Follower副本会同步Leader副本的数据。 一旦Leader副本挂了,Follo

K8s高可用集群部署----超详细(Detailed Deployment of k8s High Availability Cluster)

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页,持续学习,不断总结,共同进步,活到老学到老 导航剑指大厂系列:全面总结 运维核心技术:系统基础、数据库、网路技术、系统安全、自动化运维、容器技术、监控工具、脚本编程、云服务等。 常用运维工具系列:

VideoCrafter1:Open Diffusion models for high-quality video generation

https://zhuanlan.zhihu.com/p/677918122https://zhuanlan.zhihu.com/p/677918122 视频生成无论是文生视频,还是图生视频,图生视频这块普遍的操作还是将图片作为一个模态crossattention进unet进行去噪,这一步是需要训练的,svd除此之外,还将图片和noise做拼接,这一步,很多文生视频的方式通过通过这一步来扩展其成

Failed resolution of: Lcom/growingio/android/sdk/agent/VdsAgent;删除growingio引发的问题

删除了 growingio之后 项目一直报这个错误 Failed resolution of: Lcom/growingio/android/sdk/agent/VdsAgent; 真是讨厌 解决方案 在as 的 Terminal 分别执行这两个命令 ./gradlew cleanBuildCache  ./gradlew clean 如果在使用上面两个命令的时候出现 权限拒绝

Rapid and Accurate Image Super Resolution(RAISR)

Rapid and Accurate Image Super Resolution 每天都有数以百万计的图片在网络上被分享、储存,用户借此探索世界,研究感兴趣的话题,或者与朋友家人分享假期照片。问题是,大量的图片要嘛被照相设备的像素所限制,要嘛在手机、平板或网络限制下被人为压缩,降低了画质。   如今高分辨率显示屏幕正在家庭和移动设备上普及,因此,把低分辨率图片转化

Attentation-GAN for super-resolution(ASRGAN )

Attenatation-GAN for super-resolution(ASRGAN) 1 简单介绍:       目前的SR方法解决的都是小尺寸的数据小于500px,本文提出的是针对大尺寸的数据比如大于2000px的商业数据。本文的创新之处: 提出一种新奇的使用注意力机制的SRGAN方法,叫做A-SRGAN,他是吸收了SAGAN的思想,然后哩由于处理的是大尺度的数据,所以

DAC: High-Fidelity Audio Compression with Improved RVQGAN

Rithesh KumarDescript, Inc.2023NIPS code 文章目录 abstratmethod abstrat 44.1k音频编码为8k bps,接近90x压缩比;可以处理speech, musiccodebook collapse: 部分码本没有利用到。----quantizer dropout :允许单个模型支持可变比特率,但实际上会损害全带宽音频的

hadoop HA (高可用 high available)的搭建

hadoop HA 的搭建 hadoop HA 需求来源为什么要搭建hadoop HA?如何实现高可用?如何写入zookeeper数据? hadoop HA 的搭建:搭建准备开始搭建启动集群 hadoop HA 需求来源 为什么要搭建hadoop HA? 在hadoop 2.0之前,整个hdfs集群中只有一个nn,所以一旦nn节点宕机,则整个集群无法使用。这种现象称为单

Learning a Deep Convolutional Network for Image Super-Resolution

Abstract 我们提出了一种单图像超分辨率(SR)的深度学习方法。 我们的方法直接学习低/高分辨率图像之间的端到端映射。 该映射表示为深度卷积神经网络(CNN),它将低分辨率图像作为输入并输出高分辨率图像。 我们进一步表明,传统的基于稀疏编码的SR方法也可以被视为深度卷积网络。但与分别处理每个组件的传统方法不同,我们的方法共同优化所有层。 我们的深CNN具有轻质结构,同时展示了最先进的修复质

RAISR: Rapid and Accurate Image Super Resolution

Abstract 对于给定的图像,我们希望生成具有更大像素和更高图像质量的更大尺寸的图像。这通常称为单图像超分辨率(SISR)问题。 这个想法是,有了足够的训练数据(相应的低分辨率和高分辨率图像对),我们可以学习一组过滤器(即映射),当将其应用于不在训练集中的给定图像时,会产生更高分辨率的版本,其中学习最好是低复杂度的。在我们提出的方法中,运行时间比目前可用的最佳竞争方法快一到两个数量级,同时产