Timer Linux内核计时器函数在什么上下文中运行?
当使用Timer Linux内核计时器函数在什么上下文中运行?,timer,linux-kernel,kernel,Timer,Linux Kernel,Kernel,当使用add\u timerAPI创建的计时器过期并且在计时器结构处分配的函数运行时,它在什么上下文中运行?它是中断上下文还是某个内核进程上下文?当然是在中断上下文中,更准确地说,在softirq上下文中,请参见下面的(kernel/timer.c): 静态内联无效运行计时器(struct tvec_base*base) { 结构定时器列表*定时器; 旋转锁定irq(&base->lock); while(时间在相等(基频、基频->定时器基频)之后){ 结构清单\首件工作清单; 结构列表头*头=
add\u timer
API创建的计时器过期并且在计时器结构处分配的函数运行时,它在什么上下文中运行?它是中断上下文还是某个内核进程上下文?当然是在中断上下文中,更准确地说,在softirq上下文中,请参见下面的(kernel/timer.c):
静态内联无效运行计时器(struct tvec_base*base)
{
结构定时器列表*定时器;
旋转锁定irq(&base->lock);
while(时间在相等(基频、基频->定时器基频)之后){
结构清单\首件工作清单;
结构列表头*头=&工作列表;
int index=base->timer\u jiffies和TVR\u MASK;
/*
*级联定时器:
*/
如果(!索引&&
(!级联(基和基->tv2,索引(0)))&&
(!级联(基和基->tv3,索引(1)))&&
!级联(基和基->tv4,索引(2)))
级联(基和基->tv5,索引(3));
++基本->定时器;
列表替换初始化(基本->tv1.vec+索引和工作列表);
而(!list_empty(head)){
无效(*fn)(未签字的多头);
无符号长数据;
布尔伊克萨菲;
计时器=列表第一个条目(头、结构计时器列表、条目);
fn=定时器->功能;
数据=定时器->数据;
irqsafe=tbase\u get\u irqsafe(计时器->基础);
定时器\统计\账户\定时器(定时器);
基本->运行计时器=计时器;
拆下计时器(计时器,底座);
if(irqsafe){
旋转解锁(&base->lock);
调用_timer_fn(timer,fn,data);//锁);
}否则{
旋转解锁irq(&base->lock);
调用_timer_fn(timer,fn,data);//锁);
}
}
}
基本->运行计时器=NULL;
旋转解锁irq(&base->lock);
}
/*
*此函数在下半部分上下文中运行计时器和计时器tq。
*/
静态无效运行计时器软irq(结构软irq动作*h)
{
struct tvec_base*base=u this_cpu_read(tvec_base);
hrtimer_run_pending();
if(时间在均衡(基频、基频->定时器)之后)
__运行计时器(基本);
}
void\uuu init\u计时器(void)
{
INTERR;
/*确保计时器->基指针中有足够的低位用于标记*/
构建错误(uuuuuuuuuuuuuuuuuuuuuu对齐(结构tvec_uuuu基)和计时器标志掩码);
err=计时器\u cpu\u通知(&计时器\u nb,(无符号长)cpu\u启动\u准备,
(void*)(long)smp_处理器_id());
init_timer_stats();
BUG_ON(err!=通知_OK);
寄存器\u cpu\u通知程序(&计时器\u nb);
打开_softirq(TIMER _softirq,run _TIMER _softirq);//你在说什么操作系统?如果你指的是Linux及其内核计时器,那么它就是中断上下文,因为Linux/TIMER.c
中对add_TIMER()
的注释说明:“内核将来将在->过期点从计时器中断执行->函数(->数据)回调。”虽然在某些内核中,中断处理程序可能在进程上下文中运行,但我不建议使用它。嗨,对不起,当然是Linux内核。谢谢。
static inline void __run_timers(struct tvec_base *base)
{
struct timer_list *timer;
spin_lock_irq(&base->lock);
while (time_after_eq(jiffies, base->timer_jiffies)) {
struct list_head work_list;
struct list_head *head = &work_list;
int index = base->timer_jiffies & TVR_MASK;
/*
* Cascade timers:
*/
if (!index &&
(!cascade(base, &base->tv2, INDEX(0))) &&
(!cascade(base, &base->tv3, INDEX(1))) &&
!cascade(base, &base->tv4, INDEX(2)))
cascade(base, &base->tv5, INDEX(3));
++base->timer_jiffies;
list_replace_init(base->tv1.vec + index, &work_list);
while (!list_empty(head)) {
void (*fn)(unsigned long);
unsigned long data;
bool irqsafe;
timer = list_first_entry(head, struct timer_list,entry);
fn = timer->function;
data = timer->data;
irqsafe = tbase_get_irqsafe(timer->base);
timer_stats_account_timer(timer);
base->running_timer = timer;
detach_expired_timer(timer, base);
if (irqsafe) {
spin_unlock(&base->lock);
call_timer_fn(timer, fn, data); // <=========== HERE
spin_lock(&base->lock);
} else {
spin_unlock_irq(&base->lock);
call_timer_fn(timer, fn, data); // <============ HERE
spin_lock_irq(&base->lock);
}
}
}
base->running_timer = NULL;
spin_unlock_irq(&base->lock);
}
/*
* 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);
}
void __init init_timers(void)
{
int err;
/* ensure there are enough low bits for flags in timer->base pointer */
BUILD_BUG_ON(__alignof__(struct tvec_base) & TIMER_FLAG_MASK);
err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
(void *)(long)smp_processor_id());
init_timer_stats();
BUG_ON(err != NOTIFY_OK);
register_cpu_notifier(&timers_nb);
open_softirq(TIMER_SOFTIRQ, run_timer_softirq); // <============= HERE
}