2、在初始化时__start_xen-->init_idle_domain-->scheduler_init中会将软中断和schedule()绑定,并设置每个pcpu的用于schedule的s_timer,其处理函数是s_timer_fn,主要是触发软中断SCHEDULE_SOFTIRQ。schedule()会在每3个tick周期(30ms,即一个vcpu得到调度后运行的时间片)执行一次,该过程的结果为该pcpu找出合适的vcpu和时间片,用于该vcpu在此pcpu上的运行,然后进行上下文切换。这个schedule过程是根据选择的调度算法来确定的。
3、在初始化domain时调度模块会初始化其vcpu的调度信息,vcpu的初始化主要是把vcpu插入到其pcpu的运行就绪队列runq上和活动vcpu列表中。如果发现其对应的pcpu还没初始化,则按照下面的方法初始化该pcpu。
4、在初始化每个pcpu时会设置它的tick的timer,每个tick周期(10ms)会执行一次csched_tick,来更新该pcpu上运行的当前vcpu的credit值,减去credit_per_tick,该值是100。当活动vcpu列表为空时说明所有vcpu的credit都为负,则重新计算credit值。否则通过pick后pcpu是否变化来检查是否需要进行vcpu的迁移,如果需要则触发软中断,执行schedule算法。
5、credit算法在执行schedule时,会首先获得该pcpu的就绪队列runq上队首vcpu,即snext,检查其credit值有没有用完,如果没有用完直接返回。如果用完表明该pcpu的就绪队列上没有under或boost状态的vcpu,则进行负载均衡,查找其它pcpu上优先级较高的vcpu,执行run_steal把它偷过来运行。如果还没有找到合适的,就返回之前得到的snext
6、主ticker的master_timer由csched_priv持有,在csched_start_tickers里初始化,它每3个tick周期通过csched_acct来计算所有domain的vcpu的credit值,主要是根据当前credit总值,每个domain占用的权重weight和比例上限cap,计算出每个domain分得的credit值,然后再平均分配到每个vcpu上,vcpu的credit值就等于原有的credit值和新分到的credit之和。根据vcpu最新的credit值来确定vcpu的调度优先级是over还是under,如果是over且cap有设置,则执行sleep,把自己调度出来,等待下次判断和调度。
csched_pcpu:物理cpu的调度信息,它主要是就绪的vcpu队列,ticker计时器,用于每个tick周期计算当前运行的vcpu的credit值。
csched_vcpu:vcpu的调度信息,它位于pcpu的就绪队列上,也位于活动vcpu列表上,可以得到它所属的domain的调度信息,可以得到它的credit值与优先级
csched_dom:domain的调度信息,例如活动的vcpu列表,活动domain列表,domain的weight和cap值。
csched_private:credit调度算法的总体信息,例如调度锁,cpu个数,主ticker计时器,用于每3个tick周期计算一次所有的credit值,当前总的weight值和credit值。