




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
窗体顶端nohz下的timer机制和进程调度 在2.6.21内核之前,时钟中断是周期的,即以HZ为频率,系统总是被动的接受时钟中断,然后运行中断处理程序。如果实在没有任务可以运行,那 么就执行idle,这也许也算一种创意,可 是时钟中断还是会周期性的打破idle,然后查询有没有需要做的事情,如果没有继续idle以往的进程在特定的固定时间片内运行,时钟的定时中断提供了时间片的监督工作,一切显得十分和谐,可是系统内核本身就是没有主权,一切都在硬件的安排下进行。随后的2.6.22以后,nohz才出现,nohz其实就是动态设置下一次的中断时间而不是使用系统无条件的默认的HZ中断。这样cfs调度器,再也不用受制于底层的时钟以及时间片分配特性,linux可以动态设置时间片长短,按照自己的方式来进行调度。 nohz其实就是托了抽象出来的clocksource和 clock_event_device的福,clocksource和 clock_event_device,这两个结构体就是时钟以及时钟行为的抽象。先熟悉两个数据结构struct timer_list :软件时钟,记录了软件时钟的到期时间以及到期后要执行的操作。struct tvec_base :用于组织、管理软件时钟的结构。在 SMP 系统中,每个 CPU 有一个。 struct timer_list struct list_head entry; /所在的链表 unsigned long expires; /到期时间,以 tick 为单位 void (*function)(unsigned long); /回调函数,到期后执行的操作 unsigned long data; /回调函数的参数 struct tvec_t_base_s *base; /记录该软件时钟所在的 struct tvec_base 变量#ifdef CONFIG_TIMER_STATS void *start_site; char start_comm16; int start_pid;#endif;struct tvec_t_base_s spinlock_t lock; struct timer_list *running_timer; /正在处理的软件时钟 unsigned long timer_jiffies; /当前正在处理的软件时钟到期时间 tvec_root_t tv1; /保存了到期时间从 timer_jiffies 到 timer_jiffies + 2的8次方 之间(包括边缘值)的所有软件时钟 tvec_t tv2; /保存了到期时间从 timer_jiffies + 2的8次方 到 timer_jiffies + 2的14次方 之间(包括边缘值)的 所有软件时钟 tvec_t tv3; /1420 tvec_t tv4; /2026 tvec_t tv5; /2632 _cacheline_aligned;typedef struct tvec_t_base_s tvec_base_t;/下面开始跟踪内核中timer的代码,内核版本2.6.24/* This function runs timers and the timer-tq in bottom half context.*/static void run_timer_softirq(struct softirq_action *h) /定时器中断下半部 tvec_base_t *base = _get_cpu_var(tvec_bases); /取得CPU的tvec_base_t结构数据 hrtimer_run_queues(); /这里有机会切换到nohz或者hres if (time_after_eq(jiffies, base-timer_jiffies) /如果当前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_queues(void) struct hrtimer_cpu_base *cpu_base = &_get_cpu_var(hrtimer_bases); int i; if (hrtimer_hres_active() 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() /这个if判断就是具体切换到hres或者nohz的代码 if (hrtimer_switch_to_hres() return; hrtimer_get_softirq_time(cpu_base); for (i = 0; i check_clocks) return 0; if (ts-nohz_mode != NOHZ_MODE_INACTIVE) return 0; if (!timekeeping_is_continuous() | !tick_is_oneshot_available() return 0; if (!allow_nohz) return 1; tick_nohz_switch_to_nohz(); /如果满足调节,切换到nohz return 0;/* tick_nohz_switch_to_nohz - switch to nohz mode*/static void tick_nohz_switch_to_nohz(void) struct tick_sched *ts = &_get_cpu_var(tick_cpu_sched); ktime_t next; if (!tick_nohz_enabled) return; local_irq_disable(); if (tick_switch_to_oneshot(tick_nohz_handler) /timer改成oneshot模式(一次性定时器),同时指定回调函数tick_nohz_handler local_irq_enable(); return; ts-nohz_mode = NOHZ_MODE_LOWRES; /* * Recycle the hrtimer in ts, so we can share the * hrtimer_forward with the highres code. */ hrtimer_init(&ts-sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); /* Get the next period */ next = tick_init_jiffy_update(); for (;) ts-sched_timer.expires = next; if (!tick_program_event(next, 0) break; next = ktime_add(next, tick_period); local_irq_enable(); printk(KERN_INFO Switched to NOHz mode on CPU #%dn, smp_processor_id();/* The nohz low res interrupt handler*/static void tick_nohz_handler(struct clock_event_device *dev) struct tick_sched *ts = &_get_cpu_var(tick_cpu_sched); struct pt_regs *regs = get_irq_regs(); int cpu = smp_processor_id(); ktime_t now = ktime_get(); dev-next_event.tv64 = KTIME_MAX; /* * Check if the do_timer duty was dropped. We dont care about * concurrency: This happens only when the cpu in charge went * into a long sleep. If two cpus happen to assign themself to * this duty, then the jiffies update is still serialized by * xtime_lock. */ if (unlikely(tick_do_timer_cpu = -1) tick_do_timer_cpu = cpu; /* Check, if the jiffies need an update */ if (tick_do_timer_cpu = cpu) tick_do_update_jiffies64(now); /* * When we are idle and the tick is stopped, we have to touch * the watchdog as we might not schedule for a really long * time. This happens on complete idle SMP systems while * waiting on the login prompt. We also increment the start * of idle jiffy stamp so the idle accounting adjustment we * do when we go busy again does not account too much ticks. */ if (ts-tick_stopped) /idle的tick已经停止,替idle喂狗 touch_softlockup_watchdog(); ts-idle_jiffies+; update_process_times(user_mode(regs); /在这里面调用进程调度的回调函数 profile_tick(CPU_PROFILING); /* Do not restart, when we are in the idle loop */ if (ts-tick_stopped) return; while (tick_nohz_reprogram(ts, now) /重新设置定时器 now = ktime_get(); tick_do_update_jiffies64(now); /这里修改jiffies /tick_sched结构/* 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的tick已经停止* 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_sleeptime: Sum of the time slept in idle with sched tick stopped* sleep_length: Duration of the current idle sleep*/struct tick_sched struct hrtimer sched_timer; unsigned long check_clocks; enum tick_nohz_mode nohz_mode; ktime_t idle_tick; int tick_stopped; unsigned long idle_jiffies; unsigned long idle_calls; unsigned long idle_sleeps; ktime_t idle_entrytime; ktime_t idle_sleeptime; ktime_t sleep_length; unsigned long last_jiffies; unsigned long next_jiffies; ktime_t idle_expires;/* Called from the timer interrupt handler to charge one tick to the current* process. user_tick is 1 if the tick is user time, 0 for system.*/void update_process_times(int user_tick) struct task_struct *p = current; int cpu = smp_processor_id(); /* Note: this timer irq context must be accounted for as well. */ account_process_tick(p, user_tick); run_local_timers(); if (rcu_pending(cpu) rcu_check_callbacks(cpu, user_tick); scheduler_tick(); /每个tick一次进程调度 run_posix_cpu_timers(p);/* This function gets called by the timer code, with HZ frequency.* We call it with interrupts disabled.* It also gets called by the fork code, when changing the parents* timeslices.*/void scheduler_tick(void) int cpu = smp_processor_id(); struct rq *rq = cpu_rq(cpu); struct task_struct *curr = rq-curr; u64 next_tick = rq-tick_timestamp + TICK_NSEC; spin_lock(&rq-lock); _update_rq_clock(rq); /* * Let rq-clock advance by at least TICK_NSEC: */ if (unlikely(rq-clock clock = next_tick; rq-tick_timestamp = rq-clock; update_cpu_load(rq); if (curr != rq-idle) /* FIXME: needed? */ curr-sched_class-task_tick(rq, curr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年康复科护理质量提升计划
- 商务礼仪考试题及答案
- 安规考试题库及答案
- 河南村书记考试题及答案
- 人教版小学四年级英语作文范文解析
- 2025年医保病历审核质量分析与措施
- 护士离职申请书范文
- 轻工制造工程总承包项目管理计划
- 2025版食品行业收银系统采购与监管服务合同
- 企业培训专职教师岗位职责
- 直播助农项目创业计划书
- 复变函数与积分变换课程教案讲义
- 违反工作纪律保证书
- 消除“艾梅乙”医疗歧视-从我做起
- 三级物联网安装调试员技能鉴定考试题及答案
- 体能恢复练习课时3:1、连续单脚跳;2、仰卧两头起;3、俯卧撑 教案
- 三年级上册信息技术教案全册
- 西师版小学六年级上册数学全册教案(表格式)
- SJ∕T 11614-2016 电动汽车驱动电机系统用金属化薄膜电容器规范
- 小学校本教材《中草药的认识》(中学也可用)
- (高清版)JTGT 3610-2019 公路路基施工技术规范
评论
0/150
提交评论