Understanding the linux kernel-ch6-Timing Measurements

 
6.2 The Linux Timekeeping Architecture
· The kernel uses two basic timekeeping functions: 
  one to keep the current time up-to-date and 
  another to count the number of nanoseconds that have elapsed within the current second
Data Structures of the Timekeeping Architecture
· include/asm-i386/timer.h
struct timer_opts {
char* name;
void (*mark_offset)(void);
unsigned long (*get_offset)(void);
unsigned long long (*monotonic_clock)(void);
void (*delay)(unsigned long);
};
struct init_timer_opts {
int (*init)(char *override);
struct timer_opts *opts;
};
/* list of timers, ordered by preference, NULL terminated */
static struct init_timer_opts* __initdata timers[] = {
#ifdef CONFIG_X86_CYCLONE_TIMER
&timer_cyclone_init,
#endif
#ifdef CONFIG_HPET_TIMER
&timer_hpet_init,
#endif
#ifdef CONFIG_X86_PM_TIMER
&timer_pmtmr_init,
#endif
&timer_tsc_init,
&timer_pit_init,
NULL,
};
/* iterates through the list of timers, returning the first 
 * one that initializes successfully.
 */
struct timer_opts* __init select_timer(void)
{
int i = 0;
/* find most preferred working timer */
while (timers[i]) {
if (timers[i]->init)
if (timers[i]->init(clock_override) == 0)
return timers[i]->opts;
++i;
}
panic("select_timer: Cannot find a suitable timer/n");
return NULL;
}
u64 get_jiffies_64(void)
{
unsigned long seq;
u64 ret;
do {
seq = read_seqbegin(&xtime_lock);
ret = jiffies_64;
} while (read_seqretry(&xtime_lock, seq));
return ret;
}
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
·  Timekeeping Architecture in Uniprocessor Systems
· Initialization phase
void __init time_init(void)
{
#ifdef CONFIG_HPET_TIMER
if (is_hpet_capable()) {
/*
 * HPET initialization needs to do memory-mapped io. So, let
 * us do a late initialization after mem_init().
 */
late_time_init = hpet_time_init;
return;
}
#endif
xtime.tv_sec = get_cmos_time();
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
cur_timer = select_timer();
printk(KERN_INFO "Using %s for high-res timesource/n",cur_timer->name);
time_init_hook();
}
1. Initializes the xtime variable
2. Initializes the wall_to_monotonic variable
3. If the kernel supports HPET, it invokes the hpet_enable( ) function to determine 
   whether the ACPI firmware has probed the chip and mapped 
  its registers in the memory address space
  hpet_enable( ) programs the first timer of the HPET chip so that it raises the 
  IRQ 0 interrupt 1000 times per second. Otherwise, if the HPET chip is not available, 
  the kernel will use the PIT: the chip has already been programmed by the init_IRQ( ) 
  function to raise 1000 timer interrupts per second
4. Invokes select_timer( ) to select the best timer source available in the system, 
  and sets the cur_timer variable to the address of the corresponding timer object
5. Invokes setup_irq( 0,&irq0) to set up the interrupt gate corresponding to IRQ0
  the line associated with the system timer interrupt source (PIT or HPET)
static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};
· The timer interrupt handler
The timer_interrupt( ) function is the interrupt service routine (ISR) 
of the PIT or of the HPET; it performs the following steps:
1. Protects the time-related kernel variables 
  by issuing a write_seqlock() on the xtime_lock seqlock 
2. Executes the mark_offset method of the cur_timer timer object
3. Invokes the do_timer_interrupt( ) function
  which in turn performs the following actions:
  a. Increases by one the value of jiffies_64
  b. Invokes the update_times( ) function to update 
    the system date and time and to compute the current system load
  c. Invokes the update_process_times( ) function to perform several 
    time-related accounting operations for the local CPU 
  d. Invokes the profile_tick( ) function 
  e. If the system clock is synchronized with an external clock 
    invokes the set_rtc_mmss( ) function once every 660 seconds
4. Releases the xtime_lock seqlock by invoking write_sequnlock().
5. Returns the value 1 to notify that the interrupt has been effectively handled
Timekeeping Architecture in Multiprocessor Systems
Passed
發佈了58 篇原創文章 · 獲贊 0 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章