Linux 内核时钟之高精度处理

来源:互联网 发布:干扰摄像头软件下载 编辑:程序博客网 时间:2024/04/29 16:32
 
 

/* * Called from run_local_timers in hardirq context every jiffy */void hrtimer_run_queues(void){ struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases); ktime_t now;

 if (__hrtimer_hres_active(cpu_base))  return;

 /*  * This _is_ ugly: We have to check periodically, whether we  * can switch to highres and / or nohz mode. The clocksource  * switch happens 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_switch_to_hres();  return; }

 raw_spin_lock(&cpu_base->lock); now = hrtimer_update_base(cpu_base); __hrtimer_run_queues(cpu_base, now); raw_spin_unlock(&cpu_base->lock);}

static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now){ struct hrtimer_clock_base *base = cpu_base->clock_base; unsigned int active = cpu_base->active_bases;

 for (; active; base++, active >>= 1) {  struct timerqueue_node *node;  ktime_t basenow;

  if (!(active & 0x01))   continue;

  basenow = ktime_add(now, base->offset);

  while ((node = timerqueue_getnext(&base->active))) {   struct hrtimer *timer;

   timer = container_of(node, struct hrtimer, node);

   /*    * The immediate goal for using the softexpires is    * minimizing wakeups, not running timers at the    * earliest interrupt after their soft expiration.    * This allows us to avoid using a Priority Search    * Tree, which can answer a stabbing querry for    * overlapping intervals and instead use the simple    * BST we already have.    * We don't add extra wakeups by delaying timers that    * are right-of a not yet expired timer, because that    * timer will have to trigger a wakeup anyway.    */   if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer))    break;

   __run_hrtimer(cpu_base, base, timer, &basenow);  } }}

/* * The write_seqcount_barrier()s in __run_hrtimer() split the thing into 3 * distinct sections: * *  - queued: the timer is queued *  - callback: the timer is being ran *  - post: the timer is inactive or (re)queued * * On the read side we ensure we observe timer->state and cpu_base->running * from the same section, if anything changed while we looked at it, we retry. * This includes timer->base changing because sequence numbers alone are * insufficient for that. * * The sequence numbers are required because otherwise we could still observe * a false negative if the read side got smeared over multiple consequtive * __run_hrtimer() invocations. */

static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,     struct hrtimer_clock_base *base,     struct hrtimer *timer, ktime_t *now){ enum hrtimer_restart (*fn)(struct hrtimer *); int restart;

 lockdep_assert_held(&cpu_base->lock);

 debug_deactivate(timer); cpu_base->running = timer;

 /*  * Separate the ->running assignment from the ->state assignment.  *  * As with a regular write barrier, this ensures the read side in  * hrtimer_active() cannot observe cpu_base->running == NULL &&  * timer->state == INACTIVE.  */ raw_write_seqcount_barrier(&cpu_base->seq);

 __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 0); timer_stats_account_hrtimer(timer); fn = timer->function;

 /*  * Clear the 'is relative' flag for the TIME_LOW_RES case. If the  * timer is restarted with a period then it becomes an absolute  * timer. If its not restarted it does not matter.  */ if (IS_ENABLED(CONFIG_TIME_LOW_RES))  timer->is_rel = false;

 /*  * 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); trace_hrtimer_expire_exit(timer); raw_spin_lock(&cpu_base->lock);

 /*  * Note: We clear the running state after enqueue_hrtimer and  * we do not reprogram the event hardware. Happens either in  * hrtimer_start_range_ns() or in hrtimer_interrupt()  *  * Note: Because we dropped the cpu_base->lock above,  * hrtimer_start_range_ns() can have popped in and enqueued the timer  * for us already.  */ if (restart != HRTIMER_NORESTART &&     !(timer->state & HRTIMER_STATE_ENQUEUED))  enqueue_hrtimer(timer, base);

 /*  * Separate the ->running assignment from the ->state assignment.  *  * As with a regular write barrier, this ensures the read side in  * hrtimer_active() cannot observe cpu_base->running == NULL &&  * timer->state == INACTIVE.  */ raw_write_seqcount_barrier(&cpu_base->seq);

 WARN_ON_ONCE(cpu_base->running != timer); cpu_base->running = NULL;}

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 干部小三怀孕怎么办? 小三的孩子怎么办 把小三打住院了怎么办 小月子没人伺候怎么办 寝室室友有狐臭怎么办 室友在寝室养猫怎么办 和直接领导不合怎么办 房产共有人去世怎么办 发现邪教宣传内容怎么办 说课时两个课时怎么办 投稿文章被拒绝怎么办 中立性细胞偏低怎么办? 孩子爱告状老师怎么办 高中学不好数学怎么办 想做老师应该怎么办 教师职称换学校怎么办 大四差选修学分怎么办 尔雅通识课学分没修满怎么办 大学全英文授课怎么办 小孩脑部有囊肿怎么办 防震期间门应该怎么办 在家待着没意思怎么办 人户分离上学怎么办 小孩上学没人接送怎么办 宝宝上学没人接送怎么办 上海浦东新区酒类许可证怎么办 金税盘里报税处理打不开怎么办 惠民卡到期了怎么办 遇到不拴狗链的主人怎么办 平安福没钱续保怎么办 提前很久到机场怎么办 机场来早了怎么办 机场去早了怎么办 只有高中学历该怎么办 没钱没学历该怎么办 中招分数压线怎么办 两岁宝宝蛀牙怎么办 大学必修课差一分怎么办 好医生差两分怎么办 万丽酒店怎么办会员 银行放款慢 业主怎么办