- 论坛徽章:
- 0
|
In the time subsystem, gettimeofday() always return current wall time. The wall time is expected to record the real world time. But in arm architecture, it happily gives you a biased wall time. When time goes on, the value is far from the real world time.
Lets look at how gettimeofday() is implemented. Firstly gettimeofday() is called in the user application. And then:
1. it calls sys_gettimeofday() in the kernel space
...
/* load registers(R0, R1) with respective arguments */
swi __NR_GETTIMEOFDAY
...
2. sys_gettimeofday() calls do_gettimeofday()
...
if (likely(tv != NULL)) {
struct timeval ktv;
do_gettimeofday(&ktv);
...
}
...
3. do_gettimeofday() is implemented in the specific architecture. In this article
it is discussed in the ARM architecture
/* arch/arm/kernel/time.c */
#ifndef CONFIG_GENERIC_TIME
void do_gettimeofday(struct timeval *ktv)
{
...
}
#endif
CONFIG_GENERIC_TIME means the time subsystem uses a classic time subsystem
(please refer to relative documents). Now lets look at the code
in do_gettimeofday()
...
do {
seq = read_seqbegin_irqsave(&xtime_lock, flags);
usec = systme_timer->offset();
sec = xtime.tv_sec;
usec += xtime.tv_nsec / 1000;
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
...
system_timer refers to specific ARM MCU, such as s3c2410, at91sam9263 etc.
4. Now the control is transferred to at91sam926x_time.c(e.g. at91sam9263). In
this MCU, the linux system is drived by a PIT, which is very simple hardware
implementation.
struct sys_timer at91sam926x_timer = {
.init = at91sam926x_timer_init,
.offset = at91sam926x_timer_offset,
...
};
at91sam926x_timer is assigned to system_timer in arch/arm/kernel/setup.c
So time offset is calculated with at91sam926x_timer_offset().
static unsigned long at91sam926x_timer_offset(void)
{
...
unsigned long t = at91_sys_read(AT91_PIT_PIIR);
elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t);
return (unsigned long)(elapsed * jiffes_to_usec(1) / LATCH);
}
From the above codes, it seems that when user call gettimeofday(), he/she should get the real world time. The time is:
last_time = xtime when last tick occurs
current_time = last_time + elapsed_time after last_time
Note: AT91_PIT_PIIR records the elapsed time. Please refer to AT91SAM9263 datasheet
But the time De facto is slower than the real world time.
Why?
(to be continue...)
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103132/showart_2023144.html |
|