最近在研究xen的vcpu 调度和cpu qos策略,现在默认的scheduler是credit, 对应的代码是sched_credit.c
xen支持好几种控制策略,效果最好的当选pin, 灵活性最好的是weight, 控制和灵活兼备的就是cap,据说人家amazon在06年推ecu的时候就是用了类似的技术。
pin的实现比较好了解,也就是set affinity,个人对cap,weight的实现比较感兴趣,这两者应该是类似,好了,开始聊下代码
xen里面首先有个总的调度函数schedule(),这是SCHEDULE_SOFTIRQ的中断处理函数,主动触发调度的方式就是raise_softirq,每个pcpu有个timer,里面就是定期raise_softirq。
schedule里面主要的事情就是调用具体实现sched_credit里面的do_schedule来挑选下一个next任务,之后对prev和next的vcpu state进行更新,prev根据当前的状态,更新成blocked,runnable,offline, next更新成running, 再调用context_switch函数来完成真正一些寄存器的保存和切换
sched_credit的do_schedule是由csched_schedule实现的,这里面会先去取当前cpu 的runq的下一个任务,取出来之后判断下当前的pri,如果是over,那表示它的credit已经用完了,不能被run了,需要重新挑一个出来,如果大于over,表示可以run, 就会从runq里面摘出来。
每个pcpu还有一个timer,csched_tick, 它会计算当前vcpu使用了多少credit之类的accounting, 并把每个runq重新排序
当然还少不了一个主timer csched_acct, 定期去计算当前活动dom的活动vcpu里面的credit值,根据一定的策略如weight和cap来决定每个vcpu最后分到的credit值,如果当前credit小于0,那么表示credit不够了,优先级要降低,prio设置成over,如果有设置cap,那么会pause住,等到后面有credit再唤醒。如果credit > 0那么,优先级就提高了,prio设置为under, 如果之前因为cap而被pause的,这个时候可以unpause起来,最后通知说,我需要runq重新排序
中间weight和cap对于credit计算的影响如下:
首先有个CSCHED_CREDITS_PER_ACCT表示这次调度里面每个pcpu能够分配的credit绝对值
credit_total=n core * CSCHED_CREDITS_PER_ACCT
然后有个当前credit_fair会根据你的weight所占的比例来决定你的credit
credit_peak表示你的活动cpu数 * CSCHED_CREDITS_PER_ACCT,这就是你的vcpu能够达到的上限,也就是独占物理cpu
credit_cap根据你的cap来决定你拥有多少物理cpu的能力,cap * CSCHED_CREDITS_PER_ACCT
如果有cap, 那么creadit_cap < credit_peak时,credit_peak=credit_cap,也就是说你的上线由你的credit_cap决定
最后在credit_peak和credit_fair里面取最小的那个值作为整个domain的credit
再把domain的credit除以当前domain活动的cpu数,就变成domain的vcpu的credit
至此xen credit scheduler的基本原理就差不多说完了,后续一些细节点慢慢再补充