Linux Clock Interrupt

Source: Internet
Author: User

From: In-depth analysis of Linux kernel source code (http://oss.org.cn/kernel-book/)

The generation of clock interrupts

The physical cause of the Linux OS clock is the programmable timing/counter output pulse, which is fed into the CPU and can trigger an interrupt request signal, which we call the clock interrupt.

"Clock interruption" is a particularly important interruption, as the entire operating system is motivated by its activities. The system uses the clock interrupt to maintain the system time, to facilitate the switchover of the environment, to ensure that all processes share the CPU, to use the clock interrupt to account, supervise the system work and determine the future scheduling priorities and so on. It can be said that "clock interruption" is the pulse of the entire operating system.

Physical generation of clock interrupts:


Figure 8253 and 8259A physical connection mode

The operating system on the programmable timing/counter initialization, and then timer/counter on the input pulse count (frequency division), the resulting three output pulses Out0, OUT1, Out2 each have a purpose, many interface books are introduced this problem, we only see the output pulse on the Out0, This pulse signal to the interrupt controller 8259a_1 NO. 0 pin, triggering a periodic interrupt, we will call this interrupt clock interrupt, clock interrupt cycle, that is, the pulse signal period, we call "tick" or "Time Mark" (tick). In essence, a clock interrupt is just a periodic signal, completely hardware behavior, which triggers the CPU to execute an interrupt service program, but for convenience, we call this service program a clock interrupt.

the whole process of clock interruption for Linux 1. Initialization of programmable timing/counter

The IBM PC uses a 8253 or 8254 chip. The detailed knowledge of the chip is not covered in detail, but it is generally described in the following form and function, as shown in table 5.1 below:

Table 8253/8254 the composition and role

Name

Port Address

Working style

The purpose of the resulting output pulses

Counter 0

0x40

Mode 3

Clock interrupt, also called system clock

Counter 1

0x41

Mode 2

Dynamic Memory Refresh

Counter 2

0x42

Mode 3

Speaker Sound

Control Register

0x43

/

For initialization of 8253, receive control word

The output of counter 0 is the Out0 in Figure 5.3, its frequency is determined by the designer of the operating system, and the initialization program segment for Linux on 8253 is as follows (in/ARCH/I386/KERNEL/I8259.C's INIT_IRQ () function):

Set_intr_gate (ox20, interrupt[0]);

/* Insert an interrupt gate in the 0x20 table entry in IDT. The segment selector in this gate is set to the selector of the kernel snippet, and the offset field is set to the entry address of the No. 0 interrupt handler. */

Outb_p (0x34,0x43); /* Write control word for counter 0: Working mode 2*/

Outb_p (LATCH & 0xFF, 0x40); /* Write count initial value LSB count initial low byte */

OUTB (LATCH >> 8, 0x40); /* Write count initial value MSB count initial value high byte */

LATCH (in English means: latch, which is the initial value of the latch counter 0) is the counter 0 count of the initial value, defined in the/include/linux/timex.h as follows:

#define CLOCK_TICK_RATE 1193180/* input pulses in Figure 5.3 */

#define LATCH ((clock_tick_rate + HZ/2)/HZ)/* Counter 0 count Initial */

The clock_tick_rate is the entire 8253 input pulse, shown in 5.3 is 1.193180MHz, is approximately 1MHz square wave signal, 8253 inside of three counters are counting this clock, and then produce different output signal for different purposes.

Hz represents the frequency of the counter 0, which is the clock interrupt or the frequency of the system clock, as defined in/include/asm/param.h:

#define HZ 100

2. Functions related to clock interrupts

Below we look at the clock interrupt triggered by the service program, the program code is more complex, distributed in different source files, mainly including the following functions:

Clock Interrupt Program:timer_interrupt();

Interrupt Service General routine do_timer_interrupt ();

Clock function: Do_timer ();

Interrupt installation program: SETUP_IRQ ();

Interrupt return Function: Ret_from_intr ();

The call relationships for the first three functions are as follows:

Timer_interrupt ( )

Do_timer_interrupt ()

Do_timer ()

(1) Timer_interrupt ( )

This function is called approximately every 10ms, in fact, the timer_interrupt() function is a wrapper routine, and it does not really do much, but, as an interrupt program, it must be executed in the case of a shutdown. If you only consider the case of a single processor, the main statement of the function is to call the Do_timer_interrupt () function.

(2) do_timer_interrupt ()

The Do_timer_interrupt () function has two main tasks, one is to call Do_timer () and the other is to maintain the real-time clock (RTC, write-back every time interval), its implementation code in/ARCH/I386/KERNEL/TIME.C, In order to highlight the theme, the author has rewritten the following functions so that the reader can understand:

static inline void do_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)

{

Do_timer (regs); /* Call the clock function to equate the clock function with the clock interrupt */

if (xtime.tv_sec > last_rtc_update + 660)

UPDATE_RTC ();

/* Update the RTC time information every 11 minutes to keep the OS clock and RTC clock in sync, 11 minutes, 660 seconds, xtime.tv_sec in seconds, Last_rtc_update record the last RTC Update */

}

Where Xtime is the Timeval type mentioned earlier, this is a global variable.

(3) Clock function Do_timer () (in/KERNEL/SCHED.C)

void Do_timer (struct pt_regs * regs)

{

(* (unsigned long *) &jiffies) + +; /* Update the system time, which guarantees the jiffies

Atomic nature of the operation */

Update_process_times ();

++lost_ticks;

if (! User_mode (regs))

++lost_ticks_system;

MARK_BH (TIMER_BH);

if (Tq_timer)

MARK_BH (TQUEUE_BH);

}

where the Update_process_times () function is related to process scheduling, it can be seen from the name of the function that it handles variables related to the current process and time, for example, to update the current process's time slice counter counter, if counter<= 0, to invoke the scheduler, to process all the timers: real-time, virtual, overview, but also to do some statistical work.

There are a lot of time-related things that can't all be done with this function, because this function is executed in the case of an off interrupt, and must be processed out of the most important time information to handle other things. So, other information about time who is going to deal with it, when to deal with it? This is the second part of the discussion in chapter three to deal with. The Timer_interrupt () above (including the function it calls) is the top half.

In this function there are also two variables lost_ticks and Lost_ticks_system, which are used to record the number of times the clock interrupt occurred before the execution of the TIMER_BH (). Because the clock interrupt occurs very frequently (every 10ms), so before timer_bh () execution, there may have been a clock interrupt occurred, and TIMER_BH () to provide timing, charge and other important operations, so in order to ensure the accuracy of time measurement, the use of these two variables. The lost_ticks is used to record the number of times the TIMER_BH () clock interrupt occurred before execution, and if the current process runs in the kernel state when the clock interrupt occurs, the Lost_ticks_system is used to record the number of clock interrupts in the kernel state before the TIMER_BH () execution. This allows for an accurate charge of the current process.

(4) Interrupt installation program

As can be seen from the above introduction, clock interrupt and process scheduling is inseparable, so, once the start of a clock interrupt can be scheduled, when the system is initialized, one of the most of the work done is to initialize the clock, its function time_init () code in/arch/i386/ KERNEL/TIME.C, the abbreviations are as follows:

void __init time_init (void)

{

Xtime.tv_sec=get_cmos_time ();

xtime.tv_usec=0;

SETUP_IRQ (0,&IRQ0);

}

One of the Get_cmos_time () functions is to read the actual time from the CMOS clock chip into the variable xtime, the time accuracy of seconds. and SETUP_IRQ (0,&irq0) is the clock interrupt installation function, then irq0 refers to what it is a structure type irqaction, its definition and initial value are as follows:

static struct Irqaction irq0 = {timer_interrupt, sa_interrupt, 0, "timer", NULL, NULL};

SETUP_IRQ (0, &irq0) code in/ARCH/I386/KERNEL/IRQ.C, its main function is to connect the interrupt program into the corresponding interrupt request queue, in order to wait for the interrupt to arrive when the corresponding interrupt program is executed.

So far, we've just put the clock interrupt program into the interrupt request queue, when to execute, how to execute, this is a complicated process (see chapter III), in order to let the reader have a complete understanding of the clock interrupt, we ignore the intermediate process, and give a whole description. We'll rewrite the function as follows to show the effect of the clock interrupt:

Do_timer_interrupt ()/* This is a pseudo function */

{

Save_all/* Save the Processing machine site */

Intr_count + = 1; /* This operation is not allowed to be interrupted */

Timer_interrupt ()/* Call Clock Interrupt program */

Intr_count-= 1;

JMP RET_FROM_INTR/* Interrupt return function */

}

Where JMP Ret_from_intr is a piece of assembler code and a complex process that ultimately calls the JMP Ret_from_sys_call, the system call return function, which is closely related to the scheduling of the process, so we focus on the JMP ret_ From_sys_call.

3. System call return function:

The system call returns the source code of the function in/arch/i386/kernel/entry. S medium

ENTRY (Ret_from_sys_call)

CLI # need_resched and Signals Atomic test

Cmpl $0,need_resched (%EBX)

Jne Reschedule

Cmpl $0,sigpending (%EBX)

Jne Signal_return

Restore_all:

Restore_all

ALIGN

Signal_return:

STI # we can get here from an interrupt handler

Testl $ (vm_mask), EFlags (%ESP)

MOVL%esp,%eax

Jne V86_signal_return

Xorl%edx,%edx

Call Symbol_name (do_signal)

JMP Restore_all

ALIGN

V86_signal_return:

Call Symbol_name (save_v86_state)

MOVL%eax,%esp

Xorl%edx,%edx

Call Symbol_name (do_signal)

JMP Restore_all

....

Reschedule:

Call Symbol_name (schedule) # test

JMP Ret_from_sys_call

This piece of assembler code is what we call the "return function from System call" Ret_from_sys_call, which is the common interface from interrupts, exceptions, and return of system calls. This code body is the Ret_from_sys_call function that calls some other functions during execution (actually a piece of code, not a real function), where we list several related functions:

(1) Ret_from_sys_call: main body

(2) Reschedule: Check if rescheduling is required

(3) Signal_return: Processing the signal received by the current process

(4) V86_signal_return: Processing the signal received by the current process in virtual 86 mode

(5) Restore_all: We call this function the complete return function, because after executing the function, it is returned to the address space of the current process.

You can see that the main functions of Ret_from_sys_call are:

Check the dispatch flag need_resched, decide whether to execute the dispatcher, handle the signal of the current process, and restore the environment of the current process to make it continue to execute.

Finally, let's look at the clock interrupt in general again:

Each clock ticks, and the clock interrupts are executed. Clock interrupt execution is very high: 100 times/second, the main task of clock interruption is to handle all information related to time, decide whether to execute the scheduler and handle the lower part. All information related to time includes the system time, the time slice of the process, the time of the CPU, the various timers, the time slice after the process update provides the basis for the process scheduling, and then decides whether to execute the scheduler when the clock interrupt returns. The lower part handler is a mechanism provided by Linux that delays the execution of some of the work. Clock interrupts are absolutely guaranteed to maintain system time accuracy, while the second half of this mechanism provides not only this accuracy, but also greatly improves system performance.

Linux Clock Interrupt

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.