时间子系统1_时钟事件设备管理(二)

2014-11-24 02:37:34 · 作者: · 浏览: 14
u加入广播组bitmap中 // 1.2 如果cpu的clockevent设备为周期模式,关闭其clockevent // 2.关闭广播模式 // 2.1 从广播组bitmap中删除cpu // 2.2 如果cpu的clockevent设备为周期模式,恢复其clockevent // 3.如果广播组为空 // 3.1 停止全局广播设备 // 4.否则 // 4.1 设置全局广播设备为单触发模式或周期模式 // 注: // 1.全局广播设备tick_broadcast_device // 2.每个cpu有各自的tick_device,选择其中一个充当全局广播设备 // 3.加入广播组的clockevent需要关闭其周期触发模式 2.2 static void tick_do_broadcast_on_off(unsigned long *reason) { struct clock_event_device *bc, *dev; struct tick_device *td; unsigned long flags; int cpu, bc_stopped; raw_spin_lock_irqsave(&tick_broadcast_lock, flags); cpu = smp_processor_id(); //per cpu的tick device td = &per_cpu(tick_cpu_device, cpu); dev = td->evtdev; //全局广播设备 bc = tick_broadcast_device.evtdev; //设备不受电源状态的影响 if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP)) goto out; //广播组是否为空 bc_stopped = cpumask_empty(tick_get_broadcast_mask()); switch (*reason) { //开启cpu的广播模式 case CLOCK_EVT_NOTIFY_BROADCAST_ON: case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: //当前cpu不在广播组中 if (!cpumask_test_cpu(cpu, tick_get_broadcast_mask())) { //将cpu加入广播组 cpumask_set_cpu(cpu, tick_get_broadcast_mask()); //关闭周期触发模式的clockevent设备 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) clockevents_shutdown(dev); } break; //关闭cpu的广播模式 case CLOCK_EVT_NOTIFY_BROADCAST_OFF: if (!tick_broadcast_force && //从广播组中清除该设备 cpumask_test_cpu(cpu, tick_get_broadcast_mask())) { cpumask_clear_cpu(cpu, tick_get_broadcast_mask()); //恢复该设备的周期触发模式 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) tick_setup_periodic(dev, 0); } break; } //删除了广播组中最后一个设备 if (cpumask_empty(tick_get_broadcast_mask())) { if (!bc_stopped) { //停止全局广播设备 clockevents_shutdown(bc); } } else if (bc_stopped) { if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) tick_broadcast_start_periodic(bc); else tick_broadcast_setup_oneshot(bc); } out: raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); } // cpu进入\离开广播模式 // 当cpu进入省电模式时,由全局广播设备接管cpu的时间维护 // 调用路径:tick_notify->
tick_broadcast_oneshot_control // 函数主要任务: // 1.cpu进入省电模式,由全局广播设备接管其时间维护 // 1.1 设置cpu关闭状态,更新全局广播设备的到期时间 // 2.cpu离开省电模式,全局广播设备不再接管其时间维护 // 2.1 更新全局广播设备的到期时间 // 注: // cpu在进入省电模式时,进入广播模式 // cpu在离开省电模式时,退出广播模式 3.1 void tick_broadcast_oneshot_control(unsigned long reason) { struct clock_event_device *bc, *dev; struct tick_device *td; unsigned long flags; int cpu; raw_spin_lock_irqsave(&tick_broadcast_lock, flags); //电源状态变化不影响周期模式的全局广播设备 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) goto out; bc = tick_broadcast_device.evtdev; cpu = smp_processor_id(); td = &per_cpu(tick_cpu_device, cpu); dev = td->evtdev; //cpu的clockevent设备不受电源状态的影响 if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) goto out; //cpu进入省电模式,由全局广播设备接管其tick device的任务 if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) { //设置cpu关闭状态 if (!cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) { cpumask_set_cpu(cpu, tick_get_broadcast_oneshot_mask()); cl