Droidphone: http://blog.youkuaiyun.com/droidphone/article/category/1263459
timer
/**
* getnstimeofday - Returns the time of day in a timespec
* @ts: pointer to the timespec to be set
*
* Returns the time of day in a timespec.
*/
void getnstimeofday(struct timespec *ts)
/* Timekeeper helper functions. */
static inline s64 timekeeping_get_ns(void)
CONFIG_HZ的值?
/**
* idle_cpu - is a given cpu idle currently?
* @cpu: the processor in question.
*/
int idle_cpu(int cpu)
start_kernel() //内核启动时
->init_timers() //注册低精度timer软中断
{
open_softirq(TIMER_SOFTIRQ,run_timer_softirq);
}
->hrtimers_init() //注册高精度timer软中断
{
open_softirq(HRTIMER_SOFTIRQ,run_hrtimer_softirq);
}
->softirq_init()
{
open_softirq(TASKLET_SOFTIRQ,tasklet_action);
open_softirq(HI_SOFTIRQ, tasklet_hi_action);
}
arm timer中断处理函数://linux3.4
arch_timer_handler_cp15() //在arch_timer_of_register()->arch_timer_common_register()中注册
->arch_timer_handler()
->evt->event_handler(evt) //初始时是低精度timer的中断处理函数tick_handle_periodic(),当启用了高精度timer时,会被修改为hrtimer_interrupt()*/
tick_handle_periodic()
->tick_periodic()
->update_process_times()
->run_local_timers()
->hrtimer_run_queues() //1)在低精度模式下运行高精度hrtimer的接口函数(在低精度的tick中断handler里被调用)
->__run_hrtimer(timer, &base->softirq_time); //处理hrtimer
->raise_softirq(TIMER_SOFTIRQ) //2)随后在run_timer_softirq()启用高精度timer,此后就由hrtimer_interrupt()接管hrtimer的处理
run_timer_softirq() //低分辨率timer的软中断handler
{
struct tvec_base *base = __this_cpu_read(tvec_bases);
hrtimer_run_pending(); //IMPORTANT
->if (tick_check_oneshot_change(!hrtimer_is_hres_enabled())) //1)如果hrtimer_is_hres_enabled返回0,表示系统不允许高精度模式,
//那么在tick_check_oneshot_change函数内,通过tick_nohz_switch_to_nohz切换至NOHZ_MODE_LOWRES低精度模式
->tick_nohz_switch_to_nohz()
->tick_switch_to_oneshot(tick_nohz_handler) //NOHZ_MODE_LOWRES低精度模式的handler是tick_nohz_handler(),它完成的工作类似于tick_handle_periodic()
{
hrtimer_switch_to_hres(); //2)如果系统允许高精度模式,切换到NOHZ_MODE_HIGHRES高精度模式,此后hrtimer工作在高精度模式下
->tick_init_highres() //令 base->hres_active = 1;
->tick_switch_to_oneshot(hrtimer_interrupt)
//tick_device所关联的clock_event_device的事件回调函数会被修改为:hrtimer_interrupt(),并且会被设置成工作于CLOCK_EVT_MODE_ONESHOT单触发模式。
->tick_setup_sched_timer() //因为tick_device将被高精度定时器接管,它将不会再提供原有的tick事件机制,所以需要由高精度定时器系统模拟一个tick事件设备,继续为系统提供tick事件能力,这个工作由tick_setup_sched_timer函数完成
}
if (time_after_eq(jiffies, base->timer_jiffies))
__run_timers(base); //处理低精度timer
}
在do_nanosleep中,请求睡眠的进程会主动schedule(),主动让出CPU。
void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
{
sl->timer.function = hrtimer_wakeup; //该hrtimer过期时调用的回调函数,该函数会唤醒task
sl->task = task;
}
static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
{
hrtimer_init_sleeper(t, current); //初始化一个用于当前task的timer
do {
set_current_state(TASK_INTERRUPTIBLE);
hrtimer_start_expires(&t->timer, mode); //将hrtimer加到percpu的timerqueue中
if (!hrtimer_active(&t->timer))
t->task = NULL;
if (likely(t->task))
schedule(); //主动schedule()
hrtimer_cancel(&t->timer);
mode = HRTIMER_MODE_ABS;
} while (t->task && !signal_pending(current));
__set_current_state(TASK_RUNNING);
return t->task == NULL;
}
/**
* struct hrtimer - the basic hrtimer structure
* @node: timerqueue node, which also manages node.expires,
* the absolute expiry time in the hrtimers internal
* representation. The time is related to the clock on
* which the timer is based. Is setup by adding
* slack to the _softexpires value. For non range timers
* identical to _softexpires.
* @_softexpires: the absolute earliest expiry time of the hrtimer.
* The time which was given as expiry time when the timer
* was armed.
* @function: timer expiry callback function
* @base: pointer to the timer base (per cpu and per clock)
* @state: state information (See bit values above)
* @start_site: timer statistics field to store the site where the timer
* was started
* @start_comm: timer statistics field to store the name of the process which
* started the timer
* @start_pid: timer statistics field to store the pid of the task which
* started the timer
*
* The hrtimer structure must be initialized by hrtimer_init()
*/
struct hrtimer {
struct timerqueue_node node; //如果不允许该timer有slack时(比如对于RT(实时)进程),node->expires==_softexpires
ktime_t _softexpires; //该timer的最早的过期时间(当允许该timer有slack时,默认的slack是50000ns, 见task_struct->timer_slack_ns)
enum hrtimer_restart (*function)(struct hrtimer *); //到期的callback
struct hrtimer_clock_base *base;
unsigned long state; //见#define HRTIMER_STATE_ENQUEUED 0x01等
#ifdef CONFIG_TIMER_STATS
int start_pid; //启动该hrtimer的进程的信息,见timer_stats_hrtimer_set_start_info()
void *start_site;
char start_comm[16];
#endif
};
struct timerqueue_node {
struct rb_node node;
ktime_t expires;
};