diff -r 30ecae4339d5 tools/libxc/Makefile --- a/tools/libxc/Makefile Thu Aug 4 01:13:46 2005 +++ b/tools/libxc/Makefile Tue Aug 9 21:01:01 2005 @@ -16,6 +16,7 @@ INCLUDES += -I $(XEN_LIBXUTIL) SRCS := +SRCS += xc_sedf.c SRCS += xc_atropos.c SRCS += xc_bvtsched.c SRCS += xc_domain.c diff -r 30ecae4339d5 tools/libxc/xc.h --- a/tools/libxc/xc.h Thu Aug 4 01:13:46 2005 +++ b/tools/libxc/xc.h Tue Aug 9 21:01:01 2005 @@ -245,6 +245,14 @@ int xc_rrobin_global_get(int xc_handle, u64 *slice); +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; /*\ diff -r 30ecae4339d5 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Thu Aug 4 01:13:46 2005 +++ b/tools/python/xen/lowlevel/xc/xc.c Tue Aug 9 21:01:01 2005 @@ -785,6 +785,52 @@ return zero; } +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) @@ -1019,6 +1065,30 @@ "Get Round Robin scheduler settings\n" "Returns [dict]:\n" " slice [long]: Scheduler time slice.\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, diff -r 30ecae4339d5 tools/python/xen/xend/XendClient.py --- a/tools/python/xen/xend/XendClient.py Thu Aug 4 01:13:46 2005 +++ b/tools/python/xen/xend/XendClient.py Tue Aug 9 21:01:01 2005 @@ -272,6 +272,15 @@ 'slice' : slice, 'latency' : latency, 'xtratime': xtratime }) + + 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), diff -r 30ecae4339d5 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Thu Aug 4 01:13:46 2005 +++ b/tools/python/xen/xend/XendDomain.py Tue Aug 9 21:01:01 2005 @@ -663,6 +663,24 @@ return xc.atropos_domain_get(dominfo.dom) 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. diff -r 30ecae4339d5 tools/python/xen/xend/server/SrvDomain.py --- a/tools/python/xen/xend/server/SrvDomain.py Thu Aug 4 01:13:46 2005 +++ b/tools/python/xen/xend/server/SrvDomain.py Tue Aug 9 21:01:01 2005 @@ -114,6 +114,17 @@ ['slice', 'int'], ['latency', 'int'], ['xtratime', 'int']]) + 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 diff -r 30ecae4339d5 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Thu Aug 4 01:13:46 2005 +++ b/tools/python/xen/xm/main.py Tue Aug 9 21:01:01 2005 @@ -600,6 +600,23 @@ xm.prog(ProgRrobin) +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" diff -r 30ecae4339d5 xen/common/schedule.c --- a/xen/common/schedule.c Thu Aug 4 01:13:46 2005 +++ b/xen/common/schedule.c Tue Aug 9 21:01:01 2005 @@ -34,6 +34,8 @@ /*#define WAKE_HISTO*/ /*#define BLOCKTIME_HISTO*/ +/*#define ADV_SCHED_HISTO*/ +//#include #if defined(WAKE_HISTO) #define BUCKETS 31 @@ -72,10 +74,12 @@ extern struct scheduler sched_bvt_def; extern struct scheduler sched_rrobin_def; extern struct scheduler sched_atropos_def; +extern struct scheduler sched_sedf_def; static struct scheduler *schedulers[] = { &sched_bvt_def, &sched_rrobin_def, &sched_atropos_def, + &sched_sedf_def, NULL }; @@ -192,6 +196,10 @@ /* Block the currently-executing domain until a pertinent event occurs. */ long do_block(void) { +#ifdef ADV_SCHED_HISTO + adv_sched_hist_start(current->processor); +#endif + ASSERT(current->id != IDLE_DOMAIN_ID); current->shared_info->vcpu_data[0].evtchn_upcall_mask = 0; set_bit(DF_BLOCKED, ¤t->flags); @@ -203,6 +211,10 @@ /* 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->id, current); __enter_scheduler(); return 0; @@ -285,7 +297,7 @@ if ( cmd->sched_id != ops.sched_id ) return -EINVAL; - + if ( cmd->direction != SCHED_INFO_PUT && cmd->direction != SCHED_INFO_GET ) return -EINVAL; @@ -319,8 +331,14 @@ 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); @@ -356,9 +374,12 @@ 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; - + } perfc_incrc(sched_ctx); cleanup_writable_pagetable(prev); @@ -382,7 +403,6 @@ #endif TRACE_2D(TRC_SCHED_SWITCH, next->id, next); - switch_to(prev, next); /* @@ -396,6 +416,9 @@ /* Ensure that the domain has an up-to-date time base. */ if ( !is_idle_task(next) && update_dom_time(next) ) send_guest_virq(next, VIRQ_TIMER); +#ifdef ADV_SCHED_HISTO + adv_sched_hist_to_stop(cpu); +#endif schedule_tail(next); @@ -420,6 +443,10 @@ /* 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 + TRACE_0D(TRC_SCHED_S_TIMER_FN); raise_softirq(SCHEDULE_SOFTIRQ); perfc_incrc(sched_irq); @@ -560,6 +587,63 @@ 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 diff -r 30ecae4339d5 xen/include/public/sched_ctl.h --- a/xen/include/public/sched_ctl.h Thu Aug 4 01:13:46 2005 +++ b/xen/include/public/sched_ctl.h Tue Aug 9 21:01:01 2005 @@ -11,6 +11,7 @@ #define SCHED_BVT 0 #define SCHED_ATROPOS 2 #define SCHED_RROBIN 3 +#define SCHED_SEDF 4 /* these describe the intended direction used for a scheduler control or domain * command */ @@ -64,6 +65,16 @@ u64 latency; /* 32 */ u32 xtratime; /* 36 */ } PACKED atropos; + + 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 */ diff -r 30ecae4339d5 xen/include/xen/sched-if.h --- a/xen/include/xen/sched-if.h Thu Aug 4 01:13:46 2005 +++ b/xen/include/xen/sched-if.h Tue Aug 9 21:01:01 2005 @@ -7,7 +7,9 @@ * Portions by Mark Williamson are (C) 2004 Intel Research Cambridge */ -#define BUCKETS 10 +//#define ADV_SCHED_HISTO +#define BUCKETS 10 +/*300*/ typedef struct schedule_data_st { @@ -17,6 +19,11 @@ struct domain *idle; /* idle task for this cpu */ void * sched_priv; struct ac_timer s_timer; /* scheduling timer */ +#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 @@ -55,5 +62,3 @@ /* per CPU scheduler information */ extern schedule_data_t schedule_data[]; - -