440 likes | 703 Views
Kernel Timers. Goals . Learn how to study kernel code. Learn how kernel implements interval timers. Learn how signals work in Linux. Create a user-space mechanism to measure the execution time of a multithreaded program. Kernel Timers. Overview .
E N D
Kernel Timers • Goals. • Learn how to study kernel code. • Learn how kernel implements interval timers. • Learn how signals work in Linux. • Create a user-space mechanism to measure the execution time of a multithreaded program. Applied Operating System Concepts
Kernel Timers • Overview. • Kernel keeps the current time by reading a clock device • maintains a kernel variable with the current time • User-mode programs can access current time via system calls. • gettimeofday( ) is the usual interface to the current time. • kernel uses current time to determine when currently running process should be removed from CPU. • kernel also uses the current time to keep track of user mode/supervisor mode time for process. Applied Operating System Concepts
clocks • 4 clocks used in Linux • Real Time Clock (RTC) • Time Stamp Counter • Programmable Interval Timer • Timer of the local APICs (Advanced Programmable Interrupt Controller) in SMP systems. Won’t cover here. Applied Operating System Concepts
clocks • Real Time Clock (RTC) • Regular clock that runs on a battery • Often the Motorola 146818: CMOS RAM + RTC • Capable of issuing periodic interrupts on IRQ8 • So it can also work as an alarm clock • But not used for interrupts, instead PIT is used • Linux uses only to derive time and date • Processes can program RTC by acting on the /dev/rtc device file • Kernel accesses the RTC through 0x70 and 0x71 I/O ports • SysAd can set up clock via clock system call (acts on these two I/O ports) Applied Operating System Concepts
clocks • Time Stamp Counter (TSC) • All 80x86 microprocessors include a CLK input pin which receives the clock signal of an external oscillator • Starting with the Pentium, 80x86 processors include a 64-bit Time Stamp Counter (TSC) • Can be read with rdtsc assembly language instruction. • The register is a counter that is incremented at each clock signal • If the clock ticks at 400MHz, TSC is incremented once every 2.5 nanoseconds. • Allows Linux to get more accurate time measurements than delivered by the Programmable Interval Timer. • Linux must determine the clock signal frequency while initializing the system. • Done during boot Applied Operating System Concepts
clocks • Programmable Interval Timer (PIT) • PIT acts as the alarm clock of the system • Usually implemented by a 8254 CMOS chip • Uses I/O ports 0x40-0x43 • Linux uses the PIT to issue timer interrupts on IRQ0 at about 100-Hz frequency (every 10 milliseconds). • The timer interval is called a tick and is stored in the variable tick • Tradeoff: shorter ticks, faster kernel response time, smoother multimedia, etc. • But then more CPU time is spent handling interrupts • Alpha and IA-64: 1,024 interrupts/second (~1 millisecond) Applied Operating System Concepts
Kernel Time • Beginning of UNIX epoch: 12A.M. January 1, 1970 (00:00:00 Greenwich Meridian Time (GMT)). • actually is a skip second. Doesn’t exist! • Kernel uses two long int variables: • number of seconds since beginning of epoch • number of microseconds since beginning of last second Applied Operating System Concepts
Kernel Time • To read time from user space: #include <sys/time.h. struct timeval theTime; gettimeofday(&theTime, NULL); where struct timeval{ long tv_sec; long tv_usec; }; Applied Operating System Concepts
Kernel Time • call gettimeofday(&theTime, NULL); • on return the variable theTime.tv_sec contains number of seconds since beginning of epoch • the variable theTime.tv_usec contains number of microseconds that have elapsed since last second began. • the date command translates kernel time to local time and to Gregorian calendar time epoch. Applied Operating System Concepts
Kernel Time • gettimeofday(&theTime, NULL); • uses sys_gettimeofday( ) in file …/kernel/time.c • Also see do_gettimeofday( ) in file …/arch/i386/kernel/time.c Note that the …/ indicates the path to the source on your computer. Usually is /usr/src/linux Applied Operating System Concepts
Kernel Time • Computing time. • All modern computers use same basic approach for keeping track of time. • Hardware has timer device. • can interrupt every K time units. • For Linux K set to 10 milliseconds. • System tracks time by counting number of interrupts that have occurred since system was booted. • If know when machine was last booted, can compute time to nearest 10 milliseconds. • Know when machine was last booted via a time-of-day clock in i386 machines. Runs with a battery. Applied Operating System Concepts
0. clock interrupt 1. calls 2. updates 3. marksTIMER-BH for execution in timer bottom half (ie, ret_from_sys-call) 4. bottom half calls 5. updates system timer (using jiffies) and stores in kernel variable struct timeval xtime 6. updates per process timers Updating Kernel Time bottom half arch/i386/kernel/time.c Clock ISR timer_interrupt( ) kernel variable kernel/sched.c jiffies do-timer(…) kernel/sched.c timer_bh(…) TIMER_BH update_times(…) update_process_times(…) Applied Operating System Concepts
0. clock interrupt 1. calls 2. updates ++jiffies 5. marksTIMER-BH for execution in timer bottom half (ie, ret_from_sys-call) 3. updates ++lost_ticks 4. updates ++lost_ticks_system mark_bh(void) Updating Kernel Time arch/i386/kernel/time.c Clock ISR timer_interrupt( ) lost_ticks counts number of ticks since the last time the itimer was checked in the bottom half kernel variable kernel/sched.c jiffies do-timer(…) lost_ticks lost_ticks_system TIMER_BH Applied Operating System Concepts
6. calls Updating Kernel Time kernel variables ret_from_sys-call(…) TIMER_BH jiffies 7. updates system wide timers kernel/sched.c timer_bh(void) run_old_timers(…) run_timer_list(…) lost_ticks 8. calls update_times(…) lost_ticks_system 9. update_times gets user ticks and system ticks since last timer interrupt Applied Operating System Concepts
Updating Kernel Time kernel/sched.c update_times(…) update_wall_time(ticks) 11. also calls update_process-times passes arguments ticks and system 10. updates system time (using ticks) and stores in kernel variable struct timeval xtime ticks represent number of timer interrupts during user time system represents number of timer interrupts during system time update_process_times(…) 13. calculates user/system ticks and calls counter 12. updates counter for this process. When counter expires, time slice is up. update_one_process(…) PCB variable 14. compares user ticks to processes it_virt_value and raises SIGTALRM if bigger 15. does same with system ticks and it_prof_value and raises SIGTPROF if bigger Applied Operating System Concepts
Per Process Timers • kernel accumulates time and manages timers for each process. • Per process time values are saved in process’s descriptor. • When kernel creates a task • allocates a new task descriptor of type struct task_struct • allocated from the kernel’s heap space • uses kmalloc()call. Applied Operating System Concepts
Per Process Timers • struct task_struct contains more than 75 fields struct task_struct{ …… long counter; … … unsigned long policy, 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 timer_list real_timer; // contains tms_utime,tms_stime,tms_cutime, tms_cstime unsigned long start_time; long per_cpu_utime[NR_CPUS],per_cpu_stime[],cutime,cstime; }; Applied Operating System Concepts
Per Process Timers • Fields are updated in the update_process_times()function located in kernel/sched.c • This function is invoked as part of the ret_from_sys_call bottom half processing. • This function callsupdate_one_process() • update_one_process()calls other functions to update the values and decide if a signal should be raised to indicate that a timer has expired. • The counter field of the task_struct structure is used to determine whether the process needs scheduling attention. Applied Operating System Concepts
Per Process Timers • Interval timers (it_XXX_value and it_XXX_incr) • use the kernel time to keep track of 3 different intervals of time: • ITIMER_REAL Reflects the passage of real time. • ITIMER_VIRTUAL Reflects the passage of virtual time (i.e., in user mode) • ITIMER_PROF is the total time the process is running (i.e., in both user and kernel mode) • The it_XXX_incr field stores the interval in ticks between two signals • The it_XXX_value field stores the current value of the timer. Applied Operating System Concepts
Per Process Timers • Interval timers (it_XXX_value and it_XXX_incr) • use the kernel time to keep track of 3 different intervals of time: • ITIMER_REAL Reflects the passage of real time. • Implemented using it_real_value and it_real_incr fields. • these values are updated each time a process is triggered in the scheduler • when time expires, a SIGALRM is raised. Applied Operating System Concepts
Per Process Timers • Interval timers (it_XXX_value and it_XXX_incr) • ITIMER_VIRTUAL Reflects the passage of virtual time. • This is time during which the process is active but is not in a system call (system mode) • This time is incremented only when the corresponding process is executing. • updated by the do_timer( ) routine • when it expires, raises a SIGVTALRM. • Implemented using it_virt_value and it_virt_incr fields. Applied Operating System Concepts
Per Process Timers • Interval timers (it_XXX_value and it_XXX_incr) • ITIMER_PROF is the total time the process is running. • Reflects the passage of time during which the process is active (virtual time) plus the time that the kernel is doing work on behalf of the process (eg, reading a timer). • when this timer expires it sends a SIGPROFsignal. Applied Operating System Concepts
Per Process Timer • Each timer is actually a countdown timer • periodically initialized to a prescribed value • then reflects the passage of time by counting down to 0 • when timer reaches 0, raises a signal to notify another part of the system (in the OS or user-space program) • then resets the value and begins counting down again Applied Operating System Concepts
Per Process Timer • Each timer initialized with setitimer()system call: #include <sys/time.h> setitimer(int timerType, const struct itimerval *value, struct itimerval *oldValue); The value type is wrong in the book. Applied Operating System Concepts
Per Process Timer • Each timer initialized with setitimer()system call: The struct itimerval includes the following fields: strut itimerval{ struct timeval it_interval; struct timeval it_value; }; Applied Operating System Concepts
Per Process Timer • Idea of setitimer(int timerType, const struct itimerval *value, struct itimerval *oldValue); • ITIMER_REAL, ITIMER_VIRTUAL, ITIMER_PROF are constants defined in the sys/time.h file. • timerType parameter is set to one of these • value parameter is used to initialize second and microsecond fields of the given timer. • it_value field of value defines the current value for the timer, ie, the the initial value of the timer. • it_interval field of value defines the value that should be used to reset the timer when it reaches zero. • Each of these two parameters has fields tv_sec and tv_usec • oldVal is used to return the previous value of the timer. Applied Operating System Concepts
Per Process Timer • Read a timer with getitimer()system call: #include <sys/time.h> getitimer(int timerType, const struct itimerval *value); • Idea of getitimer() • ITIMER_REAL, ITIMER_VIRTUAL, ITIMER_PROF are constants defined in the sys/time.h file. • timerType parameter is set to one of these • value parameter is used to return the value of the given timer (fields tv_sec and tv_usec) Applied Operating System Concepts
Setting and Reading a Timer • Code fragment to set ITIMER_REAL and then read it. #include <sys/time.h> struct itimerval v; v.it_interval.tv_sec=9; v.it_interval.tv_usec=999999; v.it_val.tv_sec=9; v.it_val.tv_usec=999999; setitimer(ITIMER_REAL,&v,NULL); Applied Operating System Concepts
Setting and Reading a Timer • Code fragment to read ITIMER_REAL #include <sys/time.h> struct itimerval v; getitimer(ITIMER_REAL,&v); printf(“…%d seconds, %d microsections……” ,…,v.it_value.tv_sec,v.it_value.tv_usec,…); Applied Operating System Concepts
Project 3 • Part A. Use ITIMER_REAL to implement a function that works like gettimeofday() • Raise a signal once per second • Use the signal facility to determine when ITIMER_REAL has been decremented to 0 and to count the number of seconds that have elapsed. Applied Operating System Concepts
Project 3 • Part B. Design and implement facilities that use the ITIMER_VIRTUAL and ITIMER_PROF interval timers to profile a process • profile provides actual time of execution (use the timer from part A) • also provides CPU time (time that the process is actually running) • also provides user-space time • also provides kernel-space time • Use gettimeofday()to compute the program’s”wall clock” runtime. Applied Operating System Concepts
Project 3 • Part B (cont) • all times must have millisecond accuracy (to the extent the hardware supports it) • Code for millisecond accuracy, may not get it. • Use the signal facility to create signal handlers to keep track of the number of seconds of virtual and profile time • raise a signal once per second. Applied Operating System Concepts
Project 3 • Part C Spawn three children. • Each child must recursively compute the Fibonacci sequence for N= 20, 30, 36 • Fibonacci code given in the outline for the solution. • May take several minutes to compute N=36 • Use the facilities from part A and B to determine real time, virtual time, profile time for each of the three process. Applied Operating System Concepts
Linux Source Code • Read the code to understand how interval timers work. /usr/src/linux Architecture dependent code kept in this directory net modules arch drivers mm block Most code kept in the directories shown lib alpha char m68k kernel fs i386 ipc kernel mm …. Heart of kernel code kept here ext2 fat proc init include Applied Operating System Concepts
Linux Source Code • Read the code to understand how interval timers work. /usr/src/linux Architecture dependent code kept in this directory net modules arch drivers mm block Most code kept in the directories shown lib alpha char m68k kernel fs i386 ipc itimer.c is only here kernel mm …. ext2 fat proc init process.c is also here process.c is here include Applied Operating System Concepts
Solution outline #include <sys/time.h> #include <signal.h> #include <unistd.h> #include <stdio.h> long unsigned int fibonacci(unsigned int n); static long p_realt_secs=0, c1_realt_secs=0, c2_realt_secs=0; static long p_virtt_secs=0, c1_virtt_secs=0, c2_virtt_secs=0; static long p_proft_secs=0, c1_proft_secs=0, c2_proft_secs=0; static struct itimerval p_realt, c1_realt, c2_realt; static struct itimerval p_virtt, c1_virtt, c2_virtt; static struct itimerval p_proft, c1_proft, c2_proft; Applied Operating System Concepts
Solution outline main(int argc, char **argv){ long unsigned fib = 0; int pid1, pid2; unsigned int fibarg; int status; // Get command line argument, fibarg // Initialize parent, child1, child 2, and child 3 timer values // Enable your signal handlers for the parent signal(SIGALRM,… ); signal(SIGVTALRM,… ); signal(SIGPROF,… ); // Set the parent's itimers Applied Operating System Concepts
Solution outline pid1 = fork(); if (pid1 == 0){ // Enable child 1 signal handlers (disable parent handlers) // Set the child 1 itimers // Start child 1 on the Fibonacci program fib = fibonacci(fibarg); // Read the child 1 itimer values, and report them getitimer(ITIMER-PROF, ); getitimer(ITIMER-REAL, ); getitimer(ITIMER-VIRTUAL, ); Applied Operating System Concepts
Solution outline printf("\n"); printf("Child 1 fib = %ld, real time = %ld sec, %ld msec\n",fib, c1_realt_secs, elapsed_usecs(c1_realt.it_value.tv_sec,c1_realt.it_value.tv_usec)/1000); printf("Child 1 fib = %ld, cpu time = %ld sec, %ld msec\n",fib, c1_proft_secs, elapsed_usecs(c1_proft.it_value.tv_sec,c1_proft.it_value.tv_usec)/1000); printf("Child 1 fib = %ld, user time = %ld sec, %ld msec\n",fib, c1-proft_secs - c1_virtt_secs, elapsed_usecs(c1_virtt.it_value.tv_sec,c1_virtt.it_value.tv_usec)/1000); printf("Child 1 fib = %ld, kernel time = %ld sec, %ld msec\n",fib, c1_proft_secs, (elapsed_usecs(c1_proft.it_value.tv_sec,c1_proft.it_value.tv_usec)/1000) - (elapsed_usecs(c1_virtt.it_value.tv_sec,c1_virtt.it_value.tv_usec)/1000)); fflush(stdout); exit(0); } // end of child code Applied Operating System Concepts
Solution outline else{ pid2 = fork(); if (pid2 == 0){ // Enable child 2 signal handlers (disable parent handlers) // Set the child 2 itimers // Start child 2 on the Fibonacci program fib = fibonacci(fibarg); // Read the child 2 itimer values, and report them // lots more print statements } // end of if else{ // do the third child stuff } // end else } // end of else Applied Operating System Concepts
Solution outline else{ /* this is the parent */ // Start the parent on the Fibonacci program fib = fibonacci(fibarg); // Wait for the children to terminate waitpid(0, &status, 0); waitpid(0, &status, 0); waitpid(0, &status, 0); // Read the parent itimer values and report them // lots of print statements } } // end of main Applied Operating System Concepts
Solution outline long unsigned int fibonacci(unsigned int n){ if (n == 0) return 0; else if (n == 1 || n == 2) return 1; else return (fibonacci(n-1) + fibonacci(n-2)) } Applied Operating System Concepts