120 likes | 276 Views
제 46 강 : Timers and Time Management. Ch 10 Timers and Time Management. Terminology. HZ tick rate (differs for each architecture) #define HZ 1000 (include/asm-i386/param.h) In most other architecture, HZ is 100 i386 architecture (since 2.5 series) jiffies
E N D
제46강 : Timers and Time Management Ch 10 Timers and Time Management
Terminology • HZ • tick rate (differs for each architecture) #define HZ 1000 (include/asm-i386/param.h) • In most other architecture, HZ is 100 • i386 architecture (since 2.5 series) • jiffies • number of ticks since system boot • global variable • jiffies-Hz-Time • To convert from [seconds to jiffies] • (second * HZ) • To convert from [jiffies to seconds] • (jiffies / HZ) tick tick tick 1000 Hz 100 Hz Jiffies
Terminology • Issues on HZ • If increase the tick rate from 100 Hz 1000 Hz? • All timed events have a higher resolution • and the accuracy of timed events improve • overhead of timer Interrupt increase . • Issues on jiffies • Internal representation of jiffies • jiffies wrap-around
Hardware Clocks and Timers • System Timer • Drive an interrupt at a periodic rate • Programmable Interrupt Timer (PIT) on X86 • kernel programs PIT on boot to drive timer interrupt at HZ • Real-Time Clock (RTC) • Nonvolatile device for storing the time • RTC continueseven when the system is off (small battery) • On boot, kernel reads the RTC • Initialize the wall time (in struct timespec xtime)
Timer Interrupt Handler • The architecture-dependentroutine • Acknowledge or reset system timer as required • Periodically save the updated wall time to the RTC • Call the architecture-independent timer routine, do_timer() • The architecture-independentroutine • jiffies++ • Update the wall time • Update resource usages • Run any dynamic timers that have expired • Calculate load average
Timer Interrupt Handler 1 if user mode 0 if kernel mode void do_timer(struct pt_regs *regs) { jiffies_64++; /* increment jiffies */ update_process_times(user_mode(regs)); update_times(); } p->utime += user; p->stime += system; void update_process_times(int user_tick) { struct task_struct *p = current; int cpu = smp_processor_id(), system = user_tick ^ 1; update_one_process(p, user_tick, system, cpu); run_local_timers(); /* marks a softirq */ scheduler_tick(user_tick, system); /* decrements the currently running process’s timeslice and sets need_resched if needed */ } static inline void update_times(void) { unsigned long ticks; ticks = jiffies - wall_jiffies; if (ticks) { wall_jiffies += ticks; update_wall_time(ticks); } calc_load(ticks); }
The Time of Day • The wall time • xtime.tv_sec value stores the number of seconds that have elapsed since January 1, 1970 (epoch) • xtime.tv_nsec value stores the number of nanosecndsthat have elapsed in the last second struct timespec xtime; strut timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };
Timers • Timers --- eg “run fA() every 250 ms.” • Kernel code often needs to delay execution of some function until a later time • e.g.) bottom half mechanisms • How to use timers • Initial setup • Specify expiration time • Specify function to execute upon said expiration • Activate the timer
Timers • Timer structure struct timer_list { struct list_head entry; /* timers are part of linked list */ unsigned long expires; /* expiration value, in jiffies */ spinlock_t lock; /* lockprotecting this timer */ void (*function)(unsigned long); /* the timer handler function*/ unsigned long data; /* lone argument to the handler */ };
Timers • Using Timers • Define timer • Initialize the timer’s internal values • Fill out the remaining values as required • Activate the timer struct timer_list my_timer; init_timer(&my_timer); my_timer.expires = jiffies + delay; /* timer expires in delay ticks */ my_timer.data = 0; /* zero is passed to timer handler */ my_timer.function = my_function; /* function to run when timer expires */ add_timer(&my_timer);
Delaying Execution set_current_state (TASK_INTERRUPTIBLE); /* put the task to sleep */ schedule_timeout (s * HZ); signed long schedule_timeout(signed long timeout) { struct timer_list timer; /* create timer */ unsigned long expire; expire = timeout + jiffies; init_timer(&timer); /* initialize the timer */ timer.expires = expire; timer.data = (unsigned long) current; timer.function = process_timeout; add_timer(&timer); /* activate the timer */ schedule(); /* call schedule() */ del_timer_sync(&timer); timeout = expire - jiffies; return timeout < 0 ? 0 : timeout; } • Schedule_timeout() static void process_timeout(unsigned long __data) { wake_up_process((task_t *)__data); }
Other Ways to Delay Execution • Busy Looping (as soon as …) unsigned long delay = jiffies + 10; /* ten ticks */ while (time_before(jiffies, delay)); • Small Delays (micro-, or milli- seconds) void udelay(unsigned long usecs); void mdelay(unsigned long msecs); udelay(150); /* delay for 150 us