[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC v1] xen:rtds: towards work conserving RTDS
Make RTDS scheduler work conserving to utilize the idle resource, without breaking the real-time guarantees. VCPU model: Each real-time VCPU is extended to have a work conserving flag and a priority_level field. When a VCPU's budget is depleted in the current period, if it has work conserving flag set, its priority_level will increase by 1 and its budget will be refilled; othewrise, the VCPU will be moved to the depletedq. Scheduling policy: modified global EDF: A VCPU v1 has higher priority than another VCPU v2 if (i) v1 has smaller priority_leve; or (ii) v1 has the same priority_level but has a smaller deadline Signed-off-by: Meng Xu <mengxu@xxxxxxxxxxxxx> --- xen/common/sched_rt.c | 71 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/xen/common/sched_rt.c b/xen/common/sched_rt.c index 39f6bee..740a712 100644 --- a/xen/common/sched_rt.c +++ b/xen/common/sched_rt.c @@ -49,13 +49,16 @@ * A PCPU is feasible if the VCPU can run on this PCPU and (the PCPU is idle or * has a lower-priority VCPU running on it.) * - * Each VCPU has a dedicated period and budget. + * Each VCPU has a dedicated period, budget and is_work_conserving flag * The deadline of a VCPU is at the end of each period; * A VCPU has its budget replenished at the beginning of each period; * While scheduled, a VCPU burns its budget. * The VCPU needs to finish its budget before its deadline in each period; * The VCPU discards its unused budget at the end of each period. - * If a VCPU runs out of budget in a period, it has to wait until next period. + * A work conserving VCPU has is_work_conserving flag set to true; + * When a VCPU runs out of budget in a period, if it is work conserving, + * it increases its priority_level by 1 and refill its budget; otherwise, + * it has to wait until next period. * * Each VCPU is implemented as a deferable server. * When a VCPU has a task running on it, its budget is continuously burned; @@ -63,7 +66,8 @@ * * Queue scheme: * A global runqueue and a global depletedqueue for each CPU pool. - * The runqueue holds all runnable VCPUs with budget, sorted by deadline; + * The runqueue holds all runnable VCPUs with budget, + * sorted by priority_level and deadline; * The depletedqueue holds all VCPUs without budget, unsorted; * * Note: cpumask and cpupool is supported. @@ -191,6 +195,7 @@ struct rt_vcpu { /* VCPU parameters, in nanoseconds */ s_time_t period; s_time_t budget; + bool_t is_work_conserving; /* is vcpu work conserving */ /* VCPU current infomation in nanosecond */ s_time_t cur_budget; /* current budget */ @@ -201,6 +206,8 @@ struct rt_vcpu { struct rt_dom *sdom; struct vcpu *vcpu; + unsigned priority_level; + unsigned flags; /* mark __RTDS_scheduled, etc.. */ }; @@ -245,6 +252,11 @@ static inline struct list_head *rt_replq(const struct scheduler *ops) return &rt_priv(ops)->replq; } +static inline bool_t is_work_conserving(const struct rt_vcpu *svc) +{ + return svc->is_work_conserving; +} + /* * Helper functions for manipulating the runqueue, the depleted queue, * and the replenishment events queue. @@ -273,6 +285,20 @@ vcpu_on_replq(const struct rt_vcpu *svc) return !list_empty(&svc->replq_elem); } +/* If v1 priority >= v2 priority, return value > 0 + * Otherwise, return value < 0 + */ +static int +compare_vcpu_priority(const struct rt_vcpu *v1, const struct rt_vcpu *v2) +{ + if ( v1->priority_level < v2->priority_level || + ( v1->priority_level == v2->priority_level && + v1->cur_deadline <= v2->cur_deadline ) ) + return 1; + else + return -1; +} + /* * Debug related code, dump vcpu/cpu information */ @@ -303,6 +329,7 @@ rt_dump_vcpu(const struct scheduler *ops, const struct rt_vcpu *svc) cpulist_scnprintf(keyhandler_scratch, sizeof(keyhandler_scratch), mask); printk("[%5d.%-2u] cpu %u, (%"PRI_stime", %"PRI_stime")," " cur_b=%"PRI_stime" cur_d=%"PRI_stime" last_start=%"PRI_stime"\n" + " \t\t priority_level=%d work_conserving=%d\n" " \t\t onQ=%d runnable=%d flags=%x effective hard_affinity=%s\n", svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id, @@ -312,6 +339,8 @@ rt_dump_vcpu(const struct scheduler *ops, const struct rt_vcpu *svc) svc->cur_budget, svc->cur_deadline, svc->last_start, + svc->priority_level, + is_work_conserving(svc), vcpu_on_q(svc), vcpu_runnable(svc->vcpu), svc->flags, @@ -423,15 +452,18 @@ rt_update_deadline(s_time_t now, struct rt_vcpu *svc) */ svc->last_start = now; svc->cur_budget = svc->budget; + svc->priority_level = 0; /* TRACE */ { struct __packed { unsigned vcpu:16, dom:16; + unsigned priority_level; uint64_t cur_deadline, cur_budget; } d; d.dom = svc->vcpu->domain->domain_id; d.vcpu = svc->vcpu->vcpu_id; + d.priority_level = svc->priority_level; d.cur_deadline = (uint64_t) svc->cur_deadline; d.cur_budget = (uint64_t) svc->cur_budget; trace_var(TRC_RTDS_BUDGET_REPLENISH, 1, @@ -477,7 +509,7 @@ deadline_queue_insert(struct rt_vcpu * (*qelem)(struct list_head *), list_for_each ( iter, queue ) { struct rt_vcpu * iter_svc = (*qelem)(iter); - if ( svc->cur_deadline <= iter_svc->cur_deadline ) + if ( compare_vcpu_priority(svc, iter_svc) > 0 ) break; pos++; } @@ -537,8 +569,9 @@ runq_insert(const struct scheduler *ops, struct rt_vcpu *svc) ASSERT( !vcpu_on_q(svc) ); ASSERT( vcpu_on_replq(svc) ); - /* add svc to runq if svc still has budget */ - if ( svc->cur_budget > 0 ) + /* add svc to runq if svc still has budget or svc is work_conserving */ + if ( svc->cur_budget > 0 || + is_work_conserving(svc) ) deadline_runq_insert(svc, &svc->q_elem, runq); else list_add(&svc->q_elem, &prv->depletedq); @@ -857,6 +890,8 @@ rt_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd) svc->vcpu = vc; svc->last_start = 0; + svc->is_work_conserving = 1; + svc->priority_level = 0; svc->period = RTDS_DEFAULT_PERIOD; if ( !is_idle_vcpu(vc) ) svc->budget = RTDS_DEFAULT_BUDGET; @@ -966,8 +1001,16 @@ burn_budget(const struct scheduler *ops, struct rt_vcpu *svc, s_time_t now) if ( svc->cur_budget <= 0 ) { - svc->cur_budget = 0; - __set_bit(__RTDS_depleted, &svc->flags); + if ( is_work_conserving(svc) ) + { + svc->priority_level++; + svc->cur_budget = svc->budget; + } + else + { + svc->cur_budget = 0; + __set_bit(__RTDS_depleted, &svc->flags); + } } /* TRACE */ @@ -976,11 +1019,15 @@ burn_budget(const struct scheduler *ops, struct rt_vcpu *svc, s_time_t now) unsigned vcpu:16, dom:16; uint64_t cur_budget; int delta; + unsigned priority_level; + bool_t is_work_conserving; } d; d.dom = svc->vcpu->domain->domain_id; d.vcpu = svc->vcpu->vcpu_id; d.cur_budget = (uint64_t) svc->cur_budget; d.delta = delta; + d.priority_level = svc->priority_level; + d.is_work_conserving = svc->is_work_conserving; trace_var(TRC_RTDS_BUDGET_BURN, 1, sizeof(d), (unsigned char *) &d); @@ -1088,7 +1135,7 @@ rt_schedule(const struct scheduler *ops, s_time_t now, bool_t tasklet_work_sched vcpu_runnable(current) && scurr->cur_budget > 0 && ( is_idle_vcpu(snext->vcpu) || - scurr->cur_deadline <= snext->cur_deadline ) ) + compare_vcpu_priority(scurr, snext) > 0 ) ) snext = scurr; } @@ -1198,13 +1245,13 @@ runq_tickle(const struct scheduler *ops, struct rt_vcpu *new) } iter_svc = rt_vcpu(iter_vc); if ( latest_deadline_vcpu == NULL || - iter_svc->cur_deadline > latest_deadline_vcpu->cur_deadline ) + compare_vcpu_priority(iter_svc, latest_deadline_vcpu) < 0 ) latest_deadline_vcpu = iter_svc; } /* 3) candicate has higher priority, kick out lowest priority vcpu */ if ( latest_deadline_vcpu != NULL && - new->cur_deadline < latest_deadline_vcpu->cur_deadline ) + compare_vcpu_priority(latest_deadline_vcpu, new) < 0 ) { SCHED_STAT_CRANK(tickled_busy_cpu); cpu_to_tickle = latest_deadline_vcpu->vcpu->processor; @@ -1493,7 +1540,7 @@ static void repl_timer_handler(void *data){ { struct rt_vcpu *next_on_runq = q_elem(runq->next); - if ( svc->cur_deadline > next_on_runq->cur_deadline ) + if ( compare_vcpu_priority(svc, next_on_runq) < 0 ) runq_tickle(ops, next_on_runq); } else if ( __test_and_clear_bit(__RTDS_depleted, &svc->flags) && -- 1.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |