Xen Guest Domain中的Idle Process

在traditional operating system中,有一个Idle Process:当OS里面没有任何task的时候,就靠Idle Process来空转CPU

 

在virtualization的环境下,如果还这么“空转”,显然是对CPU cycles的一种浪费。很自然的想法:当Guest Domain不需要CPU的时候,自动让出CPU给其他domain使用。这也是work-conserving的一种methodology。

 

Xen对Guest Domain里的Idle Process进行了改写,调用hypercall来代替原来的while (1)。 Follow me:-)

 

------------------------------------------------------------------

cpu_idle

xen_idle

safe_halt

raw_safe_halt

HYPERVISOR_block

HYPERVISOR_sched_op(SCHEDOP_block, NULL)

SCHEDOP_block

do_block: 这个函数只有在SCHEDOP_block时才被调用,也就是说,只有Guest Domain的Idle Process可以引发do_block

-------------------------------------------------------------------

 

 

总这么block住也不行是吧,那啥时候被wake up呢?

容我再想想...

(1) ...

(2) ...

...

 

看看do_block哈:)

/* Block the currently-executing domain until a pertinent event occurs. */

static long do_block(void)
{
struct vcpu *v = current;

local_event_delivery_enable();
set_bit(_VPF_blocked, &v->pause_flags);

/* Check for events /after/ blocking: avoids wakeup waiting race. */
if ( local_events_need_delivery() ) {
clear_bit(_VPF_blocked, &v->pause_flags);
} else {
raise_softirq(SCHEDULE_SOFTIRQ); //哥决定让出CPU啦...
}

return 0;
}

 

static void schedule(void)
{
struct vcpu *prev = current, *next = NULL;
s_time_t now = NOW();
struct schedule_data *sd = sd = &this_cpu(schedule_data);
struct task_slice next_slice;


/* get policy-specific decision on scheduling... */
next_slice = ops.do_schedule(now);
next = next_slice.task;
sd->curr = next;

... ...

ASSERT(prev->runstate.state == RUNSTATE_running);
if (test_bit(_VPF_blocked, &prev->pause_flags)) { // do_block之后,应该跑到这里就对啦
vcpu_runstate_change(prev, RUNSTATE_blocked, now);
} else {
if (vcpu_runnable(prev))
vcpu_runstate_change(prev, RUNSTATE_runnable, now);
else
vcpu_runstate_change(prev, RUNSTATE_offline, now);
}

prev->last_run_time = now;

.........

context_switch(prev, next);
}

 

static struct task_slice csched_schedule(s_time_t now)
{
const int cpu = smp_processor_id();
struct list_head * const runq = RUNQ(cpu);
struct csched_vcpu * const scurr = CSCHED_VCPU(current);

 

if ( vcpu_runnable(current) ) { // current如果还runnable,就继续插入runq;否则就已经不在runq里了
__runq_insert(cpu, scurr);
} else {
BUG_ON(is_idle_vcpu(current));
BUG_ON(list_empty(runq));
}
... ...

}

 

static inline int vcpu_runnable(struct vcpu *v)
{
if ( (v->pause_flags == 0) &&
     (atomic_read(&v->pause_count) == 0) &&
     (atomic_read(&v->domain->pause_count) == 0)) {
return true;
} else {
return false;
}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值