Linux drive Study Notes 2-timer

Source: Internet
Author: User
Linux Kernel Timer

I. Definition

/Include/Linux/Timer. h

struct timer_list {struct list_head entry;unsigned long expires;void (*function)(unsigned long);unsigned long data;struct tvec_t_base_s *base;#ifdef CONFIG_TIMER_STATSvoid *start_site;char start_comm[16];int start_pid;#endif};
Ii. Functions

An instance of the timer_list struct corresponds to a timer. in Linux Device Driver Programming, you can use timer_list and some operations (functions) based on it to complete the timed start work or
Complete a periodic task.

Iii. Field details

1. struct list_head entry -- timer linked list, used to store soft timers. This linked list stores them in groups based on the value of the expirex field of the timer.
2. Unsigned long expires -- the expiration time of the timer. After the expiration time reaches the expires time, the timer calls its member function, where the data field is used as the function parameter.
This field indicates that the time is in the unit of time. For example, if you want to schedule a second, expires = jiffies + Hz * 1.

A. For details about jiffies, see

As we know, the operating system should be able to schedule a task on time at a certain time in the future. Therefore, a mechanism is required to ensure that the task runs on time. Microprocessors for each Operating System
It must contain a programmable interval timer that can interrupt it cyclically. This periodic interrupt is called a system clock tick (or system timer). It organizes system tasks like a timer
It is called a clock interruption.

The frequency of clock interruption is set to Hz. Hz is a constant unrelated to the architecture. In the file <Linux/Param. h> as defined in, clock interruption is very important to the operating system.
When this occurs, some functions are periodically executed, such:
. Update the system's uptime
. Update Time of day
. Check whether the time slice of the current task is used up. If yes, the task needs to be rescheduled.
. Execute the expired dynamic Timer
. Update system resource usage statistics and task time statistics

3. Void (* function) (unsigned long) -- the timer processing function. That is, when the expires time is reached, the function will be called and executed. The parameter comes from the data word of the timer.
.
4. Unsigned long data -- when calling the function, this field is used as its parameter.

Iv. Operations

1. Definition and initialization:

Struct timer_list timer;

void init_timer(struct timer_list *timer){      debug_timer_init(timer);       __init_timer(timer);} static void __init_timer(struct timer_list *timer){       timer->entry.next = NULL;       timer->base = __raw_get_cpu_var(tvec_bases);#ifdef CONFIG_TIMER_STATS       timer->start_site = NULL;       timer->start_pid = -1;       memset(timer->start_comm, 0, TASK_COMM_LEN);#endif}

The init_timer () function is defined in kernel/Timer. C. In fact, it sets the next pointer of the timer entry to null and assigns a value to the base field.

(2) -- timer = timer_initializer (function, expires, data );
To use this initialization method, you must first write the timer processing function. timer_initializer macro definition as follows:

#define TIMER_INITIALIZER(_function, _expires, _data) {  \  .entry = { .prev = TIMER_ENTRY_STATIC }, \  .function = (_function),   \  .expires = (_expires),    \  .data = (_data),    \  .base = &boot_tvec_bases,   \ }

Boot_tcec_bases is a global variable of the tvec_t_base_s type defined in kernel/Timer.

(3) -- define_timer (timer, function, expires, data );
Define and initialize the timer, which is equivalent to (2). The define_timer macro is defined:

#define DEFINE_TIMER(_name, _function, _expires, _data)  \ struct timer_list _name =    \  TIMER_INITIALIZER(_function, _expires, _data)

(4) -- setup_timer (& timer );
It is equivalent to the definition method (2) and (3). However, the base field is assigned a value by calling the init_timer () function. The prototype of setup_timer () is:

static inline void setup_timer(struct timer_list * timer,    void (*function)(unsigned long),    unsigned long data){ timer->function = function; timer->data = data; init_timer(timer);}

2. register the Timer:

After the timer is defined and initialized, you need to call the add_timer () function to register the timer to the kernel so that the timer will work. After registration, the timer starts timing.
When the arrival time expires is reached, the callback function (-> data) is executed ). The prototype of the add_timer () function is:

static inline void add_timer(struct timer_list *timer){BUG_ON(timer_pending(timer));__mod_timer(timer, timer->expires);}

3. Delete the Timer:

Int del_timer (struct timer_list * timer );
Delete the registered timer from the kernel. If the timer is active, 1 is returned; otherwise, 0 is returned.

int del_timer(struct timer_list *timer){      tvec_base_t *base;      unsigned long flags;      int ret = 0;      timer_stats_timer_clear_start_info(timer);      if (timer_pending(timer)) {            base = lock_timer_base(timer, &flags);            if (timer_pending(timer)) {                  detach_timer(timer, 1);                  ret = 1;            }            spin_unlock_irqrestore(&base->lock, flags);      }      return ret;}

4. Modify the timer time of the Timer:

int mod_timer(struct timer_list *timer, unsigned long expires){      BUG_ON(!timer->function);      timer_stats_timer_set_start_info(timer);      if (timer->expires == expires && timer_pending(timer))            return 1;      return __mod_timer(timer, expires);}

It can be seen from the code that if the time to be modified is equal to the original time of the timer and the timer is currently active, 1 is not modified. Otherwise, 0 is returned when the timer time is modified.
. Mod_timer () is a non-effective method for updating the Time of the active timer. If the timer is inactive, the timer is activated. In terms of functions, mod_timer () and so on
Price:

del_timer(timer);timer->expires=expires;add_timer(timer);

V. kernel latency Functions

1. short latency:

ndelay(unsigned long nsecs);udelay(unsigned long usecs);mdelay(unsigned long msecs);

The essence of these three macro delays is "busy waiting". That is to say, in the process of delay, the CPU is not abandoned, but the delay is achieved by repeating the frequency of the CPU for a certain number of times. Three macros
In the end, each parameter (Delay Time) is converted to call the delay_loop () function to achieve the delay. delay_loop () is as follows:

static void delay_loop(unsigned long loops){      int d0;      __asm__ __volatile__(            "\tjmp 1f\n"            ".align 16\n"            "1:\tjmp 2f\n"            ".align 16\n"            "2:\tdecl %0\n\tjns 2b"            :"=&a" (d0)            :"0" (loops));}

 

We can clearly see that each time the loops is reduced, and then we can judge that if it is 0, it will end. Otherwise, we will jump to number 2 to form a loop. This is the so-called "busy waiting ".
 

2. Long latency:

In the kernel, an intuitive latency method is to add the current jiffies with the time to be delayed, so that you can simply compare the current jiffies and the configured
Time to determine the delay time. In this method, a simple macro is provided in the kernel to determine whether the latency is complete.

time_after(jiffies,delay);time_before(jiffies,delay);

Time_after and time_before are defined:

#define time_after(a,b) \(typecheck(unsigned long, a) && \typecheck(unsigned long, b) && \((long)(b) - (long)(a) < 0))#define time_before(a,b) time_after(b,a)

In specific use, time_after or time_before is also used as the while loop judgment statement for busy wait latency.
 
3. sleep latency:

Compared with the busy waiting delay, the process is in sleep state during the delay process. This means that other tasks can be scheduled and executed, improving the CPU utilization.
After the specified time of sleep, the task is rescheduled again. The kernel provides the following sleep latency functions:

void msleep(unsigned int msecs);unsigned long msleep_interruptible(unsigned int msecs);

The difference between the two functions is that the process that calls the msleep () function for sleep delay cannot be interrupted by the signal, but the process that calls the msleep_interruptible () function for delay can be awakened by the signal. Click
The code of the msleep () function is provided:

void msleep(unsigned int msecs){      unsigned long timeout = msecs_to_jiffies(msecs) + 1;      while (timeout)            timeout = schedule_timeout_uninterruptible(timeout);}

It can be seen that msleep () relies on the schedule_timeout_uninterruptible () function in essence. If the sleep is not completed every time the task is rescheduled, the task enters sleep again.

Till the sleep time

Address: http://hi.baidu.com/%CC%EC%D1%C4%D0%D0%BF%CDfranklsb/blog/item/3dd45dd4737987afa1ec9cf6.html

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.