This article was reproduced from: http://blog.csdn.net/dean_gdp/article/details/25481225
Basic operation of Hrtimer
The traditional Linux timer is implemented by the time-wheel algorithm (TIMER.C), but Hrtimer is implemented by the red-black tree algorithm. In struct Hrtimer There is a node field, which is a struct rb_node, which represents the position of hrtimer in a red-black tree.
Hrtimer_start
The Hrtimer_start function adds a hrtimer to a red-black tree sorted by expiry time, whose main process is:
int Hrtimer_start (struct Hrtimer *timer, ktime_t Tim, const enum Hrtimer_mode mode);
Calculates the timeout for Hrtimer based on the value of the time and mode parameters and sets it to the Timer->expire domain.
Expire is set to absolute time, so if the value of the parameter MODE is Hrtimer_mode_rel (that is, the value of the parameter Tim is the relative time), then the value of the Tim must be corrected to absolute time:
expire = Tim + Timer->base->get_time (). (Note that this article only studies single-CPU cases)
Call Enqueue_hrtimer and add Hrtimer to the red-black tree.
Expiry of Hrtimer
Hrtimer in the Hrtimer_run_queues function to determine whether the execution is due. The Hrtimer_run_queues call chain is: Linux's system clock function->update_process_times->run_local_timers->hrtimer_run_queues.
void Hrtimer_run_queues (void)
Determines whether the high-precision mode, if it is high-precision mode, returns immediately. This article does not consider this situation temporarily.
Red-black trees for each clock source (real and monotonic), check hrtimer in due sequence to see if they expire (compare the timer to the softirq_time of the clock source). If it expires, remove the expired timer, and then follow the timer's specific mode to perform the appropriate operation:
L If the timer mode is HRTIMER_CB_SOFTIRQ, then move the timer to the Hrtimer_cpu_base cb_pending queue
L Call __run_hrtimer, execute the callback function of the timer in __run_hrtimer.
When high-precision mode is not configured, the timers in the cb_pending queue are executed in the T_SOFTIRQ soft interrupt. The call chain is
run_timer_softirq-> hrtimer_run_pending-> run_hrtimer_pending-> run_hrtimer_pending
Hrtimer_cancel
The role of the Hrtimer_cancel function is to delete a queued timer. Here are three cases, one is the timer has expired, and set the soft interrupt mode, the second is not expired, still in the red black tree; The third is that the timer is executing.
In the first case, the timer is hung in the Hrtimer_cpu_base cb_pending queue, so it needs to be removed from the pending queue.
In the second case, the timer is still in the red and black tree, so remove it from the red and black tree. Since this article is only considering the fact that high precision is not open, we should not study the situation where the timer is exactly in the red-black tree first (that is, the part of the code that calls the Hrtimer_force_reprogram function).
L The third case of deletion fails, the Hrtimer_cancel function loops through the retry, and then deletes the timer when it finishes executing. (This may occur in a multi-CPU system)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/hrtimer.h>
#include <linux/jiffies.h>
static struct Hrtimer timer;
ktime_t kt;
static enum Hrtimer_restart hrtimer_handler (struct Hrtimer *timer)
{
KT = Ktime_set (1, 10);
PRINTK ("------I am in Hrtimer-----\ n");
Hrtimer_forward (Timer, Timer->base->get_time (), kt);
return hrtimer_restart;
}
static int __init test_init (void)
{
Pr_info ("Timer resolution:%lu\n", tick_nsec);
KT = Ktime_set (1, 10); /* 1 sec, nsec */
Hrtimer_init (&timer, Clock_monotonic, Hrtimer_mode_rel);
Hrtimer_set_expires (&timer, kt);
Hrtimer_start (&timer, KT, Hrtimer_mode_rel);
Timer.function = Hrtimer_handler;
PRINTK ("\ n--------test start---------\ n");
return 0;
}
static void __exit test_exit (void)
{
Hrtimer_cancel (&timer);
PRINTK ("--------test over----------\ n");
Return
}
Module_license ("GPL");
Module_init (Test_init);
Module_exit (Test_exit);
Reprint Address: http://blog.chinaunix.NET/uid-361890-id-257337.html
http://blog.csdn.net/walkingman321/article/details/6133171
Linux High Precision timer Hrtimer Use the example "go"