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

2014-11-24 02:37:34 · 作者: · 浏览: 16
ockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN); //cpu下一个事件的到期时间小于全局广播设备下一个事件的到期时间,设置cpu在下一个周期到期 if (dev->next_event.tv64 < bc->next_event.tv64) tick_broadcast_set_event(dev->next_event, 1); } //cpu离开省电模式,全局广播设备不再接管其tick device的任务 } else { //清除cpu关闭状态 if (cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) { cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask()); clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT); //重新编程cpu的tick device在下一个周期到期 if (dev->next_event.tv64 != KTIME_MAX) tick_program_event(dev->next_event, 1); } } out: raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); } // 选择do_timer cpu // 调用路径:tick_notify->tick_handover_do_timer 4.1 static void tick_handover_do_timer(int *cpup) { //如果dying cpu负责do_timer,重新选取online cpu中第一个cpu负责 if (*cpup == tick_do_timer_cpu) { int cpu = cpumask_first(cpu_online_mask); tick_do_timer_cpu = (cpu < nr_cpu_ids) cpu : TICK_DO_TIMER_NONE; } } // dead cpu的clockevent的处理: // 1.从oneshot掩码中删除cpu // 2.从broadcast掩码中删除cpu // 3.关闭clockevent设备 // 3.1 设置该cpu tick device的clockevent为null // 3.2 将clockevent设备链入clockevents_released // 从oneshot掩码中删除cpu // 调用路径:tick_notify->tick_shutdown_broadcast_oneshot 5.1 void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { unsigned long flags; unsigned int cpu = *cpup; raw_spin_lock_irqsave(&tick_broadcast_lock, flags); //从oneshot掩码中删除dead cpu cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask()); raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); } // 从broadcast掩码中删除cpu // 调用路径:tick_notify->
tick_shutdown_broadcast 5.2 void tick_shutdown_broadcast(unsigned int *cpup) { struct clock_event_device *bc; unsigned long flags; unsigned int cpu = *cpup; raw_spin_lock_irqsave(&tick_broadcast_lock, flags); //从broadcast掩码中删除dead cpu bc = tick_broadcast_device.evtdev; cpumask_clear_cpu(cpu, tick_get_broadcast_mask()); //广播组为空,停止全局广播广播设备 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { if (bc && cpumask_empty(tick_get_broadcast_mask())) clockevents_shutdown(bc); } raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); } // 关闭cpu的clockevent设备 // 调用路径:tick_notify->tick_shutdown 5.3 static void tick_shutdown(unsigned int *cpup) { struct tick_device *td = &per_cpu(tick_cpu_device, *cpup); struct clock_event_device *dev = td->evtdev; unsigned long flags; raw_spin_lock_irqsave(&tick_device_lock, flags); td->mode = TICKDEV_MODE_PERIODIC; //标记给定cpu的clockevent设备为不可用 if (dev) { dev->mode = CLOCK_EVT_MODE_UNUSED; //将clockevent链接到clockevents_released clockevents_exchange_device(dev, NULL); td->evtdev = NULL; } raw_spin_unlock_irqrestore(&tick_device_lock, flags); } // 挂起cpu的clockevent // 调用路径:tick_notify->tick_suspend 6.1 static void tick_suspend(void) { struct tick_device *td = &__get_cpu_var(tick_cpu_device); unsigned long flags; //关闭cpu tick device的clockevent raw_spin_lock_irqsave(&tick_device_lock, flags); clockevents_shutdown(td->evtdev); raw_spin_unlock_irqrestore(&tick_device_lock, flags); } // 恢复cpu的clockevent // 调用路径:tick_notify->tick_resume 7.1 static void tick_resume(void) { struct tick_device *td = &__get_cpu_var(tick_cpu_device); unsigned long flags; //恢复广播 int broadcast = tick_resume_broadcast(); raw_spin_lock_irqsave(&tick_device_lock