xen下电流程分析
首先,由do_platform_op进入,进行一些平台操作。
case XENPF_enter_acpi_sleep: ret = xsm_acpi_sleep(); if ( ret ) break;
ret = acpi_enter_sleep(&op->u.enter_acpi_sleep); break; |
acpi_ enter_sleep将系统置入睡眠状态,其中有:
return continue_hypercall_on_cpu(0, enter_state_helper, &acpi_sinfo); |
continue_hypercall_on_cpu在cpu == smp_processor_id()时(默认成立),调用enter_state_helper。
enter_state_helper然后调用enter_state,enter_state是xen用来做suspend/resume操作的主接口。
enter_state中调用了disable_nonboot_cpus,disable_nonboot_cpus负责将cpu下线。
for_each_online_cpu(cpu) { if (cpu == 0) continue; error = cpu_down(cpu); |
下线顺序是从cpu1开始,cpu2…顺次递增下线。具体的下线操作由disable_nonboot_cpus中的cpu_down来完成。
cpu_down中有:
err = stop_machine_run(take_cpu_down, NULL, cpu); |
take_cpu_down→__cpu_disable()→cpu_disable_scheduler
cpu_disable_scheduler会对每一个域中的每一个vcpu进行检测,将它的亲和性从下线的pcpu身上剔除掉。
if ( v->processor == cpu )
{
set_bit(_VPF_migrating, &v->pause_flags);
vcpu_sleep_nosync(v);
vcpu_migrate(v);
}
}
}
如果vcpu在要下线的pcpu上,就要调用vcpu_migrate(v)将它迁移到其它pcpu上。具体迁移到哪个pcpu上,由vcpu_migrate调用pick_cpu函数决定。
/* Select new CPU. */ old_cpu = v->processor; new_cpu = SCHED_OP(pick_cpu, v); |
pick_cpu函数对应就是credit调度算法中的csched_cpu_pick函数。
csched_cpu_pick→_csched_cpu_pick
会选择一个在线的cpu作为new_cpu,通常这个cpu会是被下线的顺次的下一个pcpu。
cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
cpu = cpu_isset(vc->processor, cpus)
? vc->processor
: cycle_cpu(vc->processor, cpus);
当vcpu所有亲和性的pcpu都被下线以后,就会由cycle_cpu的返回值来决定下一个被选中运行vcpu的pcpu。
#define cycle_cpu(n, src) __cycle_cpu((n), &(src), NR_CPUS) |
2013年5月20日上传