chapter 6 timing measurements - osnet.cs.nchu.edu.tw

Post on 18-Dec-2021

4 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Chapter 6Timing Measurements

Chapter 6Chapter 6Timing MeasurementsTiming Measurements

HsungHsung--Pin ChangPin ChangDepartment of Computer ScienceDepartment of Computer ScienceNational Chung Hsing UniversityNational Chung Hsing University

Outline• Hardware Clocks• The Linux Timekeeping Architecture• CPU’s Time Sharing• Updating the Time and Date• Updating System Statistics• Software Timers• System Calls Related to Timing

Measurement

Introductions• Countless computerized activities are

driven by timing measurements• For examples

– Screen saver program– Process switches– ……

Introductions (Cont.)• Two main kinds of timing

measurements performed by kernel– Keeping the current time and date

• For user issued system call: time(), ftime(), and gettimeofday()

• Used by the kernel itself as timestamps for files and network packets

– Maintaining timers• Mechanisms to notify the kernel or a user

program that a certain interval of time has elapsed

Hardware Clocks• On the 80x86 architecture, the kernel

interact with four kinds of clocks– Real Time Clock– Time Stamp Counter– Programmable Interval Timers– The timer of the local APICs in SMP

system

Hardware Clocks (Cont.)• The first two are for keeping track

of the current time of day• The later two are programmed by the

kernel– To issue interrupts at a fixed,

predefined frequency– Crucial for implementing the timers

used by the kernel and user programs

Real Time Clock (RTC)• RTC is independent of the CPU and all

other chips• RTC continues to tick even when the PC is

switched off since it is energized by a small battery

• RTC is capable of issuing periodic interrupts on IRQ8 at frequencies ranging between 2 Hz and 8,192 Hz– Thus, can also be programmed acting as an

alarm clock

Real Time Clock (Cont.)• Linux uses RTC only to drive the time

and date– Process can program the RTC through

/dev/rtc device file– Kernel access RTC through 0x70 and

0x71 ports– Root can set up the clock by executing

the clock system program• Act directly on these two I/O ports

Time Stamp Counter (TSC)

• All 80x86 microprocessor include a CLK input pin– Receive the clock signal of an external

oscillator• Starting from Pentium, recent 80x86

microprocessor include a 64-bit Time Stamp Counter register– A counter that increments at each clock signal

from CLK– Can be read by rdtsc instruction

Programmable Interval Timer (PIT)

• IBM-compatible PCs include a Programmable Interval Timer (PIT)– 8254 CMOS chip using the 0x40~0x43

I/O ports• Issue interrupts forever at some

fixed frequency established by kernel– Called timer interrupts

Programmable Interval Timer (Cont.)

• Linux programs the PIT to issue timer interrupts on the IRQ0 at a 100 Hz frequency– Once every 10 milliseconds– This time interval is called a tick

Programmable Interval Timer (Cont.)

• Shorter ticks result in higher resolution timers– However, require the CPU to spend a large

fraction of its time in Kernel Mode• User programs run slower

• Thus, only very powerful machine can adopt very short ticks and afford the consequent overhead– IA-64

CPU Local Timers• All current Intel CPU include a local

APIC (Advanced Programmable Interrupt Controller)– Offer the CPU local timer

• CPU local timer is a device that can issue one-shot or periodic interrupts– Similar to the PIT

CPU Local Timers• However, a few difference between CPU

local timer and PIT– The APIC’s timer counter is 32-bits, while the

PIT’s timer counter is 16-bits– The local APIC timers sends an interrupt only

to its processor, while the PIT raises a global interrupt which may be handled by any CPU in the system

– The APIC’s timer is based on the bus clock signal. Conversely, the PIT has its own internal clock oscillator

The Linux Timekeeping Architecture

• Linux must carry on several time-related activities– Update the time elapsed since system startup– Update the time and date– Determines how long the current process has

been running, and preempts it if is has exceeded the time allocated to it

– Updates resource usage statistics– Checks whether the interval of time associated

with each software timer has elapsed

The Linux Timekeeping Architecture (Cont.)

• Linux timekeeping architecture– A set of kernel DS and functions related to

the flow of time• In UP

– All time-keeping activities are triggered by interrupts raised by Programmable Interval Timer

• In MP– General activities, e.g., software timers, are

triggered by the interrupted raised by PIT– CPU-specific activities are triggered by

interrupts raised by the local APIC timers

The Linux Timekeeping Architecture (Cont.)

• Linux uses two basic timekeeping functions– One to keep the current time up to date– Another to count the number of

microseconds that have elapsed within the current second• Use the Time Stamp Counter (TSC) if

available and is more precise• Otherwise, read the 8254 Programmable

Interval Timer’s internal oscillator

