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

2014-11-24 02:37:34 · 作者: · 浏览: 12
//	1.每个cpu都具有一个tick_device,维护周期时钟。
//	2.tick_device依赖一个clockevent设备,提供周期事件。
//	3.cpu电源状态的改变会影响tick_device,通过tick_notifier监听电源状态。
//	4.全局广播设备接管进入省电模式cpu的周期时间维护。
//	4.broadcast_mask保存开启广播模式的cpu, broadcast_oneshot_mask保存进入省电模式的cpu。

//	监听clockevent设备状态
//	调用路径:start_kernel->tick_init
1.1 void __init tick_init(void)
{
	clockevents_register_notifier(&tick_notifier);
}

//	监听clockevent设备,cpu的状态变化
1.2 static int tick_notify(struct notifier_block *nb, unsigned long reason,
			       void *dev)
{
	switch (reason) {

		//新eventclock设备注册
	case CLOCK_EVT_NOTIFY_ADD:
		return tick_check_new_device(dev);
		//cpu开启\关闭广播模式
	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
		tick_broadcast_on_off(reason, dev);
		break;
		//cpu进入\离开广播模式
	case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
	case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
		tick_broadcast_oneshot_control(reason);
		break;
		//选择do_timer的cpu
	case CLOCK_EVT_NOTIFY_CPU_DYING:
		tick_handover_do_timer(dev);
		break;
		//停用dead cpu的clockevent
	case CLOCK_EVT_NOTIFY_CPU_DEAD:
		tick_shutdown_broadcast_oneshot(dev);
		tick_shutdown_broadcast(dev);
		tick_shutdown(dev);
		break;
		//挂起cpu的clockevent
	case CLOCK_EVT_NOTIFY_SUSPEND:
		tick_suspend();
		tick_suspend_broadcast();
		break;
		//恢复cpu的clockevent
	case CLOCK_EVT_NOTIFY_RESUME:
		tick_resume();
		break;

	default:
		break;
	}

	return NOTIFY_OK;
}

//	向clockevents_chain通知clockevents事件
//	函数主要任务:
//		1.通知clockevents_chain
//		2.当cpu offline时,清空clockevents_released链表,删除与此cpu相关的clockevent
//	注:clockevents_released保存所有fail-to-add/replace-out的clockevent
//		clockevent_devices保存所有有效的clockevent
1.3 void clockevents_notify(unsigned long reason, void *arg)
{
	struct clock_event_device *dev, *tmp;
	unsigned long flags;
	int cpu;

	raw_spin_lock_irqsave(&clockevents_lock, flags);
	//封装标准通知链操作raw_notifier_call_chain
	clockevents_do_notify(reason, arg);

	switch (reason) {
	case CLOCK_EVT_NOTIFY_CPU_DEAD:
		//clockevents_released用于保存所有fail-to-add/replace-out的clockevent
		//当cpu offline后,清空此链表
		list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
			list_del(&dev->
list); //删除与此cpu相关的clockevent cpu = *((int *)arg); list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) { if (cpumask_test_cpu(cpu, dev->cpumask) && cpumask_weight(dev->cpumask) == 1 && !tick_is_broadcast_device(dev)) { BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); list_del(&dev->list); } } break; default: break; } raw_spin_unlock_irqrestore(&clockevents_lock, flags); } // cpu开启\关闭广播模式 // 调用路径:tick_notify->tick_broadcast_on_off // 注: // 1.加入、退出广播组指针对online的cpu 2.1 void tick_broadcast_on_off(unsigned long reason, int *oncpu) { //忽略offline的cpu if (!cpumask_test_cpu(*oncpu, cpu_online_mask)) printk(KERN_ERR "tick-broadcast: ignoring broadcast for " "offline CPU #%d\n", *oncpu); else tick_do_broadcast_on_off(&reason); } // cpu开启\关闭广播模式 // 函数主要任务: // 1.开启广播模式 // 1.1 将cp