`
bulote
  • 浏览: 1305425 次
文章分类
社区版块
存档分类
最新评论

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_slicecsched_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;
}
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics