Presentation is loading. Please wait.

Presentation is loading. Please wait.

Timers and Time Management Ok-Kyun Ha 2007.05.18.

Similar presentations


Presentation on theme: "Timers and Time Management Ok-Kyun Ha 2007.05.18."— Presentation transcript:

1 Timers and Time Management Ok-Kyun Ha 2007.05.18

2 Contents  Kernel Notion of Time  The Tick Rate: HZ  Jiffies  Hardware Clocks and Timers  The Timer Interrupt Handler  Timers  Delaying Execution

3 Introduction  The passing of time is very important to the kernel  almost kernel functions are time driven (not event driven)  Focus (in this chapter) - system timer and timer interrupt - the system timer is a programmable piece of hardware that issues an interrupt at a fixed frequency - dynamic timers - used to schedule events that run once after specified time complete 3

4 Kernel notion of Time  Kernel can comprehend and manage time through tick rate of system timer in hardware  When the system timer goes off, it issues an interrupt that the kernel handles via a special interrupt handler  The kernel keeps track of it simply because the kernel controls the timer interrupt  The timer interrupt is very important to the management of the operating system 4

5 The Tick Rate: HZ  The tick rate is programmed on system boot based on a static preprocessor define, HZ  The value of HZ differs for each supported architectures  The kernel defines the value in #define HZ 1000 /* internal kernel time frequency */  When writing kernel code, never assume that HZ has any given value 5

6 The Tick Rate - The Ideal HZ Value  Changing its frequency has a reasonable impact on the system  Increasing the tick rate means the timer interrupt runs more frequently  Benefits - the timer interrupt has a higher resolution - all timed events have a higher resolution - the accuracy of timed events improves  Downside - implies more frequent timer interrupts - implies higher overhead - processor must spend more time executing the timer interrupt handler 6

7 Jiffies  The global variable jiffies holds the number of ticks that have occurred since the system booted extern unsigned long volatile jiffies; /* */ - on boot: jiffies = 0; - each timer interrupt: jiffies++;  convert forms of jiffies - second to jiffies : (second*HZ) - jiffies to second: (jiffies/HZ) ex) unsigned long next_tick = jiffies + _1;/* one tick from now */ unsigned long later = jiffies + 5 * HZ;/* five second from now */ 7

8 Jiffies – Internal Representation of Jiffies  The jiffies variable has 32 bit in size on 32-bit architectures and 64-bit on 64- bit architectures - overflow: 49.7days (1000 HZ / 32-bit)  jiffies_64 extern u64 jiffies_64;/* */ - overlays the jiffies variable over the start of the jiffies_64 variable - jiffies is the lower 32 bit of the full 64-bit jiffies_64 variable - time management code uses the entire 64 bits - prevents overflow of the full 64-bit value bit 63310 jiffies_64 (jiffies on 64-bit machines) jiffies on 32-bit machine 8

9 Jiffies – Jiffies Wraparound  equal to maximum and it is incremented, it wraps around to zero  macros for comparing tick counts #define time_after(unknown, known) ((long)(known) – (long)(unknown) < 0) #define time_before(unknown, known) ((long)(unknown) – (long)(known) < 0) #define time_after_eq(unknown, known) ((long)(unkown) – (long)(known) >= 0) #define time_before_eq(unknown, known) ((long)(known) – (long)(unkown) >= 0) unsigned long timeout = jiffies + HZ/2; /* timeout in 0.5s */ /* … */ if (timeout > jiffies) { /* we did not time out, good … */ } else { /* we time out, error … */ } 9 unsigned long timeout = jiffies + HZ/2; /* timeout in 0.5s */ /* … */ if (time_after(jiffies, timeout)) { /* we did not time out, good … */ } else { /* we time out, error … */ }

10 Hardware Clock and Timers  Real-Time Clock (RTC) - a nonvolatile device for storing the system time - the kernel reads the RTC and use it to initialize the wall time - stored in the ‘ xtime’ variable  System Timer - serves a much more important (and frequent) role in the kernel’s timekeeping - provide a mechanism for driving an interrupt at a periodic rate - primary system timer is the PIT (on x86) - the kernel programs the PIT on boot to drive the system timer interrupt at HZ frequency 10

11 The Timer Interrupt Handler (1/3)  The architecture-dependent routine - registered as the interrupt handler for the system timer Obtain the xtime_lock lock, which protects access to jiffies_64 and the wall time value, xtime Acknowledge or reset the system timer as required Periodically save the updated wall time to the real time clock Call the architecture-independent timer routine, do_timer()  The architecture-independent routine: do_timer() Increment the jiffies_64 count by one Update resource usages for the currently running process (such as system and user time) Run any dynamic timers that have expired Execute scheduler_tick() Update the wall time, which is stored in xtime Calculate the load average 11

12 The Timer Interrupt Handler (2/3)  do_timer( ) void do_timer (struct pt_regs *regs) { jiffies_64 ++; update_process_times(user_mode(regs)); update_times( ); } void update_process_times(int user_tick) { struct task_struct *p = current; int cpu = smp_processor_id(); int system = user_tick ^ 1; update_one_process(p, user_tick, system, cpu); run_local_timers(); scheduler_tick(user_tick, system); } 12

13 The Timer Interrupt Handler (3/3)  update_times()  all this occurs every 1/ HZ of a second void update_times(void) { unsigned long ticks; ticks = jiffies – wall_jiffies; if (ticks) { wall_jiffies += ticks; update_wall_time (ticks); } last_time_offset = 0; calc_load(ticks); } 13

14 Timers  Bottom-half - used great for deferring work until later - not so much to delay work, but simply to not do the work now  Kernel Timer - can delaying a work during a specified amount of time - easy to use perform some initial setup specify an expiration time specify a function to execute upon said expiration activate the timer 14

15 Timers – Using Timer (1/2)  represented by struct timer_list struct timer_list { struct list_head entry;/* entry in linked list of timers */ unsigned long expires;/* expiration value, in jiffies */ spinlock_t lock;/* lock protecting this timer */ void (*function)(unsigned long);/* the timer handler function */ unsigned long data;/* lone argument to the handler */ struct tvec_t_base_s *base;/* internal timer field */ }; 15

16 Timers – Using Timer (2/2)  Using 1. define using timer struct timer_list my_timer; 2. initialize the timer init_timer(&my_timer); 3. setting the timer funtions my_timer.expires = jiffies + delay; my_timer.data = 0; my_timer.function = my_function; 4. activate the timer add_timer(&my_timer); 16

17 Timers – Timer Race condition  potential race conditions exist (run asynchronously) - a timer could be executed another processor in multi-processing system - a potential race condition that must be guarded against exists when deleting timers  delete timer - del_timer(&my_timer); - del_timer_sync(&my_timer);  modify timer: changes the expiration of a given timer - del_timer(my_timer); my_timer->expires = jiffies + new_delay; add_timer(my_timer); - mod_timer(&my_timer, jiffies+new_delay); 17

18 Timers – The Timer Implementation  The Timer Implementation - the kernel executes timers in bottom-half context after the timer interrupt completes - the timer interrupt handler runs update_process_times() which calls run_local_timers() - the kernel partitions timers into five groups based on their expiration value - timers move down through the groups as their expiration time draws closer void run_local_timers(void) { raise_softirq(TIMER_SOFTIRQ); } 18

19 Delaying Execution  kernel code (especially drivers) needs a way to delay execution for some time without using timers or bottom-half mechanism - usually to allow hardware time to complete a given task - network card driver should wait at least the two microseconds before continuing  the solutions (depending on the semantics of the delay) - Busy Looping - Small Delays - schedule_timeout() 19

20 Delaying Execution – Busy looping  Busy looping: spin in a loop until the desired number of clock ticks pass  reschedule for current process - conditionally invokes the scheduler only if there is some more important task to run unsigned long delay = jiffies + 5 * HZ; while (time_before(jiffies, delay)) ; unsigned long delay = jiffies + 5 * HZ; while (time_before(jiffies, delay)) cond_resched(); 20

21 Delaying Execution – Small Delays  requires very short and rather precise delays - kernel provide two functions for microsecond and millisecond delays - delays execution by busy looping for the specified number of microseconds or milliseconds  using the functions - the udelay() function should be called only for small delays - larger delays on fast machines might result in overflow - as delays over 1 millisecond for longer durations mdelay() function should be called void udelay(unsigned long usecs);/* udelay(150) */ void mdelay(unsigned long msecs);/* mdelay(150) */ 21

22 Delaying Execution – schedule_timeout()  optimal method - task to sleep until at least the specified time has elapsed - the kernel wakes the task up and places it back on the runqueue  using the functions  sleeping on a waiting queue, with a timeout - first occur want to make desirable to wait for a specific event or wait for a specified time to elapse - call schedule_timeout() instead of schedule() after placing itself on a wait queue /* set task’state to interruptible sleep */ set_current_state(TASK_INTERRUPTIBLE);/*TASK_UNINTERRUPTIBLE */ /* take a nap and wake up in “s” seconds */ schedule_timeout(s * HZ); 22


Download ppt "Timers and Time Management Ok-Kyun Ha 2007.05.18."

Similar presentations


Ads by Google