diff options
-rw-r--r-- | xen/common/sched_credit.c | 47 | ||||
-rw-r--r-- | xen/common/schedule.c | 5 | ||||
-rw-r--r-- | xen/include/xen/perfc_defn.h | 1 | ||||
-rw-r--r-- | xen/include/xen/sched-if.h | 5 |
4 files changed, 57 insertions, 1 deletions
diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c index c959a47d65..01f5999ffb 100644 --- a/xen/common/sched_credit.c +++ b/xen/common/sched_credit.c @@ -173,6 +173,7 @@ struct csched_private { uint32_t credit; int credit_balance; uint32_t runq_sort; + unsigned ratelimit_us; /* Period of master and tick in milliseconds */ unsigned tslice_ms, tick_period_us, ticks_per_tslice; unsigned credits_per_tslice; @@ -1301,10 +1302,15 @@ csched_schedule( struct csched_private *prv = CSCHED_PRIV(ops); struct csched_vcpu *snext; struct task_slice ret; + s_time_t runtime, tslice; CSCHED_STAT_CRANK(schedule); CSCHED_VCPU_CHECK(current); + runtime = now - current->runstate.state_entry_time; + if ( runtime < 0 ) /* Does this ever happen? */ + runtime = 0; + if ( !is_idle_vcpu(scurr->vcpu) ) { /* Update credits of a non-idle VCPU. */ @@ -1317,6 +1323,35 @@ csched_schedule( scurr->pri = CSCHED_PRI_IDLE; } + /* Choices, choices: + * - If we have a tasklet, we need to run the idle vcpu no matter what. + * - If sched rate limiting is in effect, and the current vcpu has + * run for less than that amount of time, continue the current one, + * but with a shorter timeslice and return it immediately + * - Otherwise, chose the one with the highest priority (which may + * be the one currently running) + * - If the currently running one is TS_OVER, see if there + * is a higher priority one waiting on the runqueue of another + * cpu and steal it. + */ + + /* If we have schedule rate limiting enabled, check to see + * how long we've run for. */ + if ( !tasklet_work_scheduled + && prv->ratelimit_us + && vcpu_runnable(current) + && !is_idle_vcpu(current) + && runtime < MICROSECS(prv->ratelimit_us) ) + { + snext = scurr; + snext->start_time += now; + perfc_incr(delay_ms); + tslice = MICROSECS(prv->ratelimit_us); + ret.migrated = 0; + goto out; + } + tslice = MILLISECS(prv->tslice_ms); + /* * Select next runnable local VCPU (ie top of local runq) */ @@ -1371,11 +1406,12 @@ csched_schedule( if ( !is_idle_vcpu(snext->vcpu) ) snext->start_time += now; +out: /* * Return task to run next... */ ret.time = (is_idle_vcpu(snext->vcpu) ? - -1 : MILLISECS(prv->tslice_ms)); + -1 : tslice); ret.task = snext->vcpu; CSCHED_VCPU_CHECK(ret.task); @@ -1537,6 +1573,15 @@ csched_init(struct scheduler *ops) prv->tick_period_us = prv->tslice_ms * 1000 / prv->ticks_per_tslice; prv->credits_per_tslice = CSCHED_CREDITS_PER_MSEC * prv->tslice_ms; + if ( MICROSECS(sched_ratelimit_us) > MILLISECS(sched_credit_tslice_ms) ) + { + printk("WARNING: sched_ratelimit_us >" + "sched_credit_tslice_ms is undefined\n" + "Setting ratelimit_us to 1000 * tslice_ms\n"); + prv->ratelimit_us = 1000 * prv->tslice_ms; + } + else + prv->ratelimit_us = sched_ratelimit_us; return 0; } diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 3a91220823..54658adca1 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -47,6 +47,11 @@ string_param("sched", opt_sched); bool_t sched_smt_power_savings = 0; boolean_param("sched_smt_power_savings", sched_smt_power_savings); +/* Default scheduling rate limit: 1ms + * The behavior when sched_ratelimit_us is greater than sched_credit_tslice_ms is undefined + * */ +int sched_ratelimit_us = 1000; +integer_param("sched_ratelimit_us", sched_ratelimit_us); /* Various timer handlers. */ static void s_timer_fn(void *unused); static void vcpu_periodic_timer_fn(void *data); diff --git a/xen/include/xen/perfc_defn.h b/xen/include/xen/perfc_defn.h index d166e2269b..0aef235f9d 100644 --- a/xen/include/xen/perfc_defn.h +++ b/xen/include/xen/perfc_defn.h @@ -16,6 +16,7 @@ PERFCOUNTER(sched_irq, "sched: timer") PERFCOUNTER(sched_run, "sched: runs through scheduler") PERFCOUNTER(sched_ctx, "sched: context switches") +PERFCOUNTER(delay_ms, "csched: delay") PERFCOUNTER(vcpu_check, "csched: vcpu_check") PERFCOUNTER(schedule, "csched: schedule") PERFCOUNTER(acct_run, "csched: acct_run") diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h index d9519f0d6c..03f9d8ddcc 100644 --- a/xen/include/xen/sched-if.h +++ b/xen/include/xen/sched-if.h @@ -16,6 +16,11 @@ extern struct cpupool *cpupool0; /* cpus currently in no cpupool */ extern cpumask_t cpupool_free_cpus; +/* Scheduler generic parameters + * */ +extern int sched_ratelimit_us; + + /* * In order to allow a scheduler to remap the lock->cpu mapping, * we have a per-cpu pointer, along with a pre-allocated set of |