timer

advertisement
제46강 : Timers and Time Management
Ch 10 Timers and Time Management
1
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)
tick
• jiffies
– number of ticks since system boot
– global variable
• jiffies-Hz-Time
– To convert from [seconds to jiffies]
1000 Hz
100 Hz
• (second * HZ)
– To convert from [jiffies to seconds]
Jiffies
• (jiffies / HZ)
2
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
3
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 continues even when the system is off (small battery)
On boot, kernel reads the RTC
Initialize the wall time (in struct timespec xtime)
4
Timer Interrupt Handler
• The architecture-dependent routine
– 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-independent routine
–
–
–
–
–
jiffies++
Update the wall time
Update resource usages
Run any dynamic timers that have expired
Calculate load average
5
Timer Interrupt Handler
void do_timer(struct pt_regs *regs)
{
jiffies_64++; /* increment jiffies */
update_process_times(user_mode(regs));
update_times();
}
1 if user mode
0 if kernel mode
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);
}
6
The Time of Day
• The wall time
struct timespec xtime;
strut timespec {
time_t tv_sec;
long
tv_nsec;
};
/* seconds */
/* nanoseconds */
– 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 nanosecnds
that have elapsed in the last second
7
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
8
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;
/* lock protecting this timer */
void (*function)(unsigned long);
/* the timer handler function */
unsigned long data;
/* lone argument to the handler */
};
9
Timers
• Using Timers
– Define timer
struct
timer_list my_timer;
– Initialize the timer’s internal values
init_timer(&my_timer);
– Fill out the remaining values as required
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 */
– Activate the timer
add_timer(&my_timer);
10
Delaying Execution
• Schedule_timeout()
set_current_state (TASK_INTERRUPTIBLE);
schedule_timeout (s * HZ);
/* put the task to sleep */
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;
}
static void process_timeout(unsigned long __data)
{
wake_up_process((task_t *)__data);
}
11
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
12
Download