Timers
Time is kept relative to a particular point in time:
Jan 1, 1970 GMT
Two kernel counters: one for the seconds since...
Code
#include <sys/time.h>
structu timeval theTime;
gettimeofday(&theTime, NULL);
struct timeval { long tv_sec; long tv_us...
System code
You can read the system code in kernel/time.c
(if you are looking at linux, you'll realy need to
look in the a...
time of day clock
i386 has a time of day clock (this may run
continuously or may be set at system boot
time). Although it ...
10 millisecond clock
The hardware has a programmable time that
can be set to issue an interrupt every k time
units: in Lin...
Updating the system clock
the interrupt service routine for the clock
(timer_interrupt) calls the do_timer function in
ker...
Task Control
ret_from_sys_call
this is a standard set of tasks to complete
(dispatch) any accumulated system work:
−   pending signals
...
slow
slow interrupts have more to do. So the ISR is
divided into two pieces: the “upper” half that is
“fast”, so interrupt...
timer bottom half
time bottom half activities:
−   system timer updates
−   per process time updates
−   stores the value ...
Per process timers
kernel needs to maintain time spent by each
process
timer info saved in the process's descriptor
when a...
struct task_struct {
...
long counter;
...
unsigned long polkicy, rt_priority;
unsigned long it_real_value, it_prof_value,...
// in timer.c (bottom half processing)

/*
 * Called from the timer interrupt handler to charge one tick to the current
 *...
static inline void do_it_prof(struct task_struct *p)
{
   unsigned long it_prof = p->it_prof_value;

    if (it_prof) {
  ...
static inline void do_it_virt(struct task_struct * p, unsigned long ticks)
{
   unsigned long it_virt = p->it_virt_value;
...
static inline void do_process_times(struct task_struct *p,
   unsigned long user, unsigned long system)
{
   unsigned long...
void update_one_process(struct task_struct *p, unsigned long user,
       unsigned long system, int cpu)
{
  do_process_ti...
itimers
the itimers use kernel time to keep track of
−   itimer real: passage of real time
−   itimer virtual: passage of ...
Initializing timers
setitimer (do a man)
int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *value, struct itimer-
...
Timer values are defined by the following structures:

   struct itimerval {
      struct timeval it_interval; /* next val...
itimers
two values:
−   current value
−   interval: value to initialize the counter: it's a
    countdown)
getitimer
getitimer reads the value of a timer
#include <sys/time.h>

struct itimerval v;

v.it_interval.tv_sec = 9;
v.it_interval.tv_usec = 999999;

v.it_value.tv_sec =...
Signals
A signal will be sent when a timer “runs out”. In
order to make use of this, you need to set your
own signal handl...
How to add a handler


 signal(SIGALRM, p_realt_handler);
 signal(SIGVTALRM, p_virtt_handler);
 signal(SIGPROF, p_proft_ha...
which signals?
a signal can be sent from one process to
another
do a man 7 signal to see all the signals
You can use a sig...
my sigA
check sigA.c for an example of setting a handler
(his version has a “race” condition.
doing Part A
Your part A should just set a real itimer to raise
a signal once every second.
You should define a handler th...
Upcoming SlideShare
Loading in …5
×

Timers in Unix/Linux

13,453 views

Published on

Published in: Technology, Economy & Finance
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
13,453
On SlideShare
0
From Embeds
0
Number of Embeds
482
Actions
Shares
0
Downloads
101
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Timers in Unix/Linux

  1. 1. Timers Time is kept relative to a particular point in time: Jan 1, 1970 GMT Two kernel counters: one for the seconds since Jan 1, 1970 and one for the microseconds since Jan 1, 1970
  2. 2. Code #include <sys/time.h> structu timeval theTime; gettimeofday(&theTime, NULL); struct timeval { long tv_sec; long tv_usec;}
  3. 3. System code You can read the system code in kernel/time.c (if you are looking at linux, you'll realy need to look in the appropriate arch directory.) For tv_usec to correct, it needs to be incremented once every microsecond. The system can track the passage of time by counting the number of interrupts that have occurred since system boot.
  4. 4. time of day clock i386 has a time of day clock (this may run continuously or may be set at system boot time). Although it may not have the accuracy desired, it can be used as the base for incrementing the 10-millisecond clock.
  5. 5. 10 millisecond clock The hardware has a programmable time that can be set to issue an interrupt every k time units: in Linux this is set to 10 milliseconds. So the gettimeofday function determines how many microseconds and seconds have passed since the time of day clock. when is the system clock updated?
  6. 6. Updating the system clock the interrupt service routine for the clock (timer_interrupt) calls the do_timer function in kernel/sched.c (scheduler related functions). This increment the jiffies counter each time it runs and marks a counter (TIMER_BH) for execution in the ret_from_sys_call . For an overview of the sequence of events in the case of an interrupt see p 26 (Sec 4.1.1)
  7. 7. Task Control
  8. 8. ret_from_sys_call this is a standard set of tasks to complete (dispatch) any accumulated system work: − pending signals − pending interrupt tasks − schedule other tasks slow vs fast: fast interrupts don't do much work, so interrupts are disabled. That means no further work will need to be done.
  9. 9. slow slow interrupts have more to do. So the ISR is divided into two pieces: the “upper” half that is “fast”, so interrupts can be disabled, and the “lower” half, which is “slow”, but the tasks do not require non-interruptable status. These defered tasks can be scheduled later. Since the kernel is really “multi-threaded”, more than one ISR may have run with postponed bottom half events: these are all handled when the bottom half is scheduled.
  10. 10. timer bottom half time bottom half activities: − system timer updates − per process time updates − stores the value in the struct timeval
  11. 11. Per process timers kernel needs to maintain time spent by each process timer info saved in the process's descriptor when a new task is created, the kernel create's a new task_struct the task_struct contains all the process specific info, some of which is time info:
  12. 12. struct task_struct { ... long counter; ... unsigned long polkicy, rt_priority; unsigned long it_real_value, it_prof_value, it_virt_value; unsigned long it_real_incr, it_prof_incr, it_virt_incr; struct time_list real_timer; // contains tms_utime, tms_stime. tmx_cstime struct tms; unsigned long start_time; long per_cpu_utime[NR_CPUS], per_cpu_stime[], cutime, cstime; ... }
  13. 13. // in timer.c (bottom half processing) /* * Called from the timer interrupt handler to charge one tick to the current * process. user_tick is 1 if the tick is user time, 0 for 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(); scheduler_tick(user_tick, system); }
  14. 14. static inline void do_it_prof(struct task_struct *p) { unsigned long it_prof = p->it_prof_value; if (it_prof) { if (--it_prof == 0) { it_prof = p->it_prof_incr; send_sig(SIGPROF, p, 1); } p->it_prof_value = it_prof; } }
  15. 15. static inline void do_it_virt(struct task_struct * p, unsigned long ticks) { unsigned long it_virt = p->it_virt_value; if (it_virt) { it_virt -= ticks; if (!it_virt) { it_virt = p->it_virt_incr; send_sig(SIGVTALRM, p, 1); } p->it_virt_value = it_virt; } }
  16. 16. static inline void do_process_times(struct task_struct *p, unsigned long user, unsigned long system) { unsigned long psecs; psecs = (p->utime += user); psecs += (p->stime += system); if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_cur) { /* Send SIGXCPU every second.. */ if (!(psecs % HZ)) send_sig(SIGXCPU, p, 1); /* and SIGKILL when we go over max.. */ if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_max) send_sig(SIGKILL, p, 1); } }
  17. 17. void update_one_process(struct task_struct *p, unsigned long user, unsigned long system, int cpu) { do_process_times(p, user, system); do_it_virt(p, user); do_it_prof(p); }
  18. 18. itimers the itimers use kernel time to keep track of − itimer real: passage of real time − itimer virtual: passage of virtual time (only when the process is running) − itimer prof: time the the process is actually running and the time that the kernel is doing work on the process's behalf (countdown timers)
  19. 19. Initializing timers setitimer (do a man)
  20. 20. int getitimer(int which, struct itimerval *value); int setitimer(int which, const struct itimerval *value, struct itimer- val *ovalue); The system provides each process with three interval timers, each decrementing in a distinct time domain. When any timer expires, a sig- nal is sent to the process, and the timer (potentially) restarts. ITIMER_REAL decrements in real time, and delivers SIGALRM upon expi- ration. ITIMER_VIRTUAL decrements only when the process is executing, and delivers SIGVTALRM upon expiration. ITIMER_PROF decrements both when the process executes and when the system is executing on behalf of the process. Coupled with ITIMER_VIRTUAL, this timer is usually used to pro- file the time spent by the application in user and ker- nel space. SIGPROF is delivered upon expiration.
  21. 21. Timer values are defined by the following structures: struct itimerval { struct timeval it_interval; /* next value */ struct timeval it_value; /* current value */ }; struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };
  22. 22. itimers two values: − current value − interval: value to initialize the counter: it's a countdown)
  23. 23. getitimer getitimer reads the value of a timer
  24. 24. #include <sys/time.h> struct itimerval v; v.it_interval.tv_sec = 9; v.it_interval.tv_usec = 999999; v.it_value.tv_sec = 9 v.it_value.tv_usec = 999999; setitimer(ITIMER_REAL, &v, NULL); getitimer(ITIMER_REAL, &v); printf(quot;... %ld seconds, $ld microseconds ...quot;, ..., v.it_value.tv_sec, v.it_value.tv_usec, ...); ...
  25. 25. Signals A signal will be sent when a timer “runs out”. In order to make use of this, you need to set your own signal handler. this means that you define a function that will be scheduled (invoked) when the signal is received. It's the user version of an ISR.
  26. 26. How to add a handler signal(SIGALRM, p_realt_handler); signal(SIGVTALRM, p_virtt_handler); signal(SIGPROF, p_proft_handler);
  27. 27. which signals? a signal can be sent from one process to another do a man 7 signal to see all the signals You can use a signal for arbitrary events (though there are better ways to indicate an event and coordinate actions among processes) Specific SIGALRM: SIGPROF, SIGVTALRM, SIGALRM
  28. 28. my sigA check sigA.c for an example of setting a handler (his version has a “race” condition.
  29. 29. doing Part A Your part A should just set a real itimer to raise a signal once every second. You should define a handler that increments a counter each time it is interrupted. You can integrate this with your shell so that you can do a variety of actions and then check how much time you've used. (*You don't need to convert to actual time of day.)

×