/*
* Periodic broadcast:
* - invoke the broadcast handlers
*/
static void tick_do_periodic_broadcast(void)
{
raw_spin_lock(&tick_broadcast_lock);
cpumask_and(to_cpumask(tmpmask), //确定受影响的CPU
cpu_online_mask, tick_get_broadcast_mask());
tick_do_broadcast(to_cpumask(tmpmask)); //
raw_spin_unlock(&tick_broadcast_lock);
}
tick_do_broadcast():
/*
* Broadcast the event to the cpus, which are set in the mask (mangled).
*/
static void tick_do_broadcast(struct cpumask *mask)
{
int cpu = smp_processor_id();
struct tick_device *td;
/*
* Check, if the current cpu is in the mask
*/
if (cpumask_test_cpu(cpu, mask)) { //当前CPU是否处于广播的掩码中?
cpumask_clear_cpu(cpu, mask); //从掩码中移除该CPU
td = &per_cpu(tick_cpu_device, cpu);
td->evtdev->event_handler(td->evtdev); //对当前CPU调用event_handler
}
if (!cpumask_empty(mask)) { //掩码中是否还有更多的CPU
/*
* It might be necessary to actually check whether the devices
* have different broadcast functions. For now, just use the
* one of the first device. This works as long as we have this
* misfeature only on x86 (lapic)
*/
td = &per_cpu(tick_cpu_device, cpumask_first(mask));
/*
*对与局部APIC来说,broadcast方法指向lapic_timer_interrupt。对所有与不同时钟设备相关联的CPU,该方法负责
*发送处理器中断LOCAL_TIMER_VECTOR,该中断的中断向量由内核设置为调用apic_timer_interrupt。其结果就是,时钟
*事件设备无法区分IPI和真正的中断,因而其效果与设备仍然处于工作状态是相同的。
*/
td->evtdev->broadcast(mask);
}
}