mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
bitkeeper revision 1.1389.5.37 (427f9fd5lvofpMsmBQ2h16fsuXQH6Q)
Manual merge.
This commit is contained in:
commit
bb5ae6b5cc
15 files changed
+1929
-19
No files matched your search
@@ -21,6 +21,7 @@
|
||||
412f4bd9sm5mCQ8BkrgKcAKZGadq7Q docs/misc/blkif-drivers-explained.txt
|
||||
420b949cy9ZGzED74Fz_DaWlK7tT4g docs/misc/crashdb.txt
|
||||
4251a1f82AexscYEiF4Iku8Gc_kWfQ docs/misc/grant-tables.txt
|
||||
424d462b5GuApQ_NyMsRFt9LbrsWow docs/misc/sedf_scheduler_mini-HOWTO.txt
|
||||
40d6ccbfKKBq8jE0ula4eHEzBiQuDA docs/misc/xen_config.html
|
||||
410a4c2bAO_m_l4RsiiPHnZ4ixHWbQ docs/misc/xend.tex
|
||||
3f9e7d564bWFB-Czjv1qdmE6o0GqNg docs/src/interface.tex
|
||||
@@ -742,6 +743,7 @@
|
||||
3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/xc_private.h
|
||||
42337174PxyzzPk62raDiYCIsfStDg tools/libxc/xc_ptrace.c
|
||||
4273458duzL--nsTfT6e_q6Kfij48g tools/libxc/xc_ptrace_core.c
|
||||
41ebbfe9U0b0kI-HgjK7VEY4EvW7_w tools/libxc/xc_sedf.c
|
||||
41dde8b0pLfAKMs_L9Uri2hnzHiCRQ tools/libxc/xc_vmx_build.c
|
||||
40e1b09dMYB4ItGCqcMIzirdMd9I-w tools/libxutil/Makefile
|
||||
40e033325Sjqs-_4TuzeUEprP_gYFg tools/libxutil/allocate.c
|
||||
@@ -1261,6 +1263,7 @@
|
||||
3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c
|
||||
3ddb79bdHqdQpATqC0rmUZNbsb6L6A xen/common/resource.c
|
||||
40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c
|
||||
41ebbfe9oF1BF3cH5v7yE3eOL9uPbA xen/common/sched_sedf.c
|
||||
3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c
|
||||
3ddb79bd0gVQYmL2zvuJnldvD0AGxQ xen/common/softirq.c
|
||||
3e7f358awXBC3Vw-wFRwPw18qL1khg xen/common/string.c
|
||||
@@ -1409,6 +1412,7 @@
|
||||
3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/public/xen.h
|
||||
3e397e66m2tO3s-J8Jnr7Ws_tGoPTg xen/include/xen/ac_timer.h
|
||||
40715b2epYl2jBbxzz9CI2rgIca7Zg xen/include/xen/acpi.h
|
||||
422f0995xCgnbsVhTjSncnqIABs64g xen/include/xen/adv_sched_hist.h
|
||||
3ddb79c0c0cX_DZE209-Bb-Rx1v-Aw xen/include/xen/cache.h
|
||||
41f2cea7Yna7xc0X9fyavIjoSFFeVg xen/include/xen/compile.h.in
|
||||
3f840f12CkbYSlwMrY2S11Mpyxg7Nw xen/include/xen/compiler.h
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
sEDF scheduler
|
||||
--------------
|
||||
Author:
|
||||
Stephan.Diestelhorst@{cl.cam.ac.uk, inf.tu-dresden.de}
|
||||
|
||||
Overview:
|
||||
This scheduler provides weighted CPU sharing in an intuitive way and
|
||||
uses realtime-algorithms to ensure time guarantees.
|
||||
|
||||
Usage:
|
||||
-add "sched=sedf" on Xen's boot command-line
|
||||
-create domains as usual
|
||||
-use "xm sedf <dom-id> <period> <slice> <latency-hint> <extra> <weight>"
|
||||
Where:
|
||||
-period/slice are the normal EDF scheduling parameters in nanosecs
|
||||
-latency-hint is the scaled period in case the domain is doing heavy I/O
|
||||
(unused by the currently compiled version)
|
||||
-extra is a flag (0/1), which controls whether the domain can run in
|
||||
extra-time
|
||||
-weight is mutually exclusive with period/slice and specifies another
|
||||
way of setting a domains cpu slice
|
||||
|
||||
Examples:
|
||||
normal EDF (20ms/5ms):
|
||||
xm sedf <dom-id> 20000000 5000000 0 0 0
|
||||
|
||||
best-effort domains (i.e. non-realtime):
|
||||
xm sedf <dom-id> 20000000 0 0 1 0
|
||||
|
||||
normal EDF (20ms/5ms) + share of extra-time:
|
||||
xm sedf <dom-id> 20000000 5000000 0 1 0
|
||||
|
||||
4 domains with weights 2:3:4:2
|
||||
xm sedf <d1> 0 0 0 0 2
|
||||
xm sedf <d2> 0 0 0 0 3
|
||||
xm sedf <d3> 0 0 0 0 4
|
||||
xm sedf <d4> 0 0 0 0 2
|
||||
|
||||
1 fully-specified (10ms/3ms) domain, 3 other domains share
|
||||
available rest in 2:7:3 ratio:
|
||||
xm sedf <d1> 10000000 3000000 0 0 0
|
||||
xm sedf <d2> 0 0 0 0 2
|
||||
xm sedf <d3> 0 0 0 0 7
|
||||
xm sedf <d4> 0 0 0 0 3
|
||||
@@ -16,6 +16,7 @@ vpath %c $(XEN_LIBXUTIL)
|
||||
INCLUDES += -I $(XEN_LIBXUTIL)
|
||||
|
||||
SRCS :=
|
||||
SRCS += xc_sedf.c
|
||||
SRCS += xc_bvtsched.c
|
||||
SRCS += xc_core.c
|
||||
SRCS += xc_domain.c
|
||||
|
||||
@@ -296,6 +296,14 @@ int xc_bvtsched_domain_get(int xc_handle,
|
||||
long long *warpl,
|
||||
long long *warpu);
|
||||
|
||||
int xc_sedf_domain_set(int xc_handle,
|
||||
u32 domid,
|
||||
u64 period, u64 slice, u64 latency, u16 extratime, u16 weight);
|
||||
|
||||
int xc_sedf_domain_get(int xc_handle,
|
||||
u32 domid,
|
||||
u64* period, u64 *slice, u64 *latency, u16 *extratime, u16* weight);
|
||||
|
||||
typedef evtchn_status_t xc_evtchn_status_t;
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/******************************************************************************
|
||||
* xc_sedf.c
|
||||
*
|
||||
* API for manipulating parameters of the Simple EDF scheduler.
|
||||
*
|
||||
* changes by Stephan Diestelhorst
|
||||
* based on code
|
||||
* by Mark Williamson, Copyright (c) 2004 Intel Research Cambridge.
|
||||
*/
|
||||
|
||||
#include "xc_private.h"
|
||||
|
||||
int xc_sedf_domain_set(int xc_handle,
|
||||
u32 domid, u64 period, u64 slice,u64 latency, u16 extratime,u16 weight)
|
||||
{
|
||||
dom0_op_t op;
|
||||
struct sedf_adjdom *p = &op.u.adjustdom.u.sedf;
|
||||
|
||||
op.cmd = DOM0_ADJUSTDOM;
|
||||
op.u.adjustdom.domain = (domid_t)domid;
|
||||
op.u.adjustdom.sched_id = SCHED_SEDF;
|
||||
op.u.adjustdom.direction = SCHED_INFO_PUT;
|
||||
|
||||
p->period = period;
|
||||
p->slice = slice;
|
||||
p->latency = latency;
|
||||
p->extratime = extratime;
|
||||
p->weight = weight;
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
int xc_sedf_domain_get(int xc_handle, u32 domid, u64 *period, u64 *slice, u64* latency, u16* extratime, u16* weight)
|
||||
{
|
||||
dom0_op_t op;
|
||||
int ret;
|
||||
struct sedf_adjdom *p = &op.u.adjustdom.u.sedf;
|
||||
|
||||
op.cmd = DOM0_ADJUSTDOM;
|
||||
op.u.adjustdom.domain = (domid_t)domid;
|
||||
op.u.adjustdom.sched_id = SCHED_SEDF;
|
||||
op.u.adjustdom.direction = SCHED_INFO_GET;
|
||||
|
||||
ret = do_dom0_op(xc_handle, &op);
|
||||
|
||||
*period = p->period;
|
||||
*slice = p->slice;
|
||||
*latency = p->latency;
|
||||
*extratime = p->extratime;
|
||||
*weight = p->weight;
|
||||
return ret;
|
||||
}
|
||||
@@ -827,6 +827,52 @@ static PyObject *pyxc_physinfo(PyObject *self,
|
||||
"cpu_khz", info.cpu_khz);
|
||||
}
|
||||
|
||||
static PyObject *pyxc_sedf_domain_set(PyObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
XcObject *xc = (XcObject *)self;
|
||||
u32 domid;
|
||||
u64 period, slice, latency;
|
||||
u16 extratime, weight;
|
||||
static char *kwd_list[] = { "dom", "period", "slice", "latency", "extratime", "weight",NULL };
|
||||
|
||||
if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list, &domid,
|
||||
&period, &slice, &latency, &extratime, &weight) )
|
||||
return NULL;
|
||||
if ( xc_sedf_domain_set(xc->xc_handle, domid, period, slice, latency, extratime,weight) != 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
Py_INCREF(zero);
|
||||
return zero;
|
||||
}
|
||||
|
||||
static PyObject *pyxc_sedf_domain_get(PyObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
XcObject *xc = (XcObject *)self;
|
||||
u32 domid;
|
||||
u64 period, slice,latency;
|
||||
u16 weight, extratime;
|
||||
|
||||
static char *kwd_list[] = { "dom", NULL };
|
||||
|
||||
if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
|
||||
return NULL;
|
||||
|
||||
if ( xc_sedf_domain_get( xc->xc_handle, domid, &period,
|
||||
&slice,&latency,&extratime,&weight) )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
|
||||
"domain", domid,
|
||||
"period", period,
|
||||
"slice", slice,
|
||||
"latency", latency,
|
||||
"extratime", extratime);
|
||||
}
|
||||
|
||||
static PyObject *pyxc_shadow_control(PyObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
@@ -1027,6 +1073,30 @@ static PyMethodDef pyxc_methods[] = {
|
||||
" warpu [long]: Unwarp requirement.\n"
|
||||
" warpl [long]: Warp limit,\n"
|
||||
},
|
||||
|
||||
{ "sedf_domain_set",
|
||||
(PyCFunction)pyxc_sedf_domain_set,
|
||||
METH_KEYWORDS, "\n"
|
||||
"Set the scheduling parameters for a domain when running with Atropos.\n"
|
||||
" dom [int]: domain to set\n"
|
||||
" period [long]: domain's scheduling period\n"
|
||||
" slice [long]: domain's slice per period\n"
|
||||
" latency [long]: domain's wakeup latency hint\n"
|
||||
" extratime [int]: domain aware of extratime?\n"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "sedf_domain_get",
|
||||
(PyCFunction)pyxc_sedf_domain_get,
|
||||
METH_KEYWORDS, "\n"
|
||||
"Get the current scheduling parameters for a domain when running with\n"
|
||||
"the Atropos scheduler."
|
||||
" dom [int]: domain to query\n"
|
||||
"Returns: [dict]\n"
|
||||
" domain [int]: domain ID\n"
|
||||
" period [long]: scheduler period\n"
|
||||
" slice [long]: CPU reservation per period\n"
|
||||
" latency [long]: domain's wakeup latency hint\n"
|
||||
" extratime [int]: domain aware of extratime?\n"},
|
||||
|
||||
{ "evtchn_alloc_unbound",
|
||||
(PyCFunction)pyxc_evtchn_alloc_unbound,
|
||||
|
||||
@@ -260,6 +260,15 @@ class Xend:
|
||||
'warpl' : warpl,
|
||||
'warpu' : warpu })
|
||||
|
||||
def xend_domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight):
|
||||
return self.xendPost(self.domainurl(id),
|
||||
{'op' : 'cpu_sedf_set',
|
||||
'period' : period,
|
||||
'slice' : slice,
|
||||
'latency' : latency,
|
||||
'extratime' : extratime,
|
||||
'weight' : weight })
|
||||
|
||||
def xend_domain_maxmem_set(self, id, memory):
|
||||
return self.xendPost(self.domainurl(id),
|
||||
{ 'op' : 'maxmem_set',
|
||||
|
||||
@@ -644,6 +644,24 @@ class XendDomain:
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
|
||||
def domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight):
|
||||
"""Set Simple EDF scheduler parameters for a domain.
|
||||
"""
|
||||
dominfo = self.domain_lookup(id)
|
||||
try:
|
||||
return xc.sedf_domain_set(dominfo.dom, period, slice, latency, extratime, weight)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
def domain_cpu_sedf_get(self, id):
|
||||
"""Get Atropos scheduler parameters for a domain.
|
||||
"""
|
||||
dominfo = self.domain_lookup(id)
|
||||
try:
|
||||
return xc.sedf_domain_get(dominfo.dom)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
def domain_device_create(self, id, devconfig):
|
||||
"""Create a new device for a domain.
|
||||
|
||||
|
||||
@@ -107,6 +107,18 @@ class SrvDomain(SrvDir):
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
|
||||
def op_cpu_sedf_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_cpu_sedf_set,
|
||||
[['dom', 'str'],
|
||||
['period', 'int'],
|
||||
['slice', 'int'],
|
||||
['latency', 'int'],
|
||||
['extratime', 'int'],
|
||||
['weight', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_maxmem_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_maxmem_set,
|
||||
[['dom', 'str'],
|
||||
|
||||
@@ -591,6 +591,23 @@ class ProgBvtslice(Prog):
|
||||
|
||||
xm.prog(ProgBvtslice)
|
||||
|
||||
class ProgSedf(Prog):
|
||||
group = 'scheduler'
|
||||
name= "sedf"
|
||||
info = """Set simple EDF parameters."""
|
||||
|
||||
def help(self, args):
|
||||
print args[0], "DOM PERIOD SLICE LATENCY EXTRATIME WEIGHT"
|
||||
print "\nSet simple EDF parameters."
|
||||
|
||||
def main(self, args):
|
||||
if len(args) != 7: self.err("%s: Invalid argument(s)" % args[0])
|
||||
dom = args[1]
|
||||
v = map(int, args[2:7])
|
||||
server.xend_domain_cpu_sedf_set(dom, *v)
|
||||
|
||||
xm.prog(ProgSedf)
|
||||
|
||||
class ProgInfo(Prog):
|
||||
group = 'host'
|
||||
name = "info"
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+143
-6
@@ -40,6 +40,17 @@
|
||||
static char opt_sched[10] = "bvt";
|
||||
string_param("sched", opt_sched);
|
||||
|
||||
/*#define WAKE_HISTO*/
|
||||
/*#define BLOCKTIME_HISTO*/
|
||||
/*#define ADV_SCHED_HISTO*/
|
||||
//#include <xen/adv_sched_hist.h>
|
||||
|
||||
#if defined(WAKE_HISTO)
|
||||
#define BUCKETS 31
|
||||
#elif defined(BLOCKTIME_HISTO)
|
||||
#define BUCKETS 200
|
||||
#endif
|
||||
|
||||
#define TIME_SLOP (s32)MICROSECS(50) /* allow time to slip a bit */
|
||||
|
||||
/* Various timer handlers. */
|
||||
@@ -51,8 +62,10 @@ static void dom_timer_fn(unsigned long data);
|
||||
struct schedule_data schedule_data[NR_CPUS];
|
||||
|
||||
extern struct scheduler sched_bvt_def;
|
||||
extern struct scheduler sched_sedf_def;
|
||||
static struct scheduler *schedulers[] = {
|
||||
&sched_bvt_def,
|
||||
&sched_sedf_def,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -226,6 +239,10 @@ long do_block(void)
|
||||
{
|
||||
struct exec_domain *ed = current;
|
||||
|
||||
#ifdef ADV_SCHED_HISTO
|
||||
adv_sched_hist_start(current->processor);
|
||||
#endif
|
||||
|
||||
ed->vcpu_info->evtchn_upcall_mask = 0;
|
||||
set_bit(EDF_BLOCKED, &ed->flags);
|
||||
|
||||
@@ -246,6 +263,10 @@ long do_block(void)
|
||||
/* Voluntarily yield the processor for this allocation. */
|
||||
static long do_yield(void)
|
||||
{
|
||||
#ifdef ADV_SCHED_HISTO
|
||||
adv_sched_hist_start(current->processor);
|
||||
#endif
|
||||
|
||||
TRACE_2D(TRC_SCHED_YIELD, current->domain->id, current->id);
|
||||
__enter_scheduler();
|
||||
return 0;
|
||||
@@ -275,6 +296,7 @@ long do_sched_op(unsigned long op)
|
||||
|
||||
case SCHEDOP_shutdown:
|
||||
{
|
||||
TRACE_3D(TRC_SCHED_SHUTDOWN, current->domain->id, current->id,
|
||||
TRACE_3D(TRC_SCHED_SHUTDOWN, current->domain->id, current->id,
|
||||
(op >> SCHEDOP_reasonshift));
|
||||
domain_shutdown((u8)(op >> SCHEDOP_reasonshift));
|
||||
@@ -322,10 +344,22 @@ long sched_ctl(struct sched_ctl_cmd *cmd)
|
||||
long sched_adjdom(struct sched_adjdom_cmd *cmd)
|
||||
{
|
||||
struct domain *d;
|
||||
struct exec_domain *ed;
|
||||
int cpu;
|
||||
#if NR_CPUS <=32
|
||||
unsigned long have_lock;
|
||||
#else
|
||||
unsigned long long have_lock;
|
||||
#endif
|
||||
int succ;
|
||||
|
||||
#define __set_cpu_bit(cpu, data) data |= ((typeof(data))1)<<cpu
|
||||
#define __get_cpu_bit(cpu, data) (data & ((typeof(data))1)<<cpu)
|
||||
#define __clear_cpu_bits(data) data = ((typeof(data))0)
|
||||
|
||||
if ( cmd->sched_id != ops.sched_id )
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
if ( cmd->direction != SCHED_INFO_PUT && cmd->direction != SCHED_INFO_GET )
|
||||
return -EINVAL;
|
||||
|
||||
@@ -333,9 +367,38 @@ long sched_adjdom(struct sched_adjdom_cmd *cmd)
|
||||
if ( d == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
spin_lock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock);
|
||||
/* acquire locks on all CPUs on which exec_domains of this domain run */
|
||||
do {
|
||||
succ = 0;
|
||||
__clear_cpu_bits(have_lock);
|
||||
for_each_exec_domain(d, ed) {
|
||||
cpu = ed->processor;
|
||||
if (!__get_cpu_bit(cpu, have_lock)) {
|
||||
/* if we don't have a lock on this CPU: acquire it*/
|
||||
if (spin_trylock(&schedule_data[cpu].schedule_lock)) {
|
||||
/*we have this lock!*/
|
||||
__set_cpu_bit(cpu, have_lock);
|
||||
succ = 1;
|
||||
} else {
|
||||
/*we didn,t get this lock -> free all other locks too!*/
|
||||
for (cpu = 0; cpu < NR_CPUS; cpu++)
|
||||
if (__get_cpu_bit(cpu, have_lock))
|
||||
spin_unlock(&schedule_data[cpu].schedule_lock);
|
||||
/* and start from the beginning! */
|
||||
succ = 0;
|
||||
/* leave the "for_each_domain_loop" */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!succ);
|
||||
//spin_lock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock);
|
||||
SCHED_OP(adjdom, d, cmd);
|
||||
spin_unlock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock);
|
||||
//spin_unlock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock);
|
||||
for (cpu = 0; cpu < NR_CPUS; cpu++)
|
||||
if (__get_cpu_bit(cpu, have_lock))
|
||||
spin_unlock(&schedule_data[cpu].schedule_lock);
|
||||
__clear_cpu_bits(have_lock);
|
||||
|
||||
TRACE_1D(TRC_SCHED_ADJDOM, d->id);
|
||||
put_domain(d);
|
||||
@@ -358,8 +421,14 @@ static void __enter_scheduler(void)
|
||||
perfc_incrc(sched_run);
|
||||
|
||||
spin_lock_irq(&schedule_data[cpu].schedule_lock);
|
||||
|
||||
|
||||
#ifdef ADV_SCHED_HISTO
|
||||
adv_sched_hist_from_stop(cpu);
|
||||
#endif
|
||||
now = NOW();
|
||||
#ifdef ADV_SCHED_HISTO
|
||||
adv_sched_hist_start(cpu);
|
||||
#endif
|
||||
|
||||
rem_ac_timer(&schedule_data[cpu].s_timer);
|
||||
|
||||
@@ -386,9 +455,12 @@ static void __enter_scheduler(void)
|
||||
|
||||
spin_unlock_irq(&schedule_data[cpu].schedule_lock);
|
||||
|
||||
if ( unlikely(prev == next) )
|
||||
if ( unlikely(prev == next) ) {
|
||||
#ifdef ADV_SCHED_HISTO
|
||||
adv_sched_hist_to_stop(cpu);
|
||||
#endif
|
||||
return continue_running(prev);
|
||||
|
||||
}
|
||||
perfc_incrc(sched_ctx);
|
||||
|
||||
#if defined(WAKE_HISTO)
|
||||
@@ -423,6 +495,10 @@ static void __enter_scheduler(void)
|
||||
prev->domain->id, prev->id,
|
||||
next->domain->id, next->id);
|
||||
|
||||
#ifdef ADV_SCHED_HISTO
|
||||
adv_sched_hist_to_stop(cpu);
|
||||
#endif
|
||||
|
||||
context_switch(prev, next);
|
||||
}
|
||||
|
||||
@@ -444,6 +520,10 @@ int idle_cpu(int cpu)
|
||||
/* The scheduler timer: force a run through the scheduler */
|
||||
static void s_timer_fn(unsigned long unused)
|
||||
{
|
||||
#ifdef ADV_SCHED_HISTO
|
||||
adv_sched_hist_start(current->processor);
|
||||
#endif
|
||||
|
||||
raise_softirq(SCHEDULE_SOFTIRQ);
|
||||
perfc_incrc(sched_irq);
|
||||
}
|
||||
@@ -587,9 +667,66 @@ void reset_sched_histo(unsigned char key)
|
||||
schedule_data[j].hist[i] = 0;
|
||||
}
|
||||
#else
|
||||
#if defined(ADV_SCHED_HISTO)
|
||||
void print_sched_histo(unsigned char key)
|
||||
{
|
||||
int i, j, k,t;
|
||||
printf("Hello!\n");
|
||||
for ( k = 0; k < smp_num_cpus; k++ )
|
||||
{
|
||||
j = 0;
|
||||
t = 0;
|
||||
printf ("CPU[%02d]: scheduler latency histogram FROM (ms:[count])\n", k);
|
||||
for ( i = 0; i < BUCKETS; i++ )
|
||||
{
|
||||
//if ( schedule_data[k].hist[i] != 0 )
|
||||
{
|
||||
t += schedule_data[k].from_hist[i];
|
||||
if ( i < BUCKETS-1 )
|
||||
printk("%3d:[%7u] ", i, schedule_data[k].from_hist[i]);
|
||||
else
|
||||
printk(" >:[%7u] ", schedule_data[k].from_hist[i]);
|
||||
//if ( !(++j % 5) )
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
printk("\nTotal: %i\n",t);
|
||||
}
|
||||
for ( k = 0; k < smp_num_cpus; k++ )
|
||||
{
|
||||
j = 0; t = 0;
|
||||
printf ("CPU[%02d]: scheduler latency histogram TO (ms:[count])\n", k);
|
||||
for ( i = 0; i < BUCKETS; i++ )
|
||||
{
|
||||
//if ( schedule_data[k].hist[i] != 0 )
|
||||
{
|
||||
t += schedule_data[k].from_hist[i];
|
||||
if ( i < BUCKETS-1 )
|
||||
printk("%3d:[%7u] ", i, schedule_data[k].to_hist[i]);
|
||||
else
|
||||
printk(" >:[%7u] ", schedule_data[k].to_hist[i]);
|
||||
//if ( !(++j % 5) )
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
printk("\nTotal: %i\n",t);
|
||||
}
|
||||
|
||||
}
|
||||
void reset_sched_histo(unsigned char key)
|
||||
{
|
||||
int i, j;
|
||||
for ( j = 0; j < smp_num_cpus; j++ ) {
|
||||
for ( i=0; i < BUCKETS; i++ )
|
||||
schedule_data[j].to_hist[i] = schedule_data[j].from_hist[i] = 0;
|
||||
schedule_data[j].save_tsc = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void print_sched_histo(unsigned char key) { }
|
||||
void reset_sched_histo(unsigned char key) { }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
/* Scheduler types. */
|
||||
#define SCHED_BVT 0
|
||||
#define SCHED_SEDF 4
|
||||
|
||||
/* Set or get info? */
|
||||
#define SCHED_INFO_PUT 0
|
||||
@@ -31,18 +32,31 @@ struct sched_ctl_cmd
|
||||
|
||||
struct sched_adjdom_cmd
|
||||
{
|
||||
u32 sched_id;
|
||||
u32 direction;
|
||||
domid_t domain;
|
||||
union {
|
||||
struct bvt_adjdom {
|
||||
u32 mcu_adv; /* mcu advance: inverse of weight */
|
||||
u32 warpback; /* warp? */
|
||||
s32 warpvalue; /* warp value */
|
||||
long long warpl; /* warp limit */
|
||||
long long warpu; /* unwarp time requirement */
|
||||
} bvt;
|
||||
} u;
|
||||
};
|
||||
u32 sched_id; /* 0 */
|
||||
u32 direction; /* 4 */
|
||||
domid_t domain; /* 8 */
|
||||
u16 __pad0;
|
||||
u32 __pad1;
|
||||
union { /* 16 */
|
||||
struct bvt_adjdom
|
||||
{
|
||||
u32 mcu_adv; /* 16: mcu advance: inverse of weight */
|
||||
u32 warpback; /* 20: warp? */
|
||||
s32 warpvalue; /* 24: warp value */
|
||||
long long warpl; /* 32: warp limit */
|
||||
long long warpu; /* 40: unwarp time requirement */
|
||||
} PACKED bvt;
|
||||
|
||||
struct sedf_adjdom
|
||||
{
|
||||
u64 period; /* 16 */
|
||||
u64 slice; /* 24 */
|
||||
u64 latency; /* 32 */
|
||||
u16 extratime; /* 36 */
|
||||
u16 weight; /* 38 */
|
||||
} PACKED sedf;
|
||||
|
||||
} PACKED u;
|
||||
} PACKED; /* 40 bytes */
|
||||
|
||||
#endif /* __XEN_PUBLIC_SCHED_CTL_H__ */
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Some functions to suport advanced scheduler histograms
|
||||
Author: Stephan.Diestelhorst@cl.cam.ac.uk */
|
||||
//#include <xen/sched.h>
|
||||
//#include <xen/sched-if.h>
|
||||
#include <asm/msr.h>
|
||||
#define ADV_SCHED_HISTO
|
||||
static inline void adv_sched_hist_start(int cpu) {
|
||||
u64 now;
|
||||
rdtscll(now);
|
||||
if (!schedule_data[cpu].save_tsc)
|
||||
schedule_data[cpu].save_tsc = now;
|
||||
}
|
||||
static inline void adv_sched_hist_from_stop(int cpu) {
|
||||
u64 now;
|
||||
rdtscll(now);
|
||||
if (schedule_data[cpu].save_tsc) {
|
||||
now -= schedule_data[cpu].save_tsc;
|
||||
now /= 7;
|
||||
if (now < BUCKETS-1)
|
||||
schedule_data[cpu].from_hist[now]++;
|
||||
else
|
||||
schedule_data[cpu].from_hist[BUCKETS-1]++;
|
||||
|
||||
schedule_data[cpu].save_tsc = 0;
|
||||
}
|
||||
}
|
||||
static inline void adv_sched_hist_to_stop(int cpu) {
|
||||
u64 now;
|
||||
rdtscll(now);
|
||||
if (schedule_data[cpu].save_tsc) {
|
||||
now -= schedule_data[cpu].save_tsc;
|
||||
now /= 24;
|
||||
if (now < BUCKETS-1)
|
||||
schedule_data[cpu].to_hist[now]++;
|
||||
else
|
||||
schedule_data[cpu].to_hist[BUCKETS-1]++;
|
||||
|
||||
schedule_data[cpu].save_tsc = 0;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,10 @@
|
||||
#ifndef __XEN_SCHED_IF_H__
|
||||
#define __XEN_SCHED_IF_H__
|
||||
|
||||
//#define ADV_SCHED_HISTO
|
||||
#define BUCKETS 10
|
||||
/*300*/
|
||||
|
||||
struct schedule_data {
|
||||
spinlock_t schedule_lock; /* spinlock protecting curr */
|
||||
struct exec_domain *curr; /* current task */
|
||||
@@ -15,6 +19,11 @@ struct schedule_data {
|
||||
void *sched_priv;
|
||||
struct ac_timer s_timer; /* scheduling timer */
|
||||
unsigned long tick; /* current periodic 'tick' */
|
||||
#ifdef ADV_SCHED_HISTO
|
||||
u32 to_hist[BUCKETS];
|
||||
u32 from_hist[BUCKETS];
|
||||
u64 save_tsc;
|
||||
#endif
|
||||
#ifdef BUCKETS
|
||||
u32 hist[BUCKETS]; /* for scheduler latency histogram */
|
||||
#endif
|
||||
|
||||