免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1218 | 回复: 0
打印 上一主题 下一主题

The accuracy of gettimeofday in ARM architecture 2 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-11 10:02 |只看该作者 |倒序浏览
(continued)
Now Let's look back our deduction. We get the correct time if we get the right last_time. If the last_time is incorrect, how can we get the real world time?
The last_time is based on timer interrupt. The timer, which is as a primitive source to drive the whole system, is architecture-specific. Usually it is located on PIT of the spcific architecture. In our example it is AT91SAM9263's PIT.
The procedure to calculate the last time is as follows:
1. Registration
   a. Setting the PIT with HZ
   b. Enalbling the PIT
2. After enabling PIT, it increases automatically. When the corresponding register
   overflows, it generates an interrupt, which is captured by CPU. And then CPU
   dispatches it to the corresponding interrupt routine. This is the
   timer_interrupt, whichi is registered in  arch/arm/mach-at91/at91sam926x_time.c.
Now lets look at the codes to find how it is handled.
   a. at91sam926x_timer_interrupt is called
      ...
      write_seqlock(&xtime_lock);
      nr_ticks = PITCNT(at91_sys_read(AT91_PIT_PIVR));
      do {
         timer_tick();
         nr_ticks --;
      } while (nr_ticks);
      write_sequnlock(&xtime_unlock);
      ...
      /* arch/arm/kernel/time.c */
      void timer_tick(void)
      {
         ...
         do_timer(1);
      #ifndef CONFIG_SMP
         update_process_times(user_mode(get_irq_regs()));
      #endif
         ...
      }
   b. do_timer() and update_process_times() are considered here. These two
      functions are in kernel/timer.c
      void do_timer(unsigned long ticks)
      {
         jiffies_64 += ticks;
      #ifdef CONFIG_GENERIC_TIME
         clocksource_accumulate(clock, clocksource_read(clock));
      #endif
      }
      This function just increass the jiffes_64. Function gettimeofday() uses
      xtime. So xtime must be increased in update_process_times(). Let's look at
      update_process_times().
      void update_process_times(int user_tick)
      {
         ...
         run_local_timers();
         ...
      }
      void run_local_timers(void)
      {
         raise_softirq(TIMER_SOFTIRQ);
         softlockup_tick();
      }
   c. The kernel handles the update_time in SOFTIRQ handler. This slows down the
      wall time in a specific moment, especially when system's load is very high.
      static void run_timer_softirq(struct softirq_action *action)
      {
         ...
         update_times();
         ...
      }
Solution
we can move update_times() from softirq handler to interrupt handler and update the wall time in do_timer(). Since the timer_interrupt is set to IRQF_DISABLED the process handling is atomic. see code in arch/arm/mach-at91/at91sam926x_timer.c for definition of irq flags.
      void do_timer(unsigned long ticks)
      {
         jiffies_64 += ticks;
         update_times();  //move from softirq handler
      #ifdef CONFIG_GENERIC_TIME
         clocksource_accumulate(clock, clocksource_read(clock));
      #endif
      }
   
Conclusion:
gettimeofday() returns the expected real world  time.


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103132/showart_2024003.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP