Linux Kernel Development , by Robert Love

Chapter 9 Timers and Time Management

by Shounan Chiou (邱守男) snchiou@nanya.edu.tw created: 2004-05-22

for Linux_Kernel_Study_Group@Taiwan


Introduction

-relative time vs. absolute time

-two types of events / timers:

-Events that occur periodically are driven by the system timer

-Events that kernel schedules to run once after a specified time elapsed are driven by

dynamic timers(also called kernel timers or timers)

Kernel Notion of Time

-tick rate -- system timer goes off at a preprogrammed frequency, called tick rate

-tick – the period(time) between 2 successive timer interrupt, equal to 1/tick rate

-Wall time—the actual time of day, is of most importance of user space application.

-system uptime – the relative time since boot.

The Tick Rate: HZ

- The frequency of system timer is programmed on boot based on a static preprocessor define, HZ, Its value is architechture-dependant. X86 version defined in <include/asm-i386/param.h>

-When writing kernel code, do not assume any given value of HZ.

The frequency of the timer interrupt is rather important. The kernel’s entire notin of time derives

from the periodicity of the system timer.

v2.6
  #ifdef __KERNEL__
  # define HZ             1000            /* Internal kernel timer frequency */ 
  # define USER_HZ        100             /* .. some user interfaces are in "ticks" */
  # define CLOCKS_PER_SEC (USER_HZ)       /* like times() */
  #endif
 
  #ifndef HZ
  #define HZ 100
  #endif
v2.4 
  #ifndef HZ
  #define HZ 100
  #endif 

-pros and cons:

--higher tick rate increase the resolution and accuracy

--higher tick rate makes process preemption occure more accurately

--higher tick rate implies more frequent timer interrupt ,and , thus higher overhead

--higher tick rate implies less processor time available and more frequent periodic thrashing

-On modern systems, up to 1000 can be accepted (ref. to table 9.1 )

Jiffies

-the numbers of tick since boot

-on boot, jiffies be set to 0, and incremented by one during each timer interrupt

-jiffies for 32-bit , jiffies_64 for 64-bit

-jffies wraparound:

safe use with if (time_after(jiffies, timerout)) … instead of if (timeout < jiffies) …

-After v2.5, HZ altered from 100 to 1000, so the user space application used to rely on it become anomalous. To correct this, a macro is introduced:

  #define  jiffifes_to_clock_t(x)   ((x) /  HZ/USER_HZ)

Hardware Clocks and Timers

-2 hardware devices to keep timing : system timer , and RTC

-on boot, kernel reads RTC to initialize the wall time stored in the xtime variable

-system timer provides a mechanism for driving an interrupt at a periodic rate.

The Timer Interrupt Handler

-architecture-dependent routine :

-obtain xtime_lock

-call architecture-independent routine: do_timer()

do_timer() call

update_process_times() call

update_one_process() actually update p_utime /p_stime by value of 1 and 0

run_local_timers() to handle expired dynamic timers

scheduler_tick()

update_times() call

update_wall_time(ticks)

-return to release xtime_lock

void do_timer(struct pt_regs *regs)
{
        jiffies_64++;                          /* increment count by 1 */
update_process_times(user_mode(regs));
update_times();
}

user_mode() return 1 if timer interrupt in user-space, 0 if in kernel-space

The Timer of Day

-xtime.tv_sec stores the number of seconds elapsed since Jan 1, 1970 (called epoch)

-reading or writing xtime variable requires seqlock operation on xtime_lock:

write_seqlock(&xtime_lock)
/* update xtime*/
write_sequnlock(&xtime_lock)
 (see Chap.8)

-wall time mostly be used in user-space applications

Timer

-kernel create and destroy timers dynamically.

-timers are not cyclic, is destroyed once it expired.

-create a timer, initialize the internal value, and fill out the remaining values of struct timer_list

-use del_timer_sync for multiprocessors to avoid race condition

-The kernel executes timers in bottom half context, as a softirq, after the timer

interrupt completes. run_local_timers() calls rais_softirq(TIMER_SOFTIRQ)

Delaying Execution

-delay execution should not occure while a lock held or interrupt disabled

-busy Looping with reschedule best used from process context

-small delay less than a millisecond can only use udelay(usec) function, not the jiffies

-udelay() should only be called for small delays, usually not to over 1 ms

-schedule_timeout(s) put the task to sleep until at least s time elapsed

FINISHED