Timekeeping Architecture in Uniprocessor Systems

• All time-related activities are triggered by the interrupts raised by the PIT on IRQ 0

• When a timer interrupts occurs, divide the hander into– Top half– Bottom half

PIT’s Interrupt Service Routine

• In a timer interrupt is raised, invoke the timer_interrupt() function– If CPU has a TSC register

• Execute the rdtsc instruction to obtain the value in TSC register

• Read 8254, i.e., PIT, to compute and store the delay between the interrupt occurrence and the execution of the ISR

– Used to provide correct time to time(), ftime()…

– Invoke the do_timer_interrupt()

PIT’s Interrupt Service Routine (Cont.)

• Do_timer_interrupt()– Invoke do_timer()– If timer interrupt occurred in Kernel

Mode• Invoke x86_do_profile() ; see later section

– If an adjtimex() system call is issued• Invoke set_rtc_mmss() ;see later section

PIT’s Interrupt Service Routine (Cont.)

• Do_timer(){

jiffies++update_process_time(); mark_bh(TIMER_BH);if ( TO_ACTIVE(tq_timer))

mark_bh(TQUEUE_BH);}

PIT’s Interrupt Service Routine (Cont.)

• Jiffies – A variable stores the number of elapsed

ticks since the system was started• Update_process_timer()

– Check how long the current process has been running

The IMTER_BH Bottom Half

• void timer_bh(void){

update_times();run_timer_list();

}

• Update_times()– Updates the system date, time and current

system load• Run_timer_list()

– Take care of software timers handling

CPU Time Sharing• Each process is allowed a quantum of

time of limited duration• The counter field of the process

descriptor specifies how many ticks left– Updated by update_process_times() in

PIT’s timer interrupt handler

CPU Time Sharing• update_process_times

{……; skipped, mentioned laterif (current->pid)

--current->counter;if (current->counter <= 0) {

current->counter = 0;current->need_resched = 1;

}……; skipped, mentioned later

}

Updating the Time and Date

• On boot, kernel reads the RTC and uses it to initialize the wall time– Stored in xtime variable

struct timespec xtime;struct timespec {

time_t tv_sec; # of seconds elapsed from 1.1.1970long tv_nsec; # of ms. elapsed with the last second

}

• After that, RTC is never used and kernel relies on TIMER_BH to update date and time

Updating the Time and Date (Cont.)

• update _times ;called in TIMER_BH{

write_lock_irq();ticks = jiffies – wall_jiffies;if (ticks)

wall_jiffies += ticksupdate_wall_time(tick);

}write_unlock_irq()calc_load();

}

Updating System Statistics

• The kernel must periodically collect several data used to– Check the CPU resource limit of the

running processes– Computing the average system load– Profiling the kernel code

Checking the Current Process CPU Resource Limit• In update_process_time()

– Update per_cpu_utime and per_cpu_stime field of current’s process descriptor• Store the number of ticks running in User Mode and

Kernel Mode respectively– Check whether the total CPU time (User Mode +

Kernel Mode) limit has been reached• Send SIGXCPU if > rlim[RLIMIT_CPU].rlim_cur• Send SIGKILL if > rlim[RLIMIT_CPU].rlim_max

Keeping Track of System Load

• In calu_load(), which is invoked in update_times()– Calculate average system load in the last

minute, the last 5 minute, and the last 15 minutes• Count the number of processes in the

TASK_RUNNING or TASK_UNINTERRUPTIBLE states

Profiling the Kernel Code• Kernel includes a code profiler to

identifies the hot spots of the kernel– The most frequently executed

fragments of kernel code– To enable code profiler, passing the profile parameter in the booting process

Profiling the Kernel Code (Cont.)

• in x86_do_profile() invoked in do_timer_interrupt()– Check if in Kernel Mode and if yes

• Check the eip value to determine the code segment

Software Timers• Timer

– A software facility allows functions to be invoked at some future moment

• Time-out– A moment at which the time interval

associated with a timer has elapsed

Software Timers (Cont.)• Linux considers two types of timer

– Dynamic timer• Used by kernel

– Interval timer• Used by process in User Mode

Software Timers (Cont.)• Implement a timer is quite easy

– Hold the expires field• Expires = jiffies + ticks;• Tick = timer, e.g., 5 seconds

– Then, in each timer interrupt’s BH• Check if jiffies > expires and if yes, invoke

the time-out function

Software Timers (Cont.)• Note the checking occurs in BH

– Kernel cannot ensure that the timer functions start right at their expiration times

– Not appropriate for real-time applications

Dynamic Timers• Dynamic timer may be dynamically created

and destroyed• DS: struct timer_list {

struct list_head list;unsigned long expires;unsigned long data;void (*function) (unsigned long);

}

