Credit scheduler implementation of scheduling domains.
signed-off-by: Mike D. Day <ncmike@xxxxxxxxxx>
--
sched_credit.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 253 insertions(+), 9 deletions(-)
--
diff -r 8b71c838aff8 xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Fri May 04 11:21:36 2007 -0400
+++ b/xen/common/sched_credit.c Fri May 04 17:48:54 2007 -0400
@@ -219,10 +219,14 @@ struct csched_dom {
struct csched_dom {
struct list_head active_vcpu;
struct list_head active_sdom_elem;
+ struct list_head nemesis_doms;
+ struct list_head nemesis_elem;
+ struct csched_dom *ndom;
struct domain *dom;
uint16_t active_vcpu_count;
uint16_t weight;
uint16_t cap;
+ uint16_t flags;
};
/*
@@ -344,6 +348,118 @@ __runq_tickle(unsigned int cpu, struct c
cpumask_raise_softirq(mask, SCHEDULE_SOFTIRQ);
}
+static inline struct csched_dom *csched_dom(struct domain *d)
+{
+ return (struct csched_dom *)d->sched_priv;
+}
+
+static inline struct csched_dom *get_nemesis_dom(struct csched_dom *d)
+{
+ if (d->flags & SDOM_IS_ADOM)
+ {
+ if (get_domain(d->ndom->dom))
+ return d->ndom;
+ BUG_ON(1);
+ }
+
+ return NULL;
+}
+
+static inline struct csched_dom *accounting_dom(struct csched_dom *d)
+{
+ if (d->flags & SDOM_IS_ADOM)
+ return d->ndom;
+ return d;
+}
+
+static inline void delegate_active_vcpus(struct csched_dom *adom,
+ struct csched_dom *ndom)
+{
+ BUG_ON(! (adom->flags & SDOM_IS_ADOM));
+ BUG_ON(adom->ndom != ndom);
+ if (adom->flags & SDOM_IS_ADOM && adom->ndom == ndom)
+ {
+ struct list_head *elem;
+
+ while (!list_empty(&adom->active_vcpu))
+ {
+ elem = adom->active_vcpu.next;
+ list_del(elem);
+ list_add(elem, &ndom->active_vcpu);
+ adom->active_vcpu_count--;
+ ndom->active_vcpu_count++;
+ }
+
+ if (!list_empty(&adom->active_sdom_elem))
+ {
+ list_del_init(&adom->active_sdom_elem);
+ csched_priv.weight -= adom->weight;
+ }
+
+ if (list_empty(&ndom->active_sdom_elem))
+ {
+ list_add(&ndom->active_sdom_elem, &csched_priv.active_sdom);
+ csched_priv.weight += ndom->weight;
+ }
+ }
+}
+
+static inline void reclaim_active_vcpus(struct csched_dom *ndom,
+ struct csched_dom *adom)
+{
+ BUG_ON(!(ndom->flags & SDOM_ACTIVE));
+ BUG_ON(adom->ndom != ndom);
+ if (ndom->flags & SDOM_ACTIVE && adom->ndom == ndom)
+ {
+ struct csched_vcpu *p, *n;
+
+ list_for_each_entry_safe(p, n, &ndom->active_vcpu, active_vcpu_elem)
+ {
+ if (p->sdom == adom)
+ {
+ list_del(&p->active_vcpu_elem);
+ list_add(&p->active_vcpu_elem, &adom->active_vcpu);
+ adom->active_vcpu_count++;
+ ndom->active_vcpu_count--;
+ }
+ }
+
+ if (list_empty(&ndom->active_vcpu) &&
+ !list_empty(&ndom->active_sdom_elem))
+ {
+ list_del_init(&ndom->active_sdom_elem);
+ csched_priv.weight -= ndom->weight;
+ }
+ if (!list_empty(&adom->active_vcpu) &&
+ list_empty(&adom->active_sdom_elem))
+ {
+ list_add(&adom->active_sdom_elem, &csched_priv.active_sdom);
+ csched_priv.weight += adom->weight;
+ }
+ }
+}
+
+static inline void add_adom_to_ndom(struct csched_dom *adom,
+ struct csched_dom *ndom)
+{
+ list_add(&adom->nemesis_elem, &ndom->nemesis_doms);
+ adom->ndom = ndom;
+ adom->flags |= SDOM_IS_ADOM;
+ ndom->flags |= SDOM_ACTIVE;
+ delegate_active_vcpus(adom, ndom);
+}
+
+static inline void rem_adom_from_ndom(struct csched_dom *adom,
+ struct csched_dom *ndom)
+{
+ reclaim_active_vcpus(ndom, adom);
+ adom->flags &= ~SDOM_IS_ADOM;
+ adom->ndom = 0;
+ list_del(&adom->nemesis_elem);
+ if (list_empty(&ndom->nemesis_doms))
+ ndom->flags &= ~SDOM_ACTIVE;
+}
+
static int
csched_pcpu_init(int cpu)
{
@@ -395,6 +511,17 @@ __csched_vcpu_check(struct vcpu *vc)
else
{
BUG_ON( !is_idle_vcpu(vc) );
+ }
+
+ if (sdom->flags & SDOM_ACTIVE)
+ {
+ BUG_ON(list_empty(&sdom->nemesis_doms));
+ BUG_ON(sdom->flags & SDOM_IS_ADOM);
+ }
+ if (sdom->flags & SDOM_IS_ADOM)
+ {
+ BUG_ON(list_empty(&sdom->nemesis_elem));
+ BUG_ON(sdom->flags & SDOM_ACTIVE);
}
CSCHED_STAT_CRANK(vcpu_check);
@@ -486,11 +613,11 @@ static inline void
static inline void
__csched_vcpu_acct_start(struct csched_vcpu *svc)
{
- struct csched_dom * const sdom = svc->sdom;
unsigned long flags;
-
+ struct csched_dom * sdom;
spin_lock_irqsave(&csched_priv.lock, flags);
+ sdom = accounting_dom(svc->sdom);
if ( list_empty(&svc->active_vcpu_elem) )
{
CSCHED_VCPU_STAT_CRANK(svc, state_active);
@@ -504,14 +631,13 @@ __csched_vcpu_acct_start(struct csched_v
csched_priv.weight += sdom->weight;
}
}
-
spin_unlock_irqrestore(&csched_priv.lock, flags);
}
static inline void
__csched_vcpu_acct_stop_locked(struct csched_vcpu *svc)
{
- struct csched_dom * const sdom = svc->sdom;
+ struct csched_dom * const sdom = accounting_dom(svc->sdom);
BUG_ON( list_empty(&svc->active_vcpu_elem) );
@@ -605,20 +731,33 @@ csched_vcpu_init(struct vcpu *vc)
return 0;
}
+static void nemesis_cleanup(struct csched_vcpu *svc)
+{
+ if (svc->sdom->flags & SDOM_IS_ADOM)
+ rem_adom_from_ndom(svc->sdom, accounting_dom(svc->sdom));
+ if (svc->sdom->flags & SDOM_ACTIVE)
+ {
+ struct csched_dom *p, *n;
+ list_for_each_entry_safe(p, n, &svc->sdom->nemesis_doms, nemesis_elem)
+ {
+ rem_adom_from_ndom(p, svc->sdom);
+ }
+ }
+}
+
+
static void
csched_vcpu_destroy(struct vcpu *vc)
{
struct csched_vcpu * const svc = CSCHED_VCPU(vc);
- struct csched_dom * const sdom = svc->sdom;
unsigned long flags;
CSCHED_STAT_CRANK(vcpu_destroy);
- BUG_ON( sdom == NULL );
BUG_ON( !list_empty(&svc->runq_elem) );
spin_lock_irqsave(&csched_priv.lock, flags);
-
+ nemesis_cleanup(svc);
if ( !list_empty(&svc->active_vcpu_elem) )
__csched_vcpu_acct_stop_locked(svc);
@@ -697,6 +836,108 @@ csched_vcpu_wake(struct vcpu *vc)
__runq_tickle(cpu, svc);
}
+static inline int
+_sanity_check(struct csched_dom *adom, struct csched_dom *ndom)
+{
+ if (adom->dom->domain_id == ndom->dom->domain_id)
+ return SDOM_err_same_id;
+ if (adom->flags & SDOM_ACTIVE)
+ return SDOM_err_already_sdom;
+ if (ndom->flags & SDOM_IS_ADOM)
+ return SDOM_err_already_adom;
+ return 0;
+}
+
+static inline int
+add_sanity_check(struct csched_dom *adom, struct csched_dom *ndom)
+{
+ if (adom->ndom)
+ return SDOM_err_inval;
+ return _sanity_check(adom, ndom);
+}
+
+static inline int
+rem_sanity_check(struct csched_dom *adom, struct csched_dom *ndom)
+{
+ if (adom->ndom && adom->ndom == ndom)
+ return _sanity_check(adom, ndom);
+ return SDOM_err_inval;
+}
+
+static int csched_sdom_op(struct xen_domctl_sdom * op)
+{
+ int ret = -EINVAL;
+
+ switch(op->op)
+ {
+ case SDOM_get_flags:
+ case SDOM_get_sdom:
+ {
+ struct domain *ndom = get_domain_by_id(op->sdom);
+ if (ndom)
+ {
+ struct csched_dom *p_ndom = csched_dom(ndom);
+ if (op->op == SDOM_get_flags)
+ op->flags = p_ndom->flags;
+ else
+ {
+ struct csched_dom *nemesis_dom = get_nemesis_dom(p_ndom);
+ if (nemesis_dom)
+ {
+ op->sdom = nemesis_dom->dom->domain_id;
+ put_domain(nemesis_dom->dom);
+ }
+ else
+ op->reason = SDOM_err_not_adom;
+ }
+ put_domain(ndom);
+ ret = 0;
+ }
+ break;
+ }
+
+ case SDOM_del_adom:
+ case SDOM_add_adom:
+ {
+
+ struct domain *adom, *ndom;
+ unsigned long flags;
+
+ ndom = get_domain_by_id(op->sdom);
+ if (!ndom)
+ break;
+ adom = get_domain_by_id(op->adom);
+ if (!adom)
+ goto release_ndom;
+ ret = 0;
+ if (op->op == SDOM_add_adom)
+ op->reason = add_sanity_check(csched_dom(adom), csched_dom(ndom));
+ else
+ op->reason = rem_sanity_check(csched_dom(adom), csched_dom(ndom));
+ if (op->reason)
+ goto release_adom;
+
+ spin_lock_irqsave(&csched_priv.lock, flags);
+ if (op->op == SDOM_add_adom)
+ add_adom_to_ndom(csched_dom(adom), csched_dom(ndom));
+ else
+ rem_adom_from_ndom(csched_dom(adom), csched_dom(ndom));
+ spin_unlock_irqrestore(&csched_priv.lock, flags);
+
+release_adom:
+ put_domain(adom);
+release_ndom:
+ put_domain(ndom);
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ return ret;
+}
+
static int
csched_dom_cntl(
struct domain *d,
@@ -754,10 +995,13 @@ csched_dom_init(struct domain *dom)
sdom->active_vcpu_count = 0;
INIT_LIST_HEAD(&sdom->active_sdom_elem);
sdom->dom = dom;
+ sdom->ndom = 0;
sdom->weight = CSCHED_DEFAULT_WEIGHT;
sdom->cap = 0U;
dom->sched_priv = sdom;
-
+ INIT_LIST_HEAD(&sdom->nemesis_doms);
+ INIT_LIST_HEAD(&sdom->nemesis_elem);
+ sdom->flags = 0U;
return 0;
}
@@ -942,7 +1186,6 @@ csched_acct(void)
list_for_each_safe( iter_vcpu, next_vcpu, &sdom->active_vcpu )
{
svc = list_entry(iter_vcpu, struct csched_vcpu, active_vcpu_elem);
- BUG_ON( sdom != svc->sdom );
/* Increment credit */
atomic_add(credit_fair, &svc->credit);
@@ -1384,6 +1627,7 @@ struct scheduler sched_credit_def = {
.sleep = csched_vcpu_sleep,
.wake = csched_vcpu_wake,
+ .sdom_op = csched_sdom_op,
.adjust = csched_dom_cntl,
.pick_cpu = csched_cpu_pick,
--
Mike D. Day
IBM LTC
Cell: 919 412-3900
Sametime: ncmike@xxxxxxxxxx AIM: ncmikeday Yahoo: ultra.runner
PGP key: http://www.ncultra.org/ncmike/pubkey.asc
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|