Dynamic Timers (Cont.)• To create and activate a dynamic timer

– Create a new timer_list object• struct timer_list my_timer;

– Initialize the object• init_timer(&my_timer);

– Fill out the remaining values• my_timer.expires = jiffies + delay; • my_timer.data = 0;• my_timer.function = my_function;

– Activate the timer• add_timer(&my_timer);

Dynamic Timers (Cont.)• If you want to change the expires values

– mod_timer(&my_timer, jiffies + new_delay);• Once expiration, the kernel automatically removes

it from the list• If you need to deactivate a timer prior to its

expiration– del_timer(&my_timer); // for UP– del_timer_sync(&my_timer); // for MP

Dynamic Timers and Race Conditions

• Dynamic timers are prone to race conditions– Release a resource but a timer acts on this

resources• Sol: stop the timer before releasing the resource

– In MP, another CPU may execute a timer handler while one CPU invoke del_timer()• Use del_timer_sync() instead of del_timer()• Wait until all CPU exit from the timer handler

Dynamic Timers and Race Conditions (Cont.)

– Delete a timer, change its expires values and recreated it againg• del_timer(&my_timer);• my_timer -> expires = jiffies + new_delay;• add_timer(my_timer);• This would result in two control paths

modifies the expires values executed in different CPUs at the same time in MP

• Use mod_timer() instead

Dynamic Timer Handling• Choosing a proper DS to implement

dynamic timer is important– String all timers in a single list

• Scan operation is costly– Maintain a sorted list of timers

• Insertion and deletion operations would also be costly

Dynamic Timer Handling (Cont.)

• Kernel partitions the expires values into blocks of ticks

• The details are skipped!

An Application of Dynamic Timers

• In some cases, the kernel may suspend a process for a time interval and it executes the following code

timeout = x;set_current_state(TASK_INTERRUPTIBLE);remaining = schedule_timeour(timeout);

An Application of Dynamic Timers (Cont.)

• in schedule_timeout(){

struct timer_list timer;expire = timeout + jiffies;init_timer(&timer);timer_expires = expire;timer_data = (unsigned long) current;timer.function = process_timeout;add_timer(&timer);schedule();del_timer_sync(&timer);timeout = expire – jiffies;return (timeout < 0 ? 0 : timeout)

}

An Application of Dynamic Timers (Cont.)

• process_timeout(unsigned long data){

struct task_struct * p = (struct task_struct *) data;wake_up_process(p);

}

System Calls Related to Timing Measurements

• The time(), ftime(), and gettimeofday() System Calls

• The adjtimex() System Calls• The setitimer() and alarm() System

Calls

The time(), ftime(), and gettimeofday() System Calls

• time()– Return the number of elapsed seconds

since midnight at the start of 1.1.1970• ftime()

– Return, in a DS of type timeb, the number of elapsed seconds since midnight of 1. 1.1970 and the number of elapsed milliseconds in the last second

The time(), ftime(), and gettimeofday() System Calls

• gettimeofday()– Return, in a DS named timeval, the

number of elapsed seconds since midnight of 1. 1. 1970

• The detailed implementation is skipped!!!

The adjtimex() System Call

• adjtimex()– Receives a pointer to a timex structure– Updates kernel parameters from the

values in the timex fields– Return the same structure with current

kernel values

The setitimer() and alarm() System Calls

• User Mode processes can activate special timers called interval timers– Cause Unix signals to be sent

periodically to the process– Or activate an one-shot interval timer

The setitimer() and alarm() System Calls (Cont.)

• Accuracy applies to these timers– Guaranteed to be executed after the

requested time has elapsed– But impossible to predict exactly when

they will be delivered

The setitimer() and alarm() System Calls (Cont.)

• In setitimer() system call, the first parameters specifies– ITIMER_REAL

• The actual elapsed time; • The process receives SIGALRM signals

– ITIMER_VIRTUAL• The time spent by the process in User Mode; • The process receives SIGVTALRM signals

– ITIMER_PROF• The time spent by process in User and Kernel Mode• The process receives SIGPROF signals

The setitimer() and alarm() System Calls (Cont.)

• ITIMER_REAL– Implemented by dynamic timer– Thus, the process descriptor includes a real_timer

object• ITIMER_VIRTUAL and ITIMER_PROF

– Do not require dynamic timer since they can be updated while the process is running

– Update relative values in process descriptor in timer interrupt handler, i.e., every tick

The setitimer() and alarm() System Calls (Cont.)

• alarm() system call – Send a SIGALRM signal when a

specified time interval has elapsed– Similar to the setitimer() with

ITIMER_REAL parameter• Also use real_time dynamic timer

– Thus, alarm() and setitimer() with ITIMER_REAL parameter cannot be used at the same time

top related