summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--recipes-extended/xen/xen-rt/rt-xen_0.3_4.0.1.patch6785
-rw-r--r--recipes-extended/xen/xen-rt_4.0.1.bb25
2 files changed, 0 insertions, 6810 deletions
diff --git a/recipes-extended/xen/xen-rt/rt-xen_0.3_4.0.1.patch b/recipes-extended/xen/xen-rt/rt-xen_0.3_4.0.1.patch
deleted file mode 100644
index 8a0034f5..00000000
--- a/recipes-extended/xen/xen-rt/rt-xen_0.3_4.0.1.patch
+++ /dev/null
@@ -1,6785 +0,0 @@
1Patch constructed from ZIP posted at developer site - https://sites.google.com/site/realtimexen/download
2
3http://students.cec.wustl.edu/~sx1/RT-XEN/xen0512.zip
4
5diff -ubrN xen/xen-4.0.1/tools/libxc/Makefile xen-4.0.1/tools/libxc/Makefile
6--- xen/xen-4.0.1/tools/libxc/Makefile 2010-08-25 04:22:09.000000000 -0600
7+++ xen-4.0.1/tools/libxc/Makefile 2011-04-24 20:29:11.000000000 -0600
8@@ -17,6 +17,7 @@
9 CTRL_SRCS-y += xc_private.c
10 CTRL_SRCS-y += xc_sedf.c
11 CTRL_SRCS-y += xc_csched.c
12+CTRL_SRCS-y += xc_rt.c
13 CTRL_SRCS-y += xc_tbuf.c
14 CTRL_SRCS-y += xc_pm.c
15 CTRL_SRCS-y += xc_cpu_hotplug.c
16diff -ubrN xen/xen-4.0.1/tools/libxc/xc_rt.c xen-4.0.1/tools/libxc/xc_rt.c
17--- xen/xen-4.0.1/tools/libxc/xc_rt.c 1969-12-31 17:00:00.000000000 -0700
18+++ xen-4.0.1/tools/libxc/xc_rt.c 2011-04-24 20:52:41.000000000 -0600
19@@ -0,0 +1,49 @@
20+/****************************************************************************
21+ * (C) 2006 - Emmanuel Ackaouy - XenSource Inc.
22+ ****************************************************************************
23+ *
24+ * File: xc_rt.c
25+ * Author: Sisu Xi
26+ *
27+ * Description: XC Interface to the ds scheduler
28+ *
29+ */
30+#include "xc_private.h"
31+
32+int
33+xc_sched_rt_domain_set(
34+ int xc_handle,
35+ uint32_t domid,
36+ struct xen_domctl_sched_rt *sdom)
37+{
38+ DECLARE_DOMCTL;
39+
40+ domctl.cmd = XEN_DOMCTL_scheduler_op;
41+ domctl.domain = (domid_t) domid;
42+ domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_RT;
43+ domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
44+ domctl.u.scheduler_op.u.rt = *sdom;
45+
46+ return do_domctl(xc_handle, &domctl);
47+}
48+
49+int
50+xc_sched_rt_domain_get(
51+ int xc_handle,
52+ uint32_t domid,
53+ struct xen_domctl_sched_rt *sdom)
54+{
55+ DECLARE_DOMCTL;
56+ int err;
57+
58+ domctl.cmd = XEN_DOMCTL_scheduler_op;
59+ domctl.domain = (domid_t) domid;
60+ domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_RT;
61+ domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
62+
63+ err = do_domctl(xc_handle, &domctl);
64+ if ( err == 0 )
65+ *sdom = domctl.u.scheduler_op.u.rt;
66+
67+ return err;
68+}
69diff -ubrN xen/xen-4.0.1/tools/libxc/xenctrl.h xen-4.0.1/tools/libxc/xenctrl.h
70--- xen/xen-4.0.1/tools/libxc/xenctrl.h 2010-08-25 04:22:09.000000000 -0600
71+++ xen-4.0.1/tools/libxc/xenctrl.h 2011-04-24 15:41:12.000000000 -0600
72@@ -465,6 +465,15 @@
73 uint32_t domid,
74 struct xen_domctl_sched_credit *sdom);
75
76+// added by Sisu Xi
77+int xc_sched_rt_domain_set(int xc_handle,
78+ uint32_t domid,
79+ struct xen_domctl_sched_rt *sdom);
80+
81+int xc_sched_rt_domain_get(int xc_handle,
82+ uint32_t domid,
83+ struct xen_domctl_sched_rt *sdom);
84+
85 /**
86 * This function sends a trigger to a domain.
87 *
88diff -ubrN xen/xen-4.0.1/tools/libxl/libxl.c xen-4.0.1/tools/libxl/libxl.c
89--- xen/xen-4.0.1/tools/libxl/libxl.c 2010-08-25 04:22:09.000000000 -0600
90+++ xen-4.0.1/tools/libxl/libxl.c 2011-04-24 15:50:49.000000000 -0600
91@@ -2766,6 +2766,64 @@
92 if (rc != 0)
93 return rc;
94
95+ return 0;
96+}
97+
98+// added by Sisu Xi
99+
100+int libxl_sched_rt_domain_get(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_rt *scinfo)
101+{
102+ struct xen_domctl_sched_rt sdom;
103+ int rc;
104+
105+ rc = xc_sched_rt_domain_get(ctx->xch, domid, &sdom);
106+ if (rc != 0)
107+ return rc;
108+
109+ scinfo->budget = sdom.budget;
110+ scinfo->period = sdom.period;
111+ scinfo->level = sdom.level;
112+
113+ return 0;
114+}
115+
116+int libxl_sched_rt_domain_set(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_rt *scinfo)
117+{
118+ struct xen_domctl_sched_rt sdom;
119+ xc_domaininfo_t domaininfo;
120+ int rc;
121+
122+ rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
123+ if (rc != 1 || domaininfo.domain != domid)
124+ return rc;
125+
126+
127+ if (scinfo->budget < 1 || scinfo->budget > 65535) {
128+ XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
129+ "Cpu budget out of range, valid values are within range from 1 to 65535");
130+ return -1;
131+ }
132+
133+ if (scinfo->period < 1 || scinfo->period > 65535) {
134+ XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
135+ "Cpu period out of range, valid values are within range from 1 to 65535");
136+ return -1;
137+ }
138+
139+ if (scinfo->level < 1 || scinfo->level > 65535) {
140+ XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
141+ "Cpu level out of range, valid values are within range from 1 to 65535");
142+ return -1;
143+ }
144+
145+ sdom.budget = scinfo->budget;
146+ sdom.period = scinfo->period;
147+ sdom.level = scinfo->level;
148+
149+ rc = xc_sched_rt_domain_set(ctx->xch, domid, &sdom);
150+ if (rc != 0)
151+ return rc;
152+
153 return 0;
154 }
155
156diff -ubrN xen/xen-4.0.1/tools/libxl/libxl.h xen-4.0.1/tools/libxl/libxl.h
157--- xen/xen-4.0.1/tools/libxl/libxl.h 2010-08-25 04:22:09.000000000 -0600
158+++ xen-4.0.1/tools/libxl/libxl.h 2011-04-24 15:47:43.000000000 -0600
159@@ -499,10 +499,23 @@
160 int cap;
161 };
162
163+// added by Sisu Xi
164+struct libxl_sched_rt {
165+ int budget;
166+ int period;
167+ int level;
168+};
169+
170 int libxl_sched_credit_domain_get(struct libxl_ctx *ctx, uint32_t domid,
171 struct libxl_sched_credit *scinfo);
172 int libxl_sched_credit_domain_set(struct libxl_ctx *ctx, uint32_t domid,
173 struct libxl_sched_credit *scinfo);
174+
175+// added by Sisu Xi
176+int libxl_sched_rt_domain_get(struct libxl_ctx *ctx, uint32_t domid,
177+ struct libxl_sched_rt *scinfo);
178+int libxl_sched_rt_domain_set(struct libxl_ctx *ctx, uint32_t domid,
179+ struct libxl_sched_rt *scinfo);
180 int libxl_send_trigger(struct libxl_ctx *ctx, uint32_t domid,
181 char *trigger_name, uint32_t vcpuid);
182 int libxl_send_sysrq(struct libxl_ctx *ctx, uint32_t domid, char sysrq);
183diff -ubrN xen/xen-4.0.1/tools/libxl/xl_cmdimpl.c xen-4.0.1/tools/libxl/xl_cmdimpl.c
184--- xen/xen-4.0.1/tools/libxl/xl_cmdimpl.c 2010-08-25 04:22:10.000000000 -0600
185+++ xen-4.0.1/tools/libxl/xl_cmdimpl.c 2011-04-24 15:33:20.000000000 -0600
186@@ -2989,8 +2989,7 @@
187 printf("xen_minor : %d\n", info->xen_version_minor);
188 printf("xen_extra : %s\n", info->xen_version_extra);
189 printf("xen_caps : %s\n", info->capabilities);
190- printf("xen_scheduler : %s\n",
191- sched_id == XEN_SCHEDULER_SEDF ? "sedf" : "credit");
192+ printf("xen_scheduler : %d\n", sched_id);
193 printf("xen_pagesize : %lu\n", info->pagesize);
194 printf("platform_params : virt_start=0x%lx\n", info->virt_start);
195 printf("xen_changeset : %s\n", info->changeset);
196@@ -3190,6 +3189,242 @@
197 exit(0);
198 }
199
200+
201+//added by Sisu Xi
202+static int sched_rt_domain_get(
203+ int domid, struct libxl_sched_rt *scinfo)
204+{
205+ int rc;
206+
207+ rc = libxl_sched_rt_domain_get(&ctx, domid, scinfo);
208+ if (rc)
209+ fprintf(stderr, "libxl_sched_rt_domain_get failed.\n");
210+
211+ return rc;
212+}
213+
214+static int sched_rt_domain_set(
215+ int domid, struct libxl_sched_rt *scinfo)
216+{
217+ int rc;
218+
219+ rc = libxl_sched_rt_domain_set(&ctx, domid, scinfo);
220+ if (rc)
221+ fprintf(stderr, "libxl_sched_rt_domain_set failed.\n");
222+
223+ return rc;
224+}
225+
226+static void sched_rt_domain_output(
227+ int domid, struct libxl_sched_rt *scinfo)
228+{
229+ printf("%-33s %4d %6d %4d %4d\n",
230+ libxl_domid_to_name(&ctx, domid),
231+ domid,
232+ scinfo->budget,
233+ scinfo->period,
234+ scinfo->level);
235+}
236+
237+int main_sched_rt(int argc, char **argv)
238+{
239+ struct libxl_dominfo *info;
240+ struct libxl_sched_rt scinfo;
241+ int nb_domain, i;
242+ char *dom = NULL;
243+ int budget = 25, period = 50, level = 10, opt_w = 0, opt_c = 0, opt_l = 0;
244+ int opt, rc;
245+
246+ while ((opt = getopt(argc, argv, "hd:b:p:l:")) != -1) {
247+ switch (opt) {
248+ case 'd':
249+ dom = optarg;
250+ break;
251+ case 'b':
252+ budget = strtol(optarg, NULL, 10);
253+ opt_w = 1;
254+ break;
255+ case 'p':
256+ period = strtol(optarg, NULL, 10);
257+ opt_c = 1;
258+ break;
259+ case 'l':
260+ level = strtol(optarg, NULL, 10);
261+ opt_l = 1;
262+ break;
263+ case 'h':
264+ help("sched-rt");
265+ exit(0);
266+ default:
267+ fprintf(stderr, "option `%c' not supported.\n", opt);
268+ break;
269+ }
270+ }
271+
272+ if (!dom && (opt_w || opt_c || opt_l)) {
273+ fprintf(stderr, "Must specify a domain.\n");
274+ exit(1);
275+ }
276+
277+ if (!dom) { /* list all domain's ds scheduler info */
278+ info = libxl_list_domain(&ctx, &nb_domain);
279+ if (!info) {
280+ fprintf(stderr, "libxl_domain_infolist failed.\n");
281+ exit(1);
282+ }
283+
284+ printf("%-33s %4s %6s %4s %4s\n", "Name", "ID", "Budget", "Period", "Level");
285+ for (i = 0; i < nb_domain; i++) {
286+ rc = sched_rt_domain_get(info[i].domid, &scinfo);
287+ if (rc)
288+ exit(-rc);
289+ sched_rt_domain_output(info[i].domid, &scinfo);
290+ }
291+ } else {
292+ find_domain(dom);
293+
294+ rc = sched_rt_domain_get(domid, &scinfo);
295+ if (rc)
296+ exit(-rc);
297+
298+ if (!opt_w && !opt_c && !opt_l) { /* output ds scheduler info */
299+ printf("%-33s %4s %6s %4s %4s\n", "Name", "ID", "Budget", "Period", "Level");
300+ sched_rt_domain_output(domid, &scinfo);
301+ } else { /* set ds scheduler paramaters */
302+ if (opt_w)
303+ scinfo.budget = budget;
304+ if (opt_c)
305+ scinfo.period = period;
306+ if (opt_l)
307+ scinfo.level = level;
308+ rc = sched_rt_domain_set(domid, &scinfo);
309+ if (rc)
310+ exit(-rc);
311+ }
312+ }
313+
314+ exit(0);
315+}
316+
317+//
318+//
319+// static int sched_ps_domain_get(
320+// int domid, struct libxl_sched_ps *scinfo)
321+// {
322+// int rc;
323+//
324+// rc = libxl_sched_ps_domain_get(&ctx, domid, scinfo);
325+// if (rc)
326+// fprintf(stderr, "libxl_sched_ps_domain_get failed.\n");
327+//
328+// return rc;
329+// }
330+//
331+// static int sched_ps_domain_set(
332+// int domid, struct libxl_sched_ps *scinfo)
333+// {
334+// int rc;
335+//
336+// rc = libxl_sched_ps_domain_set(&ctx, domid, scinfo);
337+// if (rc)
338+// fprintf(stderr, "libxl_sched_ps_domain_set failed.\n");
339+//
340+// return rc;
341+// }
342+//
343+// static void sched_ps_domain_output(
344+// int domid, struct libxl_sched_ps *scinfo)
345+// {
346+// printf("%-33s %4d %6d %4d %4d\n",
347+// libxl_domid_to_name(&ctx, domid),
348+// domid,
349+// scinfo->cost,
350+// scinfo->period,
351+// scinfo->level);
352+// }
353+//
354+// int main_sched_ps(int argc, char **argv)
355+// {
356+// struct libxl_dominfo *info;
357+// struct libxl_sched_ps scinfo;
358+// int nb_domain, i;
359+// char *dom = NULL;
360+// int cost = 25, period = 50, level = 10, opt_w = 0, opt_c = 0, opt_l = 0;
361+// int opt, rc;
362+//
363+// while ((opt = getopt(argc, argv, "hd:c:p:l:")) != -1) {
364+// switch (opt) {
365+// case 'd':
366+// dom = optarg;
367+// break;
368+// case 'c':
369+// cost = strtol(optarg, NULL, 10);
370+// opt_w = 1;
371+// break;
372+// case 'p':
373+// period = strtol(optarg, NULL, 10);
374+// opt_c = 1;
375+// break;
376+// case 'l':
377+// level = strtol(optarg, NULL, 10);
378+// opt_l = 1;
379+// break;
380+// case 'h':
381+// help("sched-ps");
382+// exit(0);
383+// default:
384+// fprintf(stderr, "option `%c' not supported.\n", opt);
385+// break;
386+// }
387+// }
388+//
389+// if (!dom && (opt_w || opt_c || opt_l)) {
390+// fprintf(stderr, "Must specify a domain.\n");
391+// exit(1);
392+// }
393+//
394+// if (!dom) { /* list all domain's ps scheduler info */
395+// info = libxl_list_domain(&ctx, &nb_domain);
396+// if (!info) {
397+// fprintf(stderr, "libxl_domain_infolist failed.\n");
398+// exit(1);
399+// }
400+//
401+// printf("%-33s %4s %6s %4s %4s\n", "Name", "ID", "Cost", "Period", "Level");
402+// for (i = 0; i < nb_domain; i++) {
403+// rc = sched_ps_domain_get(info[i].domid, &scinfo);
404+// if (rc)
405+// exit(-rc);
406+// sched_ps_domain_output(info[i].domid, &scinfo);
407+// }
408+// } else {
409+// find_domain(dom);
410+//
411+// rc = sched_ps_domain_get(domid, &scinfo);
412+// if (rc)
413+// exit(-rc);
414+//
415+// if (!opt_w && !opt_c && !opt_l) { /* output ps scheduler info */
416+// printf("%-33s %4s %6s %4s %4s\n", "Name", "ID", "Cost", "Period", "Level");
417+// sched_ps_domain_output(domid, &scinfo);
418+// } else { /* set ps scheduler paramaters */
419+// if (opt_w)
420+// scinfo.cost = cost;
421+// if (opt_c)
422+// scinfo.period = period;
423+// if (opt_l)
424+// scinfo.level = level;
425+// rc = sched_ps_domain_set(domid, &scinfo);
426+// if (rc)
427+// exit(-rc);
428+// }
429+// }
430+//
431+// exit(0);
432+// }
433+
434+
435+
436 int main_domid(int argc, char **argv)
437 {
438 int opt;
439diff -ubrN xen/xen-4.0.1/tools/libxl/xl_cmdtable.c xen-4.0.1/tools/libxl/xl_cmdtable.c
440--- xen/xen-4.0.1/tools/libxl/xl_cmdtable.c 2010-08-25 04:22:10.000000000 -0600
441+++ xen-4.0.1/tools/libxl/xl_cmdtable.c 2011-04-24 15:32:54.000000000 -0600
442@@ -175,6 +175,16 @@
443 "-w WEIGHT, --weight=WEIGHT Weight (int)\n"
444 "-c CAP, --cap=CAP Cap (int)"
445 },
446+ //added by Sisu Xi
447+ { "sched-rt",
448+ &main_sched_rt,
449+ "Get/Set RT scheduler parameters",
450+ "[-d <Domain> [-b[=BUDGET]|-p[=PERIOD]|-l[=LEVEL]]]",
451+ "-d DOMAIN, --domain = DOMAIN Domain to modify\n"
452+ "-b BUDGET, --budget = BUDGET Budget (int)\n"
453+ "-p PERIOD, --period = PERIOD Period (int)\n"
454+ "-l LEVEL, --level = LEVEL Level (int)"
455+ },
456 { "domid",
457 &main_domid,
458 "Convert a domain name to domain id",
459diff -ubrN xen/xen-4.0.1/tools/libxl/xl.h xen-4.0.1/tools/libxl/xl.h
460--- xen/xen-4.0.1/tools/libxl/xl.h 2010-08-25 04:22:09.000000000 -0600
461+++ xen-4.0.1/tools/libxl/xl.h 2011-04-24 15:24:44.000000000 -0600
462@@ -49,6 +49,8 @@
463 int main_memmax(int argc, char **argv);
464 int main_memset(int argc, char **argv);
465 int main_sched_credit(int argc, char **argv);
466+//added by Sisu Xi
467+int main_sched_rt(int argc, char **argv);
468 int main_domid(int argc, char **argv);
469 int main_domname(int argc, char **argv);
470 int main_rename(int argc, char **argv);
471diff -ubrN xen/xen-4.0.1/tools/python/xen/lowlevel/xc/xc.c xen-4.0.1/tools/python/xen/lowlevel/xc/xc.c
472--- xen/xen-4.0.1/tools/python/xen/lowlevel/xc/xc.c 2010-08-25 04:22:10.000000000 -0600
473+++ xen-4.0.1/tools/python/xen/lowlevel/xc/xc.c 2011-04-24 15:42:16.000000000 -0600
474@@ -1455,6 +1455,54 @@
475 "cap", sdom.cap);
476 }
477
478+// added by Sisu Xi
479+static PyObject *pyxc_sched_rt_domain_set(XcObject *self,
480+ PyObject *args,
481+ PyObject *kwds)
482+{
483+ uint32_t domid;
484+ uint16_t budget;
485+ uint16_t period;
486+ uint16_t level;
487+ static char *kwd_list[] = { "domid", "budget", "period", "level", NULL };
488+ static char kwd_type[] = "I|HHH";
489+ struct xen_domctl_sched_rt sdom;
490+
491+ budget = 25;
492+ period = 50;
493+ level = 10;
494+ if( !PyArg_ParseTupleAndKeywords(args, kwds, kwd_type, kwd_list,
495+ &domid, &budget, &period, &level) )
496+ return NULL;
497+
498+ sdom.budget = budget;
499+ sdom.period = period;
500+ sdom.level = level;
501+
502+ if ( xc_sched_rt_domain_set(self->xc_handle, domid, &sdom) != 0 )
503+ return pyxc_error_to_exception();
504+
505+ Py_INCREF(zero);
506+ return zero;
507+}
508+
509+static PyObject *pyxc_sched_rt_domain_get(XcObject *self, PyObject *args)
510+{
511+ uint32_t domid;
512+ struct xen_domctl_sched_rt sdom;
513+
514+ if( !PyArg_ParseTuple(args, "I", &domid) )
515+ return NULL;
516+
517+ if ( xc_sched_rt_domain_get(self->xc_handle, domid, &sdom) != 0 )
518+ return pyxc_error_to_exception();
519+
520+ return Py_BuildValue("{s:H,s:H,s:H}",
521+ "budget", sdom.budget,
522+ "period", sdom.period,
523+ "level", sdom.level);
524+}
525+
526 static PyObject *pyxc_domain_setmaxmem(XcObject *self, PyObject *args)
527 {
528 uint32_t dom;
529@@ -2010,6 +2058,26 @@
530 "Returns: [dict]\n"
531 " weight [short]: domain's scheduling weight\n"},
532
533+// added by Sisu Xi
534+ { "sched_rt_domain_set",
535+ (PyCFunction)pyxc_sched_rt_domain_set,
536+ METH_KEYWORDS, "\n"
537+ "Set the scheduling parameters for a domain when running with the\n"
538+ "SMP ds scheduler.\n"
539+ " domid [int]: domain id to set\n"
540+ " budget [short]: domain's scheduling budget\n"
541+ "Returns: [int] 0 on success; -1 on error.\n" },
542+
543+ { "sched_rt_domain_get",
544+ (PyCFunction)pyxc_sched_rt_domain_get,
545+ METH_VARARGS, "\n"
546+ "Get the scheduling parameters for a domain when running with the\n"
547+ "SMP ds scheduler.\n"
548+ " domid [int]: domain id to get\n"
549+ "Returns: [dict]\n"
550+ " budget [short]: domain's scheduling budget\n"},
551+
552+
553 { "evtchn_alloc_unbound",
554 (PyCFunction)pyxc_evtchn_alloc_unbound,
555 METH_VARARGS | METH_KEYWORDS, "\n"
556@@ -2378,7 +2446,10 @@
557 /* Expose some libxc constants to Python */
558 PyModule_AddIntConstant(m, "XEN_SCHEDULER_SEDF", XEN_SCHEDULER_SEDF);
559 PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT", XEN_SCHEDULER_CREDIT);
560-
561+ // PyModule_AddIntConstant(m, "XEN_SCHEDULER_SS", XEN_SCHEDULER_SS);
562+ // added by Sisu Xi
563+ PyModule_AddIntConstant(m, "XEN_SCHEDULER_RT", XEN_SCHEDULER_RT);
564+ // PyModule_AddIntConstant(m, "XEN_SCHEDULER_PS", XEN_SCHEDULER_PS);
565 }
566
567
568diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/server/SrvDomain.py xen-4.0.1/tools/python/xen/xend/server/SrvDomain.py
569--- xen/xen-4.0.1/tools/python/xen/xend/server/SrvDomain.py 2010-08-25 04:22:10.000000000 -0600
570+++ xen-4.0.1/tools/python/xen/xend/server/SrvDomain.py 2011-04-24 15:43:07.000000000 -0600
571@@ -163,6 +163,22 @@
572 val = fn(req.args, {'dom': self.dom.getName()})
573 return val
574
575+# added by Sisu Xi
576+ def op_domain_sched_rt_get(self, _, req):
577+ fn = FormFn(self.xd.domain_sched_rt_get,
578+ [['dom', 'str']])
579+ val = fn(req.args, {'dom': self.dom.getName()})
580+ return val
581+
582+ def op_domain_sched_rt_set(self, _, req):
583+ fn = FormFn(self.xd.domain_sched_rt_set,
584+ [['dom', 'str'],
585+ ['budget', 'int'],
586+ ['period', 'int'],
587+ ['level', 'int']])
588+ val = fn(req.args, {'dom': self.dom.getName()})
589+ return val
590+
591 def op_maxmem_set(self, _, req):
592 return self.call(self.dom.setMemoryMaximum,
593 [['memory', 'int']],
594diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendAPI.py xen-4.0.1/tools/python/xen/xend/XendAPI.py
595--- xen/xen-4.0.1/tools/python/xen/xend/XendAPI.py 2010-08-25 04:22:10.000000000 -0600
596+++ xen-4.0.1/tools/python/xen/xend/XendAPI.py 2011-04-24 15:40:40.000000000 -0600
597@@ -1629,6 +1629,16 @@
598 cap = xeninfo.info['vcpus_params']['cap']
599 xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
600
601+# added by Sisu Xi
602+ #need to update sched params aswell
603+ elif 'budget' in xeninfo.info['vcpus_params'] \
604+ and 'period' in xeninfo.info['vcpus_params'] \
605+ and 'level' in xeninfo.info['vcpus_params']:
606+ budget = xeninfo.info['vcpus_params']['budget']
607+ period = xeninfo.info['vcpus_params']['period']
608+ level = xeninfo.info['vcpus_params']['level']
609+ xendom.domain_sched_rt_set(xeninfo.getDomid(), budget, period, level)
610+
611 def VM_set_VCPUs_number_live(self, _, vm_ref, num):
612 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
613 dom.setVCpuCount(int(num))
614diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendConfig.py xen-4.0.1/tools/python/xen/xend/XendConfig.py
615--- xen/xen-4.0.1/tools/python/xen/xend/XendConfig.py 2010-08-25 04:22:10.000000000 -0600
616+++ xen-4.0.1/tools/python/xen/xend/XendConfig.py 2011-01-13 09:50:30.000000000 -0700
617@@ -677,6 +677,15 @@
618 int(sxp.child_value(sxp_cfg, "cpu_weight", 256))
619 cfg["vcpus_params"]["cap"] = \
620 int(sxp.child_value(sxp_cfg, "cpu_cap", 0))
621+ cfg["vcpus_params"]["budget"] = \
622+ int(sxp.child_value(sxp_cfg, "cpu_budget", 25))
623+ cfg["vcpus_params"]["cost"] = \
624+ int(sxp.child_value(sxp_cfg, "cpu_cost", 25))
625+ cfg["vcpus_params"]["period"] = \
626+ int(sxp.child_value(sxp_cfg, "cpu_period", 50))
627+ cfg["vcpus_params"]["level"] = \
628+ int(sxp.child_value(sxp_cfg, "cpu_level", 10))
629+
630
631 # Only extract options we know about.
632 extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG + \
633@@ -1057,6 +1066,14 @@
634 int(self['vcpus_params'].get('weight', 256))
635 self['vcpus_params']['cap'] = \
636 int(self['vcpus_params'].get('cap', 0))
637+ self['vcpus_params']['budget'] = \
638+ int(self['vcpus_params'].get('budget', 25))
639+ self['vcpus_params']['cost'] = \
640+ int(self['vcpus_params'].get('cost', 25))
641+ self['vcpus_params']['period'] = \
642+ int(self['vcpus_params'].get('period', 50))
643+ self['vcpus_params']['level'] = \
644+ int(self['vcpus_params'].get('level', 10))
645
646 for key, val in self['vcpus_params'].items():
647 if key.startswith('cpumap'):
648@@ -1098,6 +1115,10 @@
649 if legacy_only:
650 sxpr.append(['cpu_weight', int(self['vcpus_params'].get('weight', 256))])
651 sxpr.append(['cpu_cap', int(self['vcpus_params'].get('cap', 0))])
652+ sxpr.append(['cpu_budget', int(self['vcpus_params'].get('budget', 25))])
653+ sxpr.append(['cpu_cost', int(self['vcpus_params'].get('cost', 25))])
654+ sxpr.append(['cpu_period', int(self['vcpus_params'].get('period', 50))])
655+ sxpr.append(['cpu_level', int(self['vcpus_params'].get('level', 10))])
656 else:
657 for name, typ in XENAPI_CFG_TYPES.items():
658 if name in self and self[name] not in (None, []):
659diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendDomainInfo.py xen-4.0.1/tools/python/xen/xend/XendDomainInfo.py
660--- xen/xen-4.0.1/tools/python/xen/xend/XendDomainInfo.py 2010-08-25 04:22:10.000000000 -0600
661+++ xen-4.0.1/tools/python/xen/xend/XendDomainInfo.py 2011-04-24 15:38:43.000000000 -0600
662@@ -2019,6 +2019,25 @@
663 def setWeight(self, cpu_weight):
664 self.info['vcpus_params']['weight'] = cpu_weight
665
666+# added by Sisu Xi
667+ def getBudget(self):
668+ return self.info['vcpus_params']['budget']
669+
670+ def setBudget(self, cpu_budget):
671+ self.info['vcpus_params']['budget'] = cpu_budget
672+
673+ def getPeriod(self):
674+ return self.info['vcpus_params']['period']
675+
676+ def setPeriod(self, cpu_period):
677+ self.info['vcpus_params']['period'] = cpu_period
678+
679+ def getLevel(self):
680+ return self.info['vcpus_params']['level']
681+
682+ def setLevel(self, cpu_level):
683+ self.info['vcpus_params']['level'] = cpu_level
684+
685 def getRestartCount(self):
686 return self._readVm('xend/restart_count')
687
688@@ -2616,6 +2635,26 @@
689 raise VmError("Cpu cap out of range, valid range is from 0 to %s for specified number of vcpus" %
690 (self.getVCpuCount() * 100))
691
692+ # added by Sisu Xi
693+ # Check for cpu_{period|budget} validity for ds scheduler
694+ if XendNode.instance().xenschedinfo() == 'rt':
695+ period = self.getPeriod()
696+ budget = self.getBudget()
697+ level = self.getLevel()
698+
699+ assert type(budget) == int
700+ assert type(period) == int
701+ assert type(level) == int
702+
703+ if budget < 1 or budget > 65535:
704+ raise VmError("Cpu budget out of range, valid values are within range from 1 to 65535")
705+
706+ if period < 1 or period > 65535:
707+ raise VmError("Cpu period out of range, valid values are within range from 1 to 65535")
708+
709+ if level < 1 or level > 65535:
710+ raise VmError("Cpu level out of range, valid values are within range from 1 to 65535")
711+
712 # Test whether the devices can be assigned with VT-d
713 self.info.update_platform_pci()
714 pci = self.info["platform"].get("pci")
715@@ -2811,6 +2850,14 @@
716 XendDomain.instance().domain_sched_credit_set(self.getDomid(),
717 self.getWeight(),
718 self.getCap())
719+# added by Sisu Xi
720+ def _setSchedParams(self):
721+ if XendNode.instance().xenschedinfo() == 'rt':
722+ from xen.xend import XendDomain
723+ XendDomain.instance().domain_sched_rt_set(self.getDomid(),
724+ self.getBudget(),
725+ self.getPeriod(),
726+ self.getLevel())
727
728 def _initDomain(self):
729 log.debug('XendDomainInfo.initDomain: %s %s',
730@@ -3574,7 +3621,11 @@
731 if self.getDomid() is None:
732 return self.info['vcpus_params']
733
734+ if XendNode.instance().xenschedinfo() == 'credit':
735 retval = xc.sched_credit_domain_get(self.getDomid())
736+ # added by Sisu Xi
737+ elif XendNode.instance().xenschedinfo() == 'rt':
738+ retval = xc.sched_rt_domain_get(self.getDomid())
739 return retval
740 def get_power_state(self):
741 return XEN_API_VM_POWER_STATE[self._stateGet()]
742diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendDomain.py xen-4.0.1/tools/python/xen/xend/XendDomain.py
743--- xen/xen-4.0.1/tools/python/xen/xend/XendDomain.py 2010-08-25 04:22:10.000000000 -0600
744+++ xen-4.0.1/tools/python/xen/xend/XendDomain.py 2011-04-24 15:39:47.000000000 -0600
745@@ -1757,6 +1757,90 @@
746 log.exception(ex)
747 raise XendError(str(ex))
748
749+# added by Sisu Xi
750+ def domain_sched_rt_get(self, domid):
751+ """Get ds scheduler parameters for a domain.
752+
753+ @param domid: Domain ID or Name
754+ @type domid: int or string.
755+ @rtype: dict with keys 'budget' and 'period'
756+ @return: ds scheduler parameters
757+ """
758+ dominfo = self.domain_lookup_nr(domid)
759+ if not dominfo:
760+ raise XendInvalidDomain(str(domid))
761+
762+ if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
763+ try:
764+ return xc.sched_rt_domain_get(dominfo.getDomid())
765+ except Exception, ex:
766+ raise XendError(str(ex))
767+ else:
768+ return {'budget' : dominfo.getBudget(),
769+ 'period' : dominfo.getPeriod(),
770+ 'level' : dominfo.getLevel()}
771+
772+ def domain_sched_rt_set(self, domid, budget = None, period = None, level = None):
773+ """Set ds scheduler parameters for a domain.
774+
775+ @param domid: Domain ID or Name
776+ @type domid: int or string.
777+ @type budget: int
778+ @type period: int
779+ @rtype: 0
780+ """
781+ set_budget = False
782+ set_period = False
783+ set_level = False
784+ dominfo = self.domain_lookup_nr(domid)
785+ if not dominfo:
786+ raise XendInvalidDomain(str(domid))
787+ try:
788+ if budget is None:
789+ budget = int(0)
790+ elif budget < 1 or budget > 65535:
791+ raise XendError("Cpu budget out of range, valid values are "
792+ "within range from 1 to 65535")
793+ else:
794+ set_budget = True
795+
796+ if period is None:
797+ period = int(0)
798+ elif period < 1 or period > 65535:
799+ raise XendError("Cpu period out of range, valid values are "
800+ "within range from 1 to 65535")
801+ else:
802+ set_period = True
803+
804+ if level is None:
805+ level = int(0)
806+ elif level < 1 or level > 65535:
807+ raise XendError("Cpu level out of range, valid values are "
808+ "within range from 1 to 65535")
809+ else:
810+ set_level = True
811+
812+ assert type(budget) == int
813+ assert type(period) == int
814+ assert type(level) == int
815+
816+ rc = 0
817+ if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
818+ rc = xc.sched_rt_domain_set(dominfo.getDomid(), budget, period, level)
819+ if rc == 0:
820+ if set_budget:
821+ dominfo.setBudget(budget)
822+ if set_period:
823+ dominfo.setPeriod(period)
824+ if set_level:
825+ dominfo.setLevel(level)
826+ self.managed_config_save(dominfo)
827+ return rc
828+ except Exception, ex:
829+ log.exception(ex)
830+ raise XendError(str(ex))
831+
832+
833 def domain_maxmem_set(self, domid, mem):
834 """Set the memory limit for a domain.
835
836diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendNode.py xen-4.0.1/tools/python/xen/xend/XendNode.py
837--- xen/xen-4.0.1/tools/python/xen/xend/XendNode.py 2010-08-25 04:22:10.000000000 -0600
838+++ xen-4.0.1/tools/python/xen/xend/XendNode.py 2011-04-24 15:35:48.000000000 -0600
839@@ -779,6 +779,9 @@
840 return 'sedf'
841 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
842 return 'credit'
843+ # added by Sisu Xi
844+ elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_RT:
845+ return 'rt'
846 else:
847 return 'unknown'
848
849@@ -981,6 +984,9 @@
850 return 'sedf'
851 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
852 return 'credit'
853+ # added by Sisu Xi
854+ elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_RT:
855+ return 'rt'
856 else:
857 return 'unknown'
858
859diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendVMMetrics.py xen-4.0.1/tools/python/xen/xend/XendVMMetrics.py
860--- xen/xen-4.0.1/tools/python/xen/xend/XendVMMetrics.py 2010-08-25 04:22:10.000000000 -0600
861+++ xen-4.0.1/tools/python/xen/xend/XendVMMetrics.py 2011-04-24 15:35:09.000000000 -0600
862@@ -129,7 +129,10 @@
863 params_live['cpumap%i' % i] = \
864 ",".join(map(str, info['cpumap']))
865
866+ if XendNode.instance().xenschedinfo() == 'credit':
867 params_live.update(xc.sched_credit_domain_get(domid))
868+ elif XendNode.instance().xenschedinfo() == 'rt':
869+ params_live.update(xc.sched_rt_domain_get(domid))
870
871 return params_live
872 else:
873diff -ubrN xen/xen-4.0.1/tools/python/xen/xm/main.py xen-4.0.1/tools/python/xen/xm/main.py
874--- xen/xen-4.0.1/tools/python/xen/xm/main.py 2010-08-25 04:22:10.000000000 -0600
875+++ xen-4.0.1/tools/python/xen/xm/main.py 2011-04-24 15:47:00.000000000 -0600
876@@ -151,6 +151,9 @@
877 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
878 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
879 'Get/set credit scheduler parameters.'),
880+ # added by Sisu Xi
881+ 'sched-rt' : ('[-d <Domain> [-b[=BUDGET]|-p[=PERIOD]|-l[=LEVEL]]]',
882+ 'Get/set ds scheduler parameters.'),
883 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
884 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
885 'trigger' : ('<Domain> <nmi|reset|init|s3resume|power> [<VCPU>]',
886@@ -277,6 +280,13 @@
887 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
888 ('-c CAP', '--cap=CAP', 'Cap (int)'),
889 ),
890+ # added by Sisu Xi
891+ 'sched-rt': (
892+ ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
893+ ('-b BUDGET', '--budget=BUDGET', 'Budget (int)'),
894+ ('-p PERIOD', '--period=PERIOD', 'Period (int)'),
895+ ('-l LEVEL', '--level =LEVEL', 'Level (int)'),
896+ ),
897 'list': (
898 ('-l', '--long', 'Output all VM details in SXP'),
899 ('', '--label', 'Include security labels'),
900@@ -420,6 +430,8 @@
901 scheduler_commands = [
902 "sched-credit",
903 "sched-sedf",
904+ # added by Sisu Xi
905+ "sched-rt",
906 ]
907
908 device_commands = [
909@@ -1740,6 +1752,105 @@
910 if result != 0:
911 err(str(result))
912
913+# added by Sisu Xi
914+def xm_sched_rt(args):
915+ """Get/Set options for RT Scheduler."""
916+
917+ check_sched_type('rt')
918+
919+ try:
920+ opts, params = getopt.getopt(args, "d:b:p:l:",
921+ ["domain=", "budget=", "period=", "level="])
922+ except getopt.GetoptError, opterr:
923+ err(opterr)
924+ usage('sched-rt')
925+
926+ domid = None
927+ budget = None
928+ period = None
929+ level = None
930+
931+ for o, a in opts:
932+ if o in ["-d", "--domain"]:
933+ domid = a
934+ elif o in ["-b", "--budget"]:
935+ budget = int(a)
936+ elif o in ["-p", "--period"]:
937+ period = int(a);
938+ elif o in ["-l", "--level"]:
939+ level = int(a);
940+
941+ doms = filter(lambda x : domid_match(domid, x),
942+ [parse_doms_info(dom)
943+ for dom in getDomains(None, 'all')])
944+
945+ if budget is None and period is None and level is None:
946+ if domid is not None and doms == []:
947+ err("Domain '%s' does not exist." % domid)
948+ usage('sched-rt')
949+ # print header if we aren't setting any parameters
950+ print '%-33s %4s %6s %4s %4s' % ('Name','ID','Budget','Period', 'Level')
951+
952+ for d in doms:
953+ try:
954+ if serverType == SERVER_XEN_API:
955+ info = server.xenapi.VM_metrics.get_VCPUs_params(
956+ server.xenapi.VM.get_metrics(
957+ get_single_vm(d['name'])))
958+ else:
959+ info = server.xend.domain.sched_rt_get(d['name'])
960+ except xmlrpclib.Fault:
961+ pass
962+
963+ if 'budget' not in info or 'period' not in info or 'level' not in info:
964+ # domain does not support sched-rt?
965+ info = {'budget': -1, 'period': -1, 'level': -1}
966+
967+ info['budget'] = int(info['budget'])
968+ info['period'] = int(info['period'])
969+ info['level'] = int(info['level'])
970+
971+ info['name'] = d['name']
972+ info['domid'] = str(d['domid'])
973+ print( ("%(name)-32s %(domid)5s %(budget)6d %(period)6d %(level)6d") % info)
974+ else:
975+ if domid is None:
976+ # place holder for system-wide scheduler parameters
977+ err("No domain given.")
978+ usage('sched-rt')
979+
980+ if serverType == SERVER_XEN_API:
981+ if doms[0]['domid']:
982+ server.xenapi.VM.add_to_VCPUs_params_live(
983+ get_single_vm(domid),
984+ "budget",
985+ budget)
986+ server.xenapi.VM.add_to_VCPUs_params_live(
987+ get_single_vm(domid),
988+ "period",
989+ period)
990+ server.xenapi.VM.add_to_VCPUs_params_live(
991+ get_single_vm(domid),
992+ "level",
993+ level)
994+ else:
995+ server.xenapi.VM.add_to_VCPUs_params(
996+ get_single_vm(domid),
997+ "budget",
998+ budget)
999+ server.xenapi.VM.add_to_VCPUs_params(
1000+ get_single_vm(domid),
1001+ "period",
1002+ period)
1003+ server.xenapi.VM.add_to_VCPUs_params(
1004+ get_single_vm(domid),
1005+ "level",
1006+ level)
1007+ else:
1008+ result = server.xend.domain.sched_rt_set(domid, budget, period, level)
1009+ if result != 0:
1010+ err(str(result))
1011+
1012 def xm_info(args):
1013 arg_check(args, "info", 0, 1)
1014
1015@@ -3492,6 +3603,8 @@
1016 # scheduler
1017 "sched-sedf": xm_sched_sedf,
1018 "sched-credit": xm_sched_credit,
1019+ # added by Sisu Xi
1020+ "sched-rt": xm_sched_rt,
1021 # block
1022 "block-attach": xm_block_attach,
1023 "block-detach": xm_block_detach,
1024diff -ubrN xen/xen-4.0.1/xen/arch/ia64/xen/domain.c xen-4.0.1/xen/arch/ia64/xen/domain.c
1025--- xen/xen-4.0.1/xen/arch/ia64/xen/domain.c 2010-08-25 04:22:11.000000000 -0600
1026+++ xen-4.0.1/xen/arch/ia64/xen/domain.c 2011-01-18 01:03:45.000000000 -0700
1027@@ -228,7 +228,7 @@
1028 flush_vtlb_for_context_switch(prev, current);
1029 }
1030
1031-void context_switch(struct vcpu *prev, struct vcpu *next)
1032+void context_switch(int flag, struct vcpu *prev, struct vcpu *next)
1033 {
1034 uint64_t spsr;
1035
1036@@ -307,6 +307,9 @@
1037
1038 flush_vtlb_for_context_switch(prev, current);
1039 flush_cache_for_context_switch(current);
1040+ if (flag == 1) {
1041+ printk("%13lu ia64\n", NOW());
1042+ }
1043 context_saved(prev);
1044 }
1045
1046diff -ubrN xen/xen-4.0.1/xen/arch/x86/domain.c xen-4.0.1/xen/arch/x86/domain.c
1047--- xen/xen-4.0.1/xen/arch/x86/domain.c 2010-08-25 04:22:11.000000000 -0600
1048+++ xen-4.0.1/xen/arch/x86/domain.c 2011-01-18 01:13:02.000000000 -0700
1049@@ -1421,7 +1421,7 @@
1050 }
1051
1052
1053-void context_switch(struct vcpu *prev, struct vcpu *next)
1054+void context_switch(int flag, struct vcpu *prev, struct vcpu *next)
1055 {
1056 unsigned int cpu = smp_processor_id();
1057 cpumask_t dirty_mask = next->vcpu_dirty_cpumask;
1058@@ -1482,6 +1482,10 @@
1059 if (prev != next)
1060 update_runstate_area(next);
1061
1062+ if (flag == 1) {
1063+ printk("%13lu\n", NOW());
1064+ }
1065+
1066 schedule_tail(next);
1067 BUG();
1068 }
1069diff -ubrN xen/xen-4.0.1/xen/common/Makefile xen-4.0.1/xen/common/Makefile
1070--- xen/xen-4.0.1/xen/common/Makefile 2010-08-25 04:22:12.000000000 -0600
1071+++ xen-4.0.1/xen/common/Makefile 2011-04-25 14:44:37.000000000 -0600
1072@@ -14,6 +14,11 @@
1073 obj-y += rangeset.o
1074 obj-y += sched_credit.o
1075 obj-y += sched_sedf.o
1076+obj-y += sched_rt_wcps.o
1077+obj-y += sched_rt_periodic.o
1078+obj-y += sched_rt_ssps.o
1079+obj-y += sched_rt.o
1080+obj-y += sched_rt_deferrable.o
1081 obj-y += schedule.o
1082 obj-y += shutdown.o
1083 obj-y += softirq.o
1084diff -ubrN xen/xen-4.0.1/xen/common/sched_credit.c xen-4.0.1/xen/common/sched_credit.c
1085--- xen/xen-4.0.1/xen/common/sched_credit.c 2010-08-25 04:22:12.000000000 -0600
1086+++ xen-4.0.1/xen/common/sched_credit.c 2011-04-09 22:29:29.000000000 -0600
1087@@ -710,6 +710,9 @@
1088 sdom->cap = op->u.credit.cap;
1089
1090 spin_unlock_irqrestore(&csched_priv.lock, flags);
1091+ if ( d->domain_id == 0) {
1092+ return 1;
1093+ }
1094 }
1095
1096 return 0;
1097diff -ubrN xen/xen-4.0.1/xen/common/sched_ds_ecrts11.c xen-4.0.1/xen/common/sched_ds_ecrts11.c
1098--- xen/xen-4.0.1/xen/common/sched_ds_ecrts11.c 1969-12-31 17:00:00.000000000 -0700
1099+++ xen-4.0.1/xen/common/sched_ds_ecrts11.c 2011-01-22 13:05:56.000000000 -0700
1100@@ -0,0 +1,927 @@
1101+/******************************************************************************
1102+ * Periodic / Polling / Deferrable Server scheduler for xen
1103+ *
1104+ * by Sisu Xi (C) 2010 Washington University in St. Louis
1105+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
1106+ ******************************************************************************/
1107+
1108+#include <xen/config.h>
1109+#include <xen/init.h>
1110+#include <xen/lib.h>
1111+#include <xen/sched.h>
1112+#include <xen/domain.h>
1113+#include <xen/delay.h>
1114+#include <xen/event.h>
1115+#include <xen/time.h>
1116+#include <xen/perfc.h>
1117+#include <xen/sched-if.h>
1118+#include <xen/softirq.h>
1119+#include <asm/atomic.h>
1120+#include <xen/errno.h>
1121+#include <xen/keyhandler.h>
1122+
1123+#define DS_DOM(_dom) ((struct ds_dom *) (_dom)->sched_priv)
1124+#define DS_PCPU(_c) ((struct ds_pcpu *)per_cpu(schedule_data, _c).sched_priv)
1125+#define DS_VCPU(_vcpu) ((struct ds_vcpu *) (_vcpu)->sched_priv)
1126+#define RUNQ(_cpu) (&(DS_PCPU(_cpu)->runq))
1127+#define RDYQ(_cpu) (&(DS_PCPU(_cpu)->rdyq))
1128+#define DS_CUR(_cpu) DS_VCPU(per_cpu(schedule_data, _cpu).curr)
1129+#define BUDGET(_b) (MILLISECS(_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
1130+
1131+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
1132+
1133+#define DS_DOM_0_PERIOD 100
1134+#define DS_IDLE_PERIOD 200
1135+
1136+#define DS_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
1137+#define DS_DOM_PERIOD 50
1138+
1139+//used for replenishment
1140+struct rep_elem {
1141+ s_time_t re_time;
1142+ struct ds_vcpu *dvc;
1143+};
1144+
1145+//physical cpu
1146+struct ds_pcpu {
1147+ struct list_head runq; // runQ on the pcpu, organized by linked list
1148+ struct list_head rdyq;
1149+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
1150+ int rep_size; // current size, for later dynamic reqQ use. currently set equals to capacity
1151+ int rep_capacity; // upper limit
1152+ struct timer ticker; // for preemptive use, tick every budget
1153+};
1154+
1155+//virtual cpu
1156+struct ds_vcpu {
1157+ struct list_head runq_elem;
1158+ struct list_head rdyq_elem;
1159+ struct ds_dom *ddom;
1160+ struct vcpu *vcpu;
1161+
1162+ uint16_t budget;
1163+ uint16_t period;
1164+ uint16_t level;
1165+
1166+ uint16_t cur_budget;
1167+ s_time_t last_start_time; // used for burn_budget
1168+ int flag;
1169+};
1170+
1171+//domain
1172+struct ds_dom {
1173+ struct domain *dom;
1174+ uint16_t budget;
1175+ uint16_t period;
1176+ uint16_t level;
1177+};
1178+
1179+//global variable, records the number of cpus
1180+struct ds_private {
1181+ spinlock_t lock; // used for init
1182+ uint32_t ncpus; //number of physical cpus
1183+ int polling; // polling server or deferrable server?
1184+ int periodic;
1185+};
1186+static struct ds_private ds_priv;
1187+/*
1188+//used for record, overhead measurement
1189+#define RECORD 11000 // record 10s
1190+struct record_elem{
1191+ s_time_t dur;
1192+
1193+ int curr;
1194+ int next;
1195+ s_time_t enter; // enter schedule time
1196+ s_time_t leave; // leave schedule time
1197+
1198+};
1199+*/
1200+struct timer ds_start_timer; // would start after 10s, used only once
1201+int ds_start_flag = 0; // start to record or not
1202+int ds_wake = 0;
1203+/*
1204+int ds_idx = 0; //ds_idx to record
1205+int ds_idx_tick = 0;
1206+int ds_wake = 0;
1207+int ds_sleep = 0;
1208+struct record_elem ds_res[RECORD]; // domain_id, time in ms;
1209+struct record_elem ds_res_tick[RECORD];
1210+//finish for the record
1211+*/
1212+static void ds_tick(void *_cpu);
1213+
1214+//dump the repq
1215+static void
1216+ds_dump_repq(int cpu) {
1217+ int loop = 0;
1218+ struct ds_pcpu *ppc = DS_PCPU(cpu);
1219+
1220+ printk("\n# into %s on cpu %d, now is %lu, size: %d, the repQ is :\n", __func__, cpu, NOW(), ppc->rep_size);
1221+ for (loop = 0; loop < ppc->rep_size; loop++) {
1222+ printk("\t[%d. %d]: %d @ %lu\n",
1223+ ppc->repq[loop].dvc->vcpu->domain->domain_id,
1224+ ppc->repq[loop].dvc->vcpu->vcpu_id,
1225+ ppc->repq[loop].dvc->period,
1226+ ppc->repq[loop].re_time);
1227+ }
1228+}
1229+
1230+//dump the virtual cpu
1231+static void
1232+ds_dump_vcpu(struct ds_vcpu *dvc) {
1233+ printk("\t[%i, %i], (%i, %i), cpu: %i, cur_budget: %i, level: %d\n",
1234+ dvc->vcpu->domain->domain_id, dvc->vcpu->vcpu_id, dvc->budget, dvc->period, dvc->vcpu->processor,
1235+ dvc->cur_budget, dvc->level);
1236+}
1237+
1238+//inlined code
1239+static inline struct ds_vcpu *
1240+__runq_elem(struct list_head *elem) {
1241+ return list_entry(elem, struct ds_vcpu, runq_elem);
1242+}
1243+
1244+//inlined code
1245+static inline struct ds_vcpu *
1246+__rdyq_elem(struct list_head *elem) {
1247+ return list_entry(elem, struct ds_vcpu, rdyq_elem);
1248+}
1249+
1250+//dump the physical cpu
1251+static void
1252+ds_dump_pcpu(int cpu) {
1253+ struct list_head *iter;
1254+ struct ds_pcpu *ppc = DS_PCPU(cpu);
1255+ struct list_head *runq = &ppc->runq;
1256+ struct list_head *rdyq = &ppc->rdyq;
1257+ struct ds_vcpu *dvc = DS_CUR(cpu);
1258+ int loop = 0;
1259+
1260+ printk("\n# into %s, on cpu: %d, now is: %lu\n", __func__, cpu, NOW());
1261+
1262+ if (dvc) {
1263+ printk("\trun: ");
1264+ ds_dump_vcpu(dvc);
1265+ }
1266+
1267+ printk("runq:\n");
1268+ list_for_each(iter, runq) {
1269+ dvc = __runq_elem(iter);
1270+ if (dvc) {
1271+ printk("\t%3d: ", ++loop);
1272+ ds_dump_vcpu(dvc);
1273+ }
1274+ }
1275+
1276+ printk("rdyq:\n");
1277+ list_for_each(iter, rdyq) {
1278+ dvc = __rdyq_elem(iter);
1279+ if (dvc) {
1280+ printk("\t%3d: ", ++loop);
1281+ ds_dump_vcpu(dvc);
1282+ }
1283+ }
1284+
1285+
1286+ ds_dump_repq(cpu);
1287+}
1288+/*
1289+//dump the record out.
1290+static void
1291+ds_dump_record(void) {
1292+ int i;
1293+
1294+ ds_start_flag = 0;
1295+
1296+ printk("For Schedule Function\n");
1297+
1298+ for (i = 1; i < ds_idx; i++) {
1299+ printk("%13lu\n", ds_res[i].dur);
1300+ }
1301+
1302+ printk("\n\nFor tick function\n");
1303+ for (i = 1; i < ds_idx_tick; i++) {
1304+ printk("%13lu\n", ds_res_tick[i].dur);
1305+ }
1306+
1307+ for (i = 0; i < RECORD; i++) {
1308+ ds_res[i].dur = 0;
1309+ ds_res_tick[i].dur = 0;
1310+ }
1311+
1312+ ds_wake = 0;
1313+ ds_sleep = 0;
1314+ ds_idx_tick = 0;
1315+ ds_idx = 0;
1316+}
1317+*/
1318+// the current vcpu is on runQ?
1319+static inline int
1320+__vcpu_on_runq(struct ds_vcpu *dvc) {
1321+ return !list_empty(&dvc->runq_elem);
1322+}
1323+
1324+// the current vcpu is on runQ?
1325+static inline int
1326+__vcpu_on_rdyq(struct ds_vcpu *dvc) {
1327+ return !list_empty(&dvc->rdyq_elem);
1328+}
1329+
1330+//pick the first vcpu whose budget is >0 from the runq
1331+static inline struct ds_vcpu *
1332+__runq_pick(unsigned int cpu) {
1333+ struct list_head * runq = RUNQ(cpu);
1334+ struct list_head * iter;
1335+
1336+ list_for_each(iter, runq) {
1337+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
1338+ if (iter_dvc->cur_budget > 0) {
1339+ return iter_dvc;
1340+ }
1341+ }
1342+
1343+ BUG_ON(1);
1344+ return NULL;
1345+}
1346+
1347+//insert into the runq, followed a FIFO way. sorted by period
1348+static inline void
1349+__runq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
1350+ struct list_head * runq = RUNQ(cpu);
1351+ struct list_head * iter;
1352+
1353+ BUG_ON(__vcpu_on_runq(dvc));
1354+ BUG_ON(cpu != dvc->vcpu->processor);
1355+
1356+ list_for_each(iter, runq) {
1357+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
1358+ if (dvc->level <= iter_dvc->level) {
1359+ break;
1360+ }
1361+ }
1362+
1363+ list_add_tail(&dvc->runq_elem, iter);
1364+}
1365+
1366+//insert into the runq, followed a FIFO way. sorted by period
1367+static inline void
1368+__rdyq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
1369+ struct list_head * rdyq = RDYQ(cpu);
1370+ struct list_head * iter;
1371+
1372+ BUG_ON(__vcpu_on_rdyq(dvc));
1373+ BUG_ON(cpu != dvc->vcpu->processor);
1374+
1375+ list_for_each(iter, rdyq) {
1376+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
1377+ if (dvc->level <= iter_dvc->level) {
1378+ break;
1379+ }
1380+ }
1381+
1382+ list_add_tail(&dvc->rdyq_elem, iter);
1383+}
1384+
1385+//remove it from runQ
1386+static inline void
1387+__runq_remove(struct ds_vcpu *dvc) {
1388+ BUG_ON(!__vcpu_on_runq(dvc));
1389+ list_del_init(&dvc->runq_elem);
1390+}
1391+
1392+//remove it from runQ
1393+static inline void
1394+__rdyq_remove(struct ds_vcpu *dvc) {
1395+ BUG_ON(!__vcpu_on_rdyq(dvc));
1396+ list_del_init(&dvc->rdyq_elem);
1397+}
1398+
1399+//used for the heap, repQ
1400+static inline int
1401+ds_rep_parent(int childIdx) {
1402+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
1403+}
1404+
1405+//insert into the repQ
1406+static inline void
1407+ds_repq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
1408+ struct ds_pcpu * ppc = DS_PCPU(cpu);
1409+ int childIdx, parentIdx;
1410+
1411+ if (ppc->rep_size == ppc->rep_capacity) {
1412+ printk("\n# into %s, repQ full!!\n", __func__);
1413+ BUG_ON(1);
1414+ }
1415+
1416+ childIdx = ppc->rep_size;
1417+ parentIdx = ds_rep_parent(childIdx);
1418+
1419+ while (childIdx > 0 && (NOW() + dvc->period*BUDGET(1)) < ppc->repq[parentIdx].re_time) {
1420+ ppc->repq[childIdx] = ppc->repq[parentIdx];
1421+ childIdx = parentIdx;
1422+ parentIdx = ds_rep_parent(childIdx);
1423+ }
1424+
1425+ ppc->repq[childIdx].re_time = NOW() + dvc->period*BUDGET(1);
1426+ ppc->repq[childIdx].dvc = dvc;
1427+ ppc->rep_size++;
1428+/*
1429+ printk("\t add a repl. now: %lu, cpu: %d, re_time: %lu, amount: %d, for cpu [%d, %d]\n",
1430+ NOW(), cpu, dvc->next_time, amount, dvc->vcpu->domain->domain_id, dvc->vcpu->vcpu_id);
1431+ ds_dump_vcpu(dvc);
1432+*/
1433+}
1434+
1435+//remove from the repQ
1436+static inline void
1437+ds_repq_remove(unsigned int cpu) {
1438+ struct ds_pcpu * ppc = DS_PCPU(cpu);
1439+ int childIdx = 1;
1440+ int rightChildIdx;
1441+ int rootIdx = 0;
1442+ struct rep_elem temp;
1443+
1444+ BUG_ON(ppc->rep_size <= 0);
1445+
1446+ ppc->repq[0] = ppc->repq[ppc->rep_size - 1];
1447+ ppc->rep_size--;
1448+
1449+ temp = ppc->repq[0];
1450+
1451+ while (childIdx < ppc->rep_size) {
1452+ rightChildIdx = childIdx + 1;
1453+ if (rightChildIdx < ppc->rep_size && ppc->repq[rightChildIdx].re_time < ppc->repq[childIdx].re_time) {
1454+ childIdx = rightChildIdx;
1455+ }
1456+ if (ppc->repq[childIdx].re_time < temp.re_time) {
1457+ ppc->repq[rootIdx] = ppc->repq[childIdx];
1458+ rootIdx = childIdx;
1459+ childIdx = 2 * rootIdx + 1;
1460+ } else {
1461+ break;
1462+ }
1463+ }
1464+ ppc->repq[rootIdx] = temp;
1465+}
1466+
1467+//dump dump function
1468+static void
1469+ds_dump(void) {
1470+ printk("# into %s. Did Nothing\n", __func__);
1471+}
1472+
1473+//burn the scurr budget
1474+static void
1475+burn_budgets(struct ds_vcpu *dvc, s_time_t now) {
1476+ s_time_t delta;
1477+ unsigned int consume;
1478+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
1479+ struct list_head * iter;
1480+
1481+ BUG_ON(dvc != DS_CUR(dvc->vcpu->processor));
1482+
1483+ if (dvc->last_start_time == 0) {
1484+ dvc->last_start_time = now;
1485+ return;
1486+ }
1487+
1488+ delta = now - dvc->last_start_time;
1489+ BUG_ON(delta <= 0);
1490+
1491+ consume = ( delta/BUDGET(1) );
1492+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
1493+ if (consume > dvc->cur_budget) {
1494+ //printk("\n# into %s, consumed more than cur budget!\n", __func__);
1495+ consume = dvc->cur_budget;
1496+ }
1497+
1498+ dvc->cur_budget -= consume;
1499+
1500+ if (ds_priv.periodic == 1) {
1501+ list_for_each(iter, rdyq) {
1502+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
1503+ //rdyQ has higher priority
1504+ if (dvc->level > iter_dvc->level) {
1505+ iter_dvc->cur_budget -= consume;
1506+ if (iter_dvc->cur_budget < 0) {
1507+ iter_dvc->cur_budget = 0;
1508+ }
1509+ }
1510+ }
1511+ }
1512+}
1513+
1514+//init the physical cpu
1515+static int
1516+ds_pcpu_init(int cpu) {
1517+ struct ds_pcpu *ppc;
1518+ unsigned long flags;
1519+
1520+ /* Allocate per-PCPU info */
1521+ ppc = xmalloc(struct ds_pcpu);
1522+ if (ppc == NULL)
1523+ return -1;
1524+ memset(ppc, 0, sizeof (*ppc));
1525+
1526+ spin_lock_irqsave(&ds_priv.lock, flags);
1527+
1528+ if (ds_priv.ncpus < cpu)
1529+ ds_priv.ncpus = cpu + 1;
1530+
1531+ init_timer(&ppc->ticker, ds_tick, (void *) (unsigned long) cpu, cpu);
1532+ INIT_LIST_HEAD(&ppc->runq);
1533+ INIT_LIST_HEAD(&ppc->rdyq);
1534+ per_cpu(schedule_data, cpu).sched_priv = ppc;
1535+
1536+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
1537+
1538+ ppc->rep_capacity = REPQ_CAPACITY;
1539+ ppc->repq = xmalloc_array(struct rep_elem, ppc->rep_capacity);
1540+ BUG_ON(ppc->repq == NULL);
1541+ ppc->rep_size = 0;
1542+
1543+ spin_unlock_irqrestore(&ds_priv.lock, flags);
1544+
1545+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
1546+
1547+ return 0;
1548+}
1549+
1550+//check the vcpu
1551+static inline void
1552+__ds_vcpu_check(struct vcpu *vc) {
1553+ struct ds_vcpu * const dvc = DS_VCPU(vc);
1554+ struct ds_dom * const ddom = dvc->ddom;
1555+
1556+ BUG_ON(dvc->vcpu != vc);
1557+ BUG_ON(ddom != DS_DOM(vc->domain));
1558+ if (ddom) {
1559+ BUG_ON(is_idle_vcpu(vc));
1560+ BUG_ON(ddom->dom != vc->domain);
1561+ } else {
1562+ BUG_ON(!is_idle_vcpu(vc));
1563+ }
1564+}
1565+#define DS_VCPU_CHECK(_vc) (__ds_vcpu_check(_vc))
1566+
1567+//pick a cpu to run, used to migrate from different cpus
1568+static int
1569+ds_cpu_pick(struct vcpu *vc) {
1570+ cpumask_t cpus;
1571+ int cpu;
1572+
1573+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
1574+
1575+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
1576+ return cycle_cpu(vc->processor, cpus);
1577+ }
1578+
1579+ cpu = cpu_isset(vc->processor, cpus)
1580+ ? vc->processor
1581+ : cycle_cpu(vc->processor, cpus);
1582+
1583+ return cpu;
1584+}
1585+
1586+//check the current repQ to see if a repl needs to happen
1587+static int
1588+check_cpu_for_repl(int cpu) {
1589+ struct ds_pcpu * ppc = DS_PCPU(cpu);
1590+ int flag = 0; //used for interrupt
1591+
1592+ while((ppc->rep_size != 0) && ppc->repq[0].re_time < NOW()) {
1593+ ppc->repq[0].dvc->cur_budget = ppc->repq[0].dvc->budget;
1594+ if (flag == 0 && ppc->repq[0].dvc->level < DS_CUR(cpu)->level) {
1595+ flag = 1; // need interrupt
1596+ }
1597+ ds_repq_insert(ppc->repq[0].dvc->vcpu->processor, ppc->repq[0].dvc);
1598+ ds_repq_remove(cpu);
1599+ }
1600+
1601+ return flag;
1602+}
1603+
1604+//init the virtual cpu
1605+static int
1606+ds_vcpu_init(struct vcpu *vc) {
1607+ struct domain * const dom = vc->domain;
1608+ struct ds_dom *ddom = DS_DOM(dom);
1609+ struct ds_vcpu *dvc;
1610+
1611+ /* Allocate per-VCPU info */
1612+ dvc = xmalloc(struct ds_vcpu);
1613+ if (dvc == NULL) {
1614+ return -1;
1615+ }
1616+ memset(dvc, 0, sizeof (*dvc));
1617+
1618+ INIT_LIST_HEAD(&dvc->runq_elem);
1619+ INIT_LIST_HEAD(&dvc->rdyq_elem);
1620+ dvc->ddom = ddom;
1621+ dvc->vcpu = vc;
1622+ dvc->budget = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->budget;
1623+ dvc->period = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->period;
1624+ dvc->level = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->level;
1625+ dvc->cur_budget = dvc->budget;
1626+
1627+ dvc->last_start_time = 0;
1628+ dvc->flag = 0;
1629+ vc->sched_priv = dvc;
1630+
1631+ /* Allocate per-PCPU info */
1632+ if (unlikely(!DS_PCPU(vc->processor))) {
1633+ if (ds_pcpu_init(vc->processor) != 0)
1634+ return -1;
1635+ }
1636+
1637+ DS_VCPU_CHECK(vc);
1638+
1639+ printk("\n# into %s, vcpu init: ", __func__);
1640+ ds_dump_vcpu(dvc);
1641+
1642+ return 0;
1643+}
1644+
1645+//destory the vcpu
1646+static void
1647+ds_vcpu_destroy(struct vcpu *vc) {
1648+ struct ds_vcpu * const dvc = DS_VCPU(vc);
1649+ struct ds_dom * const ddom = dvc->ddom;
1650+
1651+ printk("\n# into %s, vcpu destroy: ", __func__);
1652+ ds_dump_vcpu(dvc);
1653+
1654+ BUG_ON(ddom == NULL);
1655+ BUG_ON(!list_empty(&dvc->runq_elem));
1656+
1657+ xfree(dvc);
1658+}
1659+
1660+//sleep the vcpu
1661+static void
1662+ds_vcpu_sleep(struct vcpu *vc) {
1663+ struct ds_vcpu * const dvc = DS_VCPU(vc);
1664+
1665+ BUG_ON(is_idle_vcpu(vc));
1666+
1667+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
1668+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
1669+ } else if (__vcpu_on_runq(dvc)) {
1670+ //polling server
1671+ if (ds_priv.polling == 1) {
1672+ dvc->cur_budget = 0;
1673+ }
1674+ __runq_remove(dvc);
1675+ } else if (__vcpu_on_rdyq(dvc)) {
1676+ __rdyq_remove(dvc);
1677+ }
1678+}
1679+
1680+//wake up the vcpu, insert it into runq, raise a softirq
1681+static void
1682+ds_vcpu_wake(struct vcpu *vc) {
1683+ struct ds_vcpu * const dvc = DS_VCPU(vc);
1684+ const unsigned int cpu = vc->processor;
1685+
1686+ BUG_ON(is_idle_vcpu(vc));
1687+
1688+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
1689+ //printk("\n# why wake up running? migration?\n");
1690+ return;
1691+ }
1692+ if (unlikely(__vcpu_on_runq(dvc))) {
1693+ //printk("\n# why wake up on runq ones? migration?\n");
1694+ return;
1695+ }
1696+
1697+/*
1698+ if (smp_processor_id() == 1) {
1699+ printk("%s, domain %d, now %lu\n", __func__, vc->domain->domain_id, NOW()/1000000);
1700+ }
1701+*/
1702+
1703+ if (__vcpu_on_rdyq(dvc)) {
1704+ __rdyq_remove(dvc);
1705+ }
1706+
1707+ __runq_insert(cpu, dvc);
1708+ if (dvc->level < DS_CUR(cpu)->level) {
1709+ if (ds_start_flag == 1 && dvc->vcpu->processor == 1) {
1710+ ds_wake++;
1711+ }
1712+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
1713+ }
1714+}
1715+
1716+static void
1717+ds_ds_finish_timer(void * temp) {
1718+ ds_start_flag = 0;
1719+ printk("wake up %d times\n", ds_wake);
1720+ ds_wake = 0;
1721+}
1722+
1723+//used for record data, for overhead measurement
1724+static void
1725+ds_ds_start_timer(void * temp) {
1726+ ds_start_flag = 1;
1727+ init_timer(&ds_start_timer, ds_ds_finish_timer, (void *) (unsigned int) 1, 1);
1728+ set_timer(&ds_start_timer, NOW() + MILLISECS(10000));
1729+}
1730+
1731+//adjust the domain's budget & period, also used to trigger the record
1732+static int
1733+ds_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
1734+ struct ds_dom * const ddom = DS_DOM(d);
1735+ unsigned long flags;
1736+ struct ds_vcpu *dvc = DS_VCPU(d->vcpu[0]);
1737+
1738+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
1739+ op->u.ds.budget = ddom->budget;
1740+ op->u.ds.period = ddom->period;
1741+ op->u.ds.level = ddom->level;
1742+ //ds_dump_vcpu(dvc);
1743+ } else {
1744+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
1745+
1746+ spin_lock_irqsave(&ds_priv.lock, flags);
1747+ if (op->u.ds.budget != 0) {
1748+ ddom->budget = op->u.ds.budget;
1749+ dvc->budget = op->u.ds.budget;
1750+ }
1751+ if (op->u.ds.period != 0) {
1752+ ddom->period = op->u.ds.period;
1753+ dvc->period = op->u.ds.period;
1754+ }
1755+ if (op->u.ds.level != 0) {
1756+ ddom->level = op->u.ds.level;
1757+ dvc->level = op->u.ds.level;
1758+ }
1759+ dvc->cur_budget = dvc->budget;
1760+ spin_unlock_irqrestore(&ds_priv.lock, flags);
1761+
1762+ if (dvc->vcpu->domain->domain_id == 0) {
1763+ if (op->u.ds.budget == 100) {
1764+ if (ds_priv.polling == 0) {
1765+ ds_priv.polling = 1;
1766+ printk("running with the polling server!\n");
1767+ } else if (ds_priv.polling == 1) {
1768+ ds_priv.polling = 0;
1769+ printk("running with the deferrable server!\n");
1770+ }
1771+ } else if (op->u.ds.budget == 200) {
1772+ if (ds_priv.periodic == 0) {
1773+ ds_priv.periodic = 1;
1774+ ds_priv.polling = 0;
1775+ printk("running with the periodic server!\n");
1776+ } else if (ds_priv.periodic == 1) {
1777+ ds_priv.periodic = 0;
1778+ if (ds_priv.polling == 1) {
1779+ printk("running with the polling server!\n");
1780+ } else if (ds_priv.polling == 0) {
1781+ printk("running with the deferrable server!\n");
1782+ }
1783+ }
1784+ } else if (op->u.ds.budget == 300) {
1785+ init_timer(&ds_start_timer, ds_ds_start_timer, (void *) (unsigned int) 1, 1);
1786+ set_timer(&ds_start_timer, NOW() + MILLISECS(5000));
1787+ return 1;
1788+ }
1789+ }
1790+ }
1791+
1792+ return 0;
1793+}
1794+
1795+//init a dom
1796+static int
1797+ds_dom_init(struct domain *dom) {
1798+ struct ds_dom *ddom;
1799+
1800+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
1801+
1802+ if (is_idle_domain(dom)) {
1803+ printk("\t# init an idle domain\n");
1804+ return 0;
1805+ }
1806+
1807+ ddom = xmalloc(struct ds_dom);
1808+ if (ddom == NULL)
1809+ return -ENOMEM;
1810+ memset(ddom, 0, sizeof (*ddom));
1811+
1812+ /* Initialize budget and period */
1813+ ddom->dom = dom;
1814+
1815+ switch(dom->domain_id) {
1816+ case 32767:
1817+ ddom->budget = DS_IDLE_PERIOD;
1818+ ddom->period = DS_IDLE_PERIOD;
1819+ ddom->level = DS_IDLE_PERIOD;
1820+ break;
1821+ case 0:
1822+ ddom->budget = DS_DOM_0_PERIOD;
1823+ ddom->period = DS_DOM_0_PERIOD;
1824+ ddom->level = 1;
1825+ break;
1826+ default:
1827+ ddom->budget = DS_DOM_BUDGET;
1828+ ddom->period = DS_DOM_PERIOD;
1829+ ddom->level = 10;
1830+ break;
1831+ }
1832+
1833+ dom->sched_priv = ddom;
1834+
1835+ return 0;
1836+}
1837+
1838+//destory a domain
1839+static void
1840+ds_dom_destroy(struct domain *dom) {
1841+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
1842+ xfree(DS_DOM(dom));
1843+}
1844+
1845+//ticked by pcpu tick in pcpu.
1846+static void
1847+ds_tick(void *_cpu) {
1848+ unsigned int cpu = (unsigned long) _cpu;
1849+ struct ds_pcpu *ppc = DS_PCPU(cpu);
1850+/*
1851+ if (smp_processor_id() == 1 && ds_start_flag == 1) {
1852+ ds_res_tick[ds_idx_tick].enter = NOW();
1853+ }
1854+*/
1855+ BUG_ON(current->processor != cpu);
1856+
1857+ if (check_cpu_for_repl(cpu)) {
1858+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
1859+ }
1860+
1861+ if (ds_cpu_pick(current) != cpu) {
1862+ set_bit(_VPF_migrating, &current->pause_flags);
1863+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
1864+ }
1865+
1866+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
1867+/*
1868+ if (smp_processor_id() == 1 && ds_start_flag == 1) {
1869+ ds_res_tick[ds_idx_tick].leave = NOW();
1870+ if (ds_idx_tick++ >= RECORD) {
1871+ printk("tick full!\n");
1872+ ds_dump_record();
1873+ }
1874+ }
1875+ */
1876+}
1877+
1878+// most important function, called every budget time
1879+static struct task_slice
1880+ds_schedule(s_time_t now) {
1881+ const int cpu = smp_processor_id();
1882+ struct list_head *runq = RUNQ(cpu);
1883+ struct ds_vcpu *scurr = DS_VCPU(current);
1884+ struct ds_vcpu *snext;
1885+ struct task_slice ret;
1886+
1887+ DS_VCPU_CHECK(current);
1888+/*
1889+// for record
1890+ if (smp_processor_id() == 1 && ds_start_flag == 1) {
1891+ if(is_idle_vcpu(scurr->vcpu)) ds_res[ds_idx].curr = 10;
1892+ else ds_res[ds_idx].curr = scurr->vcpu->domain->domain_id;
1893+ ds_res[ds_idx].enter = NOW();
1894+ }
1895+*/
1896+ if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
1897+ //if (!is_idle_vcpu(scurr->vcpu)) {
1898+ burn_budgets(scurr, now);
1899+ if (scurr->flag == 0) {
1900+ scurr->flag = 1;
1901+ ds_repq_insert(scurr->vcpu->processor, scurr);
1902+ }
1903+ }
1904+
1905+ if (vcpu_runnable(current)) {
1906+ __runq_insert(cpu, scurr);
1907+ } else {
1908+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
1909+ // for the polling server
1910+ if (cpu == 1 && scurr->vcpu->domain->domain_id != 0 && ds_priv.polling == 1) {
1911+ scurr->cur_budget = 0;
1912+ }
1913+ __rdyq_insert(cpu, scurr);
1914+ }
1915+
1916+ snext = __runq_pick(cpu);
1917+
1918+ __runq_remove(snext);
1919+
1920+ if (cpu == 1 && snext->vcpu->domain->domain_id != 0) {
1921+ snext->last_start_time = NOW();
1922+ }
1923+
1924+ ret.time = (is_idle_vcpu(snext->vcpu) ? -1 : BUDGET(1));
1925+
1926+ //ret.time = BUDGET(1);
1927+ ret.task = snext->vcpu;
1928+
1929+ DS_VCPU_CHECK(ret.task);
1930+
1931+ BUG_ON(!vcpu_runnable(snext->vcpu));
1932+ //printk("now is %lu\n", now);
1933+/*
1934+// for record
1935+ if (smp_processor_id() == 1 && ds_start_flag == 1) {
1936+ if(is_idle_vcpu(snext->vcpu)) ds_res[ds_idx].next = 10;
1937+ else ds_res[ds_idx].next = snext->vcpu->domain->domain_id;
1938+ ds_res[ds_idx].leave = NOW();
1939+ if(ds_idx++ >= RECORD) {
1940+ printk("full!!\n");
1941+ ds_dump_record();
1942+ }
1943+ }
1944+ */
1945+
1946+ return ret;
1947+}
1948+
1949+//init the global data
1950+static void
1951+ds_init(void) {
1952+ printk("\n# into %s\n", __func__);
1953+ spin_lock_init(&ds_priv.lock);
1954+ ds_priv.ncpus = 0;
1955+ ds_priv.polling = 0;
1956+ ds_priv.periodic = 0;
1957+}
1958+
1959+/* Tickers cannot be kicked until SMP subsystem is alive. */
1960+static __init int
1961+ds_start_tickers(void) {
1962+ struct ds_pcpu *ppc;
1963+ unsigned int cpu;
1964+
1965+ printk("\n# into %s, start all tickers right now\n", __func__);
1966+
1967+ if (ds_priv.ncpus == 0)
1968+ return 0;
1969+
1970+ for_each_online_cpu(cpu) {
1971+ ppc = DS_PCPU(cpu);
1972+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
1973+ }
1974+
1975+ return 0;
1976+}
1977+__initcall(ds_start_tickers);
1978+
1979+static void ds_tick_suspend(void) {
1980+ struct ds_pcpu *ppc;
1981+
1982+ printk("\n# into %s, why is this called?\n", __func__);
1983+
1984+ ppc = DS_PCPU(smp_processor_id());
1985+
1986+ stop_timer(&ppc->ticker);
1987+}
1988+
1989+static void ds_tick_resume(void) {
1990+ struct ds_pcpu *ppc;
1991+ uint64_t now = NOW();
1992+
1993+ printk("\n# into %s, why is this called?\n", __func__);
1994+
1995+ ppc = DS_PCPU(smp_processor_id());
1996+
1997+ set_timer(&ppc->ticker, now + BUDGET(1));
1998+}
1999+
2000+const struct scheduler sched_ds_def = {
2001+ .name = "Deferrable Server Scheduler",
2002+ .opt_name = "ds",
2003+ .sched_id = XEN_SCHEDULER_DS,
2004+
2005+ .init_domain = ds_dom_init,
2006+ .destroy_domain = ds_dom_destroy,
2007+
2008+ .init_vcpu = ds_vcpu_init,
2009+ .destroy_vcpu = ds_vcpu_destroy,
2010+
2011+ .init = ds_init,
2012+
2013+ .pick_cpu = ds_cpu_pick,
2014+
2015+ .tick_suspend = ds_tick_suspend,
2016+ .tick_resume = ds_tick_resume,
2017+
2018+ .do_schedule = ds_schedule,
2019+
2020+ .sleep = ds_vcpu_sleep,
2021+ .wake = ds_vcpu_wake,
2022+
2023+ .adjust = ds_dom_cntl,
2024+
2025+ .dump_cpu_state = ds_dump_pcpu,
2026+ .dump_settings = ds_dump,
2027+};
2028diff -ubrN xen/xen-4.0.1/xen/common/sched_ds_emsoft11.c xen-4.0.1/xen/common/sched_ds_emsoft11.c
2029--- xen/xen-4.0.1/xen/common/sched_ds_emsoft11.c 1969-12-31 17:00:00.000000000 -0700
2030+++ xen-4.0.1/xen/common/sched_ds_emsoft11.c 2011-04-10 11:56:00.000000000 -0600
2031@@ -0,0 +1,1136 @@
2032+/******************************************************************************
2033+ * Periodic / Polling / Deferrable Server scheduler for xen
2034+ *
2035+ * by Sisu Xi (C) 2010 Washington University in St. Louis
2036+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
2037+ ******************************************************************************/
2038+
2039+#include <xen/config.h>
2040+#include <xen/init.h>
2041+#include <xen/lib.h>
2042+#include <xen/sched.h>
2043+#include <xen/domain.h>
2044+#include <xen/delay.h>
2045+#include <xen/event.h>
2046+#include <xen/time.h>
2047+#include <xen/perfc.h>
2048+#include <xen/sched-if.h>
2049+#include <xen/softirq.h>
2050+#include <asm/atomic.h>
2051+#include <xen/errno.h>
2052+#include <xen/keyhandler.h>
2053+
2054+#define DS_DOM(_dom) ((struct ds_dom *) (_dom)->sched_priv)
2055+#define DS_PCPU(_c) ((struct ds_pcpu *)per_cpu(schedule_data, _c).sched_priv)
2056+#define DS_VCPU(_vcpu) ((struct ds_vcpu *) (_vcpu)->sched_priv)
2057+#define RUNQ(_cpu) (&(DS_PCPU(_cpu)->runq))
2058+#define RDYQ(_cpu) (&(DS_PCPU(_cpu)->rdyq))
2059+#define DS_CUR(_cpu) DS_VCPU(per_cpu(schedule_data, _cpu).curr)
2060+#define BUDGET(_b) (MILLISECS(10*_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
2061+
2062+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
2063+
2064+#define DS_DOM_0_PERIOD 100
2065+#define DS_IDLE_PERIOD 200
2066+
2067+#define DS_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
2068+#define DS_DOM_PERIOD 50
2069+
2070+//PES is the Simple PES, CS is the standard PES
2071+enum server_type {DS, POS, PES, CS, SS};
2072+
2073+//physical cpu
2074+struct ds_pcpu {
2075+ struct list_head runq; // runQ on the pcpu, organized by linked list
2076+ struct list_head rdyq;
2077+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
2078+ int rep_size; // current size, for later dynamic reqQ use. currently set equals to capacity
2079+ int rep_capacity; // upper limit
2080+ struct timer ticker; // for preemptive use, tick every budget
2081+};
2082+
2083+//virtual cpu
2084+struct ds_vcpu {
2085+ struct list_head runq_elem;
2086+ struct list_head rdyq_elem;
2087+ struct list_head active_elem; //used to link all active vcpu except domain 0 and idle one!
2088+ struct ds_dom *ddom;
2089+ struct vcpu *vcpu;
2090+
2091+ uint16_t repq_pending; // used to calculate how many items are on repq
2092+
2093+ uint16_t budget;
2094+ uint16_t period;
2095+ uint16_t level;
2096+
2097+ uint16_t cur_budget;
2098+ s_time_t last_start_time; // used for burn_budget
2099+ s_time_t next_time; //the next repl time
2100+
2101+ int flag; // represent whether the vCPU has started or not
2102+
2103+ uint16_t burn_total; // used only for Sporadic Server
2104+};
2105+
2106+//used for replenishment
2107+struct rep_elem {
2108+ s_time_t re_time;
2109+ int16_t re_amount;
2110+ struct ds_vcpu *dvc;
2111+};
2112+
2113+//domain
2114+struct ds_dom {
2115+ struct domain *dom;
2116+ uint16_t budget;
2117+ uint16_t period;
2118+ uint16_t level;
2119+};
2120+
2121+//global variable, records the number of cpus
2122+struct ds_private {
2123+ spinlock_t lock; // used for init
2124+ uint32_t ncpus; //number of physical cpus
2125+ enum server_type type; // used for different type of servers
2126+ struct list_head active; //active_vcpu except domain 0 and idle vcpu!
2127+};
2128+static struct ds_private ds_priv;
2129+
2130+static void ds_tick(void *_cpu);
2131+
2132+//dump the repq
2133+static void
2134+ds_dump_repq(int cpu) {
2135+ int loop = 0;
2136+ struct ds_pcpu *ppc = DS_PCPU(cpu);
2137+
2138+ printk("repq: size: %d\n", ppc->rep_size);
2139+ for (loop = 0; loop < ppc->rep_size; loop++) {
2140+ printk("\t[%d, %d]: %d @ %lu\n",
2141+ ppc->repq[loop].dvc->vcpu->domain->domain_id,
2142+ ppc->repq[loop].dvc->vcpu->vcpu_id,
2143+ ppc->repq[loop].re_amount,
2144+ ppc->repq[loop].re_time);
2145+ }
2146+}
2147+
2148+//dump the virtual cpu
2149+static void
2150+ds_dump_vcpu(struct ds_vcpu *dvc) {
2151+ printk("\t[%i, %i], cur: %i, rep: %d, last: %lu, next: %lu, \n", dvc->vcpu->domain->domain_id, dvc->vcpu->vcpu_id, dvc->cur_budget, dvc->repq_pending, dvc->last_start_time, dvc->next_time);
2152+}
2153+
2154+//inlined code
2155+static inline struct ds_vcpu *
2156+__runq_elem(struct list_head *elem) {
2157+ return list_entry(elem, struct ds_vcpu, runq_elem);
2158+}
2159+
2160+//inlined code
2161+static inline struct ds_vcpu *
2162+__rdyq_elem(struct list_head *elem) {
2163+ return list_entry(elem, struct ds_vcpu, rdyq_elem);
2164+}
2165+
2166+//dump the physical cpu
2167+static void
2168+ds_dump_pcpu(int cpu) {
2169+ struct list_head *iter;
2170+ struct ds_pcpu *ppc = DS_PCPU(cpu);
2171+ struct list_head *runq = &ppc->runq;
2172+ struct list_head *rdyq = &ppc->rdyq;
2173+ struct ds_vcpu *dvc = DS_CUR(cpu);
2174+ int loop = 0;
2175+
2176+ printk("### cpu: %d, now is: %lu\n", cpu, NOW());
2177+
2178+ if (dvc) {
2179+ printk("\trun: ");
2180+ ds_dump_vcpu(dvc);
2181+ }
2182+
2183+ printk("runq:\n");
2184+ list_for_each(iter, runq) {
2185+ dvc = __runq_elem(iter);
2186+ if (dvc) {
2187+ printk("\t%3d: ", ++loop);
2188+ ds_dump_vcpu(dvc);
2189+ }
2190+ }
2191+
2192+ printk("rdyq:\n");
2193+ list_for_each(iter, rdyq) {
2194+ dvc = __rdyq_elem(iter);
2195+ if (dvc) {
2196+ printk("\t%3d: ", ++loop);
2197+ ds_dump_vcpu(dvc);
2198+ }
2199+ }
2200+
2201+ ds_dump_repq(cpu);
2202+ printk("\n");
2203+}
2204+
2205+// the current vcpu is on runQ?
2206+static inline int
2207+__vcpu_on_runq(struct ds_vcpu *dvc) {
2208+ return !list_empty(&dvc->runq_elem);
2209+}
2210+
2211+// the current vcpu is on runQ?
2212+static inline int
2213+__vcpu_on_rdyq(struct ds_vcpu *dvc) {
2214+ return !list_empty(&dvc->rdyq_elem);
2215+}
2216+
2217+//pick the first vcpu whose budget is >0 from the runq
2218+static inline struct ds_vcpu *
2219+__runq_pick(unsigned int cpu) {
2220+ struct list_head * runq = RUNQ(cpu);
2221+ struct list_head * iter;
2222+
2223+ list_for_each(iter, runq) {
2224+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
2225+ if (iter_dvc->cur_budget > 0) {
2226+ return iter_dvc;
2227+ }
2228+ }
2229+
2230+ BUG_ON(1);
2231+ return NULL;
2232+}
2233+
2234+//pick the first one with budget > 0, regardless of runnable or not
2235+static inline struct ds_vcpu *
2236+__rdyq_pick(unsigned int cpu) {
2237+ struct list_head * rdyq = RDYQ(cpu);
2238+ struct list_head * iter;
2239+
2240+ list_for_each(iter, rdyq) {
2241+ struct ds_vcpu *iter_dvc = __rdyq_elem(iter);
2242+ if (iter_dvc->cur_budget > 0) {
2243+ return iter_dvc;
2244+ }
2245+ }
2246+
2247+ return NULL;
2248+}
2249+
2250+static inline struct ds_vcpu *
2251+__runq_pick_idle(unsigned int cpu) {
2252+ struct list_head * runq = RUNQ(cpu);
2253+ struct list_head * iter;
2254+
2255+ list_for_each(iter, runq) {
2256+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
2257+ if (is_idle_vcpu(iter_dvc->vcpu)) {
2258+ return iter_dvc;
2259+ }
2260+ }
2261+
2262+ BUG_ON(1);
2263+ return NULL;
2264+}
2265+
2266+//insert into the runq, followed a FIFO way. sorted by level
2267+static inline void
2268+__runq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
2269+ struct list_head * runq = RUNQ(cpu);
2270+ struct list_head * iter;
2271+
2272+ BUG_ON(__vcpu_on_runq(dvc));
2273+ BUG_ON(cpu != dvc->vcpu->processor);
2274+
2275+ list_for_each(iter, runq) {
2276+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
2277+ if (dvc->level < iter_dvc->level) {
2278+ break;
2279+ }
2280+ }
2281+
2282+ list_add_tail(&dvc->runq_elem, iter);
2283+}
2284+
2285+//insert into the runq, followed a FIFO way. sorted by level
2286+static inline void
2287+__rdyq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
2288+ struct list_head * rdyq = RDYQ(cpu);
2289+ struct list_head * iter;
2290+
2291+ BUG_ON(__vcpu_on_rdyq(dvc));
2292+ BUG_ON(cpu != dvc->vcpu->processor);
2293+
2294+ list_for_each(iter, rdyq) {
2295+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2296+ if (dvc->level <= iter_dvc->level) {
2297+ break;
2298+ }
2299+ }
2300+
2301+ list_add_tail(&dvc->rdyq_elem, iter);
2302+}
2303+
2304+//remove it from runQ
2305+static inline void
2306+__runq_remove(struct ds_vcpu *dvc) {
2307+ BUG_ON(!__vcpu_on_runq(dvc));
2308+ list_del_init(&dvc->runq_elem);
2309+}
2310+
2311+//remove it from runQ
2312+static inline void
2313+__rdyq_remove(struct ds_vcpu *dvc) {
2314+ BUG_ON(!__vcpu_on_rdyq(dvc));
2315+ list_del_init(&dvc->rdyq_elem);
2316+}
2317+
2318+//used for the heap, repQ
2319+static inline int
2320+ds_rep_parent(int childIdx) {
2321+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
2322+}
2323+
2324+//insert into the repQ
2325+static inline void
2326+ds_repq_insert(unsigned int cpu, struct ds_vcpu *dvc, int amount) {
2327+ struct ds_pcpu * ppc = DS_PCPU(cpu);
2328+ int childIdx, parentIdx;
2329+
2330+ if (dvc->next_time == 0) {
2331+ printk("\n# in %s, ERROR! dvc is:", __func__);
2332+ ds_dump_vcpu(dvc);
2333+ ds_dump_pcpu(cpu);
2334+ dvc->next_time = NOW() + BUDGET(1) * dvc->period;
2335+ }
2336+
2337+ if (amount == 0) {
2338+ return;
2339+ }
2340+
2341+ if (ppc->rep_size == ppc->rep_capacity) {
2342+ printk("\n# into %s, repQ full!!\n", __func__);
2343+ BUG_ON(1);
2344+ }
2345+
2346+ childIdx = ppc->rep_size;
2347+ parentIdx = ds_rep_parent(childIdx);
2348+
2349+ while (childIdx > 0 && dvc->next_time < ppc->repq[parentIdx].re_time) {
2350+ ppc->repq[childIdx] = ppc->repq[parentIdx];
2351+ childIdx = parentIdx;
2352+ parentIdx = ds_rep_parent(childIdx);
2353+ }
2354+
2355+ ppc->repq[childIdx].re_time = dvc->next_time;
2356+ ppc->repq[childIdx].dvc = dvc;
2357+ ppc->repq[childIdx].re_amount = amount;
2358+ ppc->rep_size++;
2359+
2360+ // dvc->next_time = 0;
2361+ dvc->repq_pending++;
2362+}
2363+
2364+//remove from the repQ
2365+static inline void
2366+ds_repq_remove(unsigned int cpu) {
2367+ struct ds_pcpu * ppc = DS_PCPU(cpu);
2368+ int childIdx = 1;
2369+ int rightChildIdx;
2370+ int rootIdx = 0;
2371+ struct rep_elem temp;
2372+
2373+ BUG_ON(ppc->rep_size <= 0);
2374+
2375+ ppc->repq[0].dvc->repq_pending--;
2376+ ppc->repq[0] = ppc->repq[ppc->rep_size - 1];
2377+ ppc->rep_size--;
2378+
2379+ temp = ppc->repq[0];
2380+
2381+ while (childIdx < ppc->rep_size) {
2382+ rightChildIdx = childIdx + 1;
2383+ if (rightChildIdx < ppc->rep_size && ppc->repq[rightChildIdx].re_time < ppc->repq[childIdx].re_time) {
2384+ childIdx = rightChildIdx;
2385+ }
2386+ if (ppc->repq[childIdx].re_time < temp.re_time) {
2387+ ppc->repq[rootIdx] = ppc->repq[childIdx];
2388+ rootIdx = childIdx;
2389+ childIdx = 2 * rootIdx + 1;
2390+ } else {
2391+ break;
2392+ }
2393+ }
2394+ ppc->repq[rootIdx] = temp;
2395+}
2396+
2397+//dump dump function
2398+static void
2399+ds_dump(void) {
2400+ printk("# into %s. Did Nothing\n", __func__);
2401+}
2402+
2403+//burn the scurr budget
2404+//dom != 0 && !is_idle_vcpu(dvc)
2405+static void
2406+burn_budgets(struct ds_vcpu *dvc, s_time_t now) {
2407+ s_time_t delta;
2408+ unsigned int consume;
2409+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
2410+ struct list_head * iter;
2411+
2412+ BUG_ON(dvc != DS_CUR(dvc->vcpu->processor));
2413+
2414+ if (dvc->last_start_time == 0) {
2415+ dvc->last_start_time = now;
2416+ printk("\nset last_start_time to 0 in %s\n", __func__);
2417+ return;
2418+ }
2419+
2420+ delta = now - dvc->last_start_time;
2421+ BUG_ON(delta <= 0);
2422+
2423+ consume = ( delta/BUDGET(1) );
2424+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
2425+
2426+ dvc->cur_budget -= consume;
2427+ if (dvc->cur_budget < 0) dvc->cur_budget = 0;
2428+
2429+ if(ds_priv.type == SS) {
2430+ dvc->burn_total += consume;
2431+ }
2432+
2433+ // printk("\n\t%d @ burn\n", consume);
2434+//used for simple PES, to burn all the VCPU's budget who has higher priority
2435+ if (ds_priv.type == PES) {
2436+ list_for_each(iter, rdyq) {
2437+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2438+ //rdyQ has higher priority
2439+ if (dvc->level > iter_dvc->level && iter_dvc->cur_budget > 0) {
2440+ iter_dvc->cur_budget -= consume;
2441+ if (iter_dvc->cur_budget < 0) {
2442+ iter_dvc->cur_budget = 0;
2443+ }
2444+ break; // the enhanced old periodic server
2445+ }
2446+ }
2447+ }
2448+}
2449+
2450+//used for PES and CS, the dvc is the IDLE VCPU
2451+//domain != 0, is_idle_vcpu(dvc)
2452+static void
2453+burn_extra(struct ds_vcpu *dvc, s_time_t now) {
2454+ s_time_t delta;
2455+ unsigned int consume;
2456+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
2457+ struct list_head * iter;
2458+
2459+ BUG_ON(dvc != DS_CUR(dvc->vcpu->processor));
2460+
2461+ if (dvc->last_start_time == 0) {
2462+ dvc->last_start_time = now;
2463+ return;
2464+ }
2465+
2466+ if (ds_priv.type == DS || ds_priv.type == POS || ds_priv.type == SS) {
2467+ return;
2468+ }
2469+
2470+ delta = now - dvc->last_start_time;
2471+ BUG_ON(delta <= 0);
2472+
2473+ consume = ( delta/BUDGET(1) );
2474+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
2475+
2476+ if (ds_priv.type == PES) {
2477+ list_for_each(iter, rdyq) {
2478+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2479+ //rdyQ has higher priority
2480+ if (iter_dvc->cur_budget > 0) {
2481+ iter_dvc->cur_budget -= consume;
2482+ if (iter_dvc->cur_budget < 0) {
2483+ iter_dvc->cur_budget = 0;
2484+ }
2485+ break; // the enhanced old periodic server
2486+ }
2487+ }
2488+ } else { // now for the CS, need to consume the budget of the first element on rdyq
2489+ list_for_each(iter, rdyq) {
2490+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2491+ //rdyQ has higher priority
2492+ if (iter_dvc->cur_budget > 0) {
2493+ iter_dvc->cur_budget -= consume;
2494+ if (iter_dvc->cur_budget < 0) {
2495+ iter_dvc->cur_budget = 0;
2496+ }
2497+ break;
2498+ }
2499+ }// if no one runs, also check the rdyQ, and then returns
2500+ }
2501+}
2502+
2503+//init the physical cpu
2504+static int
2505+ds_pcpu_init(int cpu) {
2506+ struct ds_pcpu *ppc;
2507+ unsigned long flags;
2508+
2509+ /* Allocate per-PCPU info */
2510+ ppc = xmalloc(struct ds_pcpu);
2511+ if (ppc == NULL)
2512+ return -1;
2513+ memset(ppc, 0, sizeof (*ppc));
2514+
2515+ spin_lock_irqsave(&ds_priv.lock, flags);
2516+
2517+ if (ds_priv.ncpus < cpu)
2518+ ds_priv.ncpus = cpu + 1;
2519+
2520+ init_timer(&ppc->ticker, ds_tick, (void *) (unsigned long) cpu, cpu);
2521+ INIT_LIST_HEAD(&ppc->runq);
2522+ INIT_LIST_HEAD(&ppc->rdyq);
2523+ per_cpu(schedule_data, cpu).sched_priv = ppc;
2524+
2525+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
2526+
2527+ ppc->rep_capacity = REPQ_CAPACITY;
2528+ ppc->repq = xmalloc_array(struct rep_elem, ppc->rep_capacity);
2529+ BUG_ON(ppc->repq == NULL);
2530+ ppc->rep_size = 0;
2531+
2532+ spin_unlock_irqrestore(&ds_priv.lock, flags);
2533+
2534+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
2535+
2536+ return 0;
2537+}
2538+
2539+//check the vcpu
2540+static inline void
2541+__ds_vcpu_check(struct vcpu *vc) {
2542+ struct ds_vcpu * const dvc = DS_VCPU(vc);
2543+ struct ds_dom * const ddom = dvc->ddom;
2544+
2545+ BUG_ON(dvc->vcpu != vc);
2546+ BUG_ON(ddom != DS_DOM(vc->domain));
2547+ if (ddom) {
2548+ BUG_ON(is_idle_vcpu(vc));
2549+ BUG_ON(ddom->dom != vc->domain);
2550+ } else {
2551+ BUG_ON(!is_idle_vcpu(vc));
2552+ }
2553+}
2554+#define DS_VCPU_CHECK(_vc) (__ds_vcpu_check(_vc))
2555+
2556+//pick a cpu to run, used to migrate from different cpus
2557+static int
2558+ds_cpu_pick(struct vcpu *vc) {
2559+ cpumask_t cpus;
2560+ int cpu;
2561+
2562+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
2563+
2564+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
2565+ return cycle_cpu(vc->processor, cpus);
2566+ }
2567+
2568+ cpu = cpu_isset(vc->processor, cpus)
2569+ ? vc->processor
2570+ : cycle_cpu(vc->processor, cpus);
2571+
2572+ return cpu;
2573+}
2574+
2575+//for PES or CS, when the
2576+//check the current repQ to see if a repl needs to happen
2577+static int
2578+check_cpu_for_repl(int cpu) {
2579+ struct ds_pcpu * ppc = DS_PCPU(cpu);
2580+ int flag = 0; //used for interrupt
2581+ struct list_head * rdyq = RDYQ(cpu);
2582+ struct list_head * iter;
2583+
2584+ while((ppc->rep_size != 0) && ppc->repq[0].re_time < NOW()) {
2585+ ppc->repq[0].dvc->cur_budget += ppc->repq[0].re_amount;
2586+ if (ppc->repq[0].dvc->cur_budget > ppc->repq[0].dvc->budget) {
2587+ ppc->repq[0].dvc->cur_budget = ppc->repq[0].dvc->budget;
2588+ }
2589+
2590+ if (ds_priv.type != SS) { // insert next repl
2591+ ppc->repq[0].dvc->next_time = NOW() + BUDGET(1) * ppc->repq[0].dvc->period;
2592+ ds_repq_insert(ppc->repq[0].dvc->vcpu->processor, ppc->repq[0].dvc, ppc->repq[0].dvc->budget);
2593+ }
2594+
2595+ if (ds_priv.type != CS) {
2596+ if (ppc->repq[0].dvc->level < DS_CUR(cpu)->level) {
2597+ flag = 1;
2598+ } // raise interrupt
2599+ } else { // for the CS type
2600+ if (!is_idle_vcpu(current)) {
2601+ if (ppc->repq[0].dvc->level < DS_CUR(cpu)->level) {
2602+ flag = 1;
2603+ }
2604+ } else { // the idle VCPU
2605+ list_for_each(iter, rdyq) {
2606+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2607+ //rdyQ has higher priority
2608+ if (iter_dvc->cur_budget > 0) {
2609+ if (ppc->repq[0].dvc->level < iter_dvc->level) {
2610+ flag = 1; // higher priority
2611+ }
2612+ break;
2613+ }
2614+ }
2615+ }
2616+ }
2617+
2618+ ds_repq_remove(cpu);
2619+ }
2620+
2621+ return flag;
2622+}
2623+
2624+//init the virtual cpu
2625+static int
2626+ds_vcpu_init(struct vcpu *vc) {
2627+ struct domain * const dom = vc->domain;
2628+ struct ds_dom *ddom = DS_DOM(dom);
2629+ struct ds_vcpu *dvc;
2630+
2631+ /* Allocate per-VCPU info */
2632+ dvc = xmalloc(struct ds_vcpu);
2633+ if (dvc == NULL) {
2634+ return -1;
2635+ }
2636+ memset(dvc, 0, sizeof (*dvc));
2637+
2638+ INIT_LIST_HEAD(&dvc->runq_elem);
2639+ INIT_LIST_HEAD(&dvc->rdyq_elem);
2640+ INIT_LIST_HEAD(&dvc->active_elem); // init for active list
2641+ dvc->ddom = ddom;
2642+ dvc->vcpu = vc;
2643+ dvc->budget = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->budget;
2644+ dvc->period = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->period;
2645+ dvc->level = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->level;
2646+ dvc->cur_budget = dvc->budget;
2647+ dvc->repq_pending = 0;
2648+
2649+ dvc->last_start_time = 0;
2650+ dvc->flag = 0;
2651+
2652+ dvc->burn_total = 0;
2653+ dvc->next_time = 0;
2654+
2655+ vc->sched_priv = dvc;
2656+
2657+ /* Allocate per-PCPU info */
2658+ if (unlikely(!DS_PCPU(vc->processor))) {
2659+ if (ds_pcpu_init(vc->processor) != 0)
2660+ return -1;
2661+ }
2662+
2663+ DS_VCPU_CHECK(vc);
2664+
2665+ printk("\n# into %s, vcpu init: ", __func__);
2666+ ds_dump_vcpu(dvc);
2667+
2668+ return 0;
2669+}
2670+
2671+//destory the vcpu
2672+static void
2673+ds_vcpu_destroy(struct vcpu *vc) {
2674+ struct ds_vcpu * const dvc = DS_VCPU(vc);
2675+ struct ds_dom * const ddom = dvc->ddom;
2676+
2677+ printk("\n# into %s, vcpu destroy: ", __func__);
2678+ ds_dump_vcpu(dvc);
2679+
2680+ BUG_ON(ddom == NULL);
2681+ BUG_ON(!list_empty(&dvc->runq_elem));
2682+ list_del_init(&dvc->active_elem);
2683+
2684+ xfree(dvc);
2685+}
2686+
2687+//sleep the vcpu
2688+static void
2689+ds_vcpu_sleep(struct vcpu *vc) {
2690+ struct ds_vcpu * const dvc = DS_VCPU(vc);
2691+
2692+ BUG_ON(is_idle_vcpu(vc));
2693+
2694+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
2695+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
2696+ } else if (__vcpu_on_runq(dvc)) {
2697+ //polling server
2698+ if (ds_priv.type == POS) {
2699+ dvc->cur_budget = 0;
2700+ }
2701+ __runq_remove(dvc);
2702+ } else if (__vcpu_on_rdyq(dvc)) {
2703+ __rdyq_remove(dvc);
2704+ }
2705+}
2706+
2707+//wake up the vcpu, insert it into runq, raise a softirq
2708+static void
2709+ds_vcpu_wake(struct vcpu *vc) {
2710+ struct ds_vcpu * const dvc = DS_VCPU(vc);
2711+ const unsigned int cpu = vc->processor;
2712+ struct list_head * rdyq = RDYQ(cpu);
2713+ struct list_head * iter;
2714+
2715+ BUG_ON(is_idle_vcpu(vc));
2716+
2717+ // if (vc->domain->domain_id != 0) {
2718+ // printk("wake vcpu: now %lu ", NOW());
2719+ // ds_dump_vcpu(dvc);
2720+ // }
2721+
2722+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
2723+ if (vc->domain->domain_id != 0) {
2724+ printk("\nrunning\n");
2725+ }
2726+ return;
2727+ }
2728+ if (unlikely(__vcpu_on_runq(dvc))) {
2729+ if (vc->domain->domain_id != 0) {
2730+ printk("\nrunq\n");
2731+ }
2732+ return;
2733+ }
2734+
2735+ if (__vcpu_on_rdyq(dvc)) {
2736+ __rdyq_remove(dvc);
2737+ }
2738+
2739+ if (!__vcpu_on_runq(dvc)) {
2740+ __runq_insert(cpu, dvc);
2741+ }
2742+
2743+ if (ds_priv.type != CS) {
2744+ if (dvc->level < DS_CUR(cpu)->level) {
2745+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2746+ return;
2747+ }
2748+ } else {
2749+ if (!is_idle_vcpu(current)) {
2750+ if (dvc->level < DS_CUR(cpu)->level) {
2751+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2752+ return;
2753+ }
2754+ } else {
2755+ list_for_each(iter, rdyq) {
2756+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2757+ //rdyQ has higher priority
2758+ if (iter_dvc->cur_budget > 0) {
2759+ if (dvc->level < iter_dvc->level) {
2760+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2761+ return;
2762+ }
2763+ break;
2764+ }
2765+ }
2766+ }
2767+ }
2768+
2769+ return;
2770+}
2771+
2772+static inline void
2773+ds_reset(int cpu) {
2774+ struct ds_pcpu * ppc = DS_PCPU(cpu);
2775+ struct list_head * iter;
2776+
2777+ printk("\nbefore reset\n");
2778+ ds_dump_pcpu(cpu);
2779+
2780+ // empty the RepQ
2781+ while(ppc->rep_size != 0) {
2782+ ds_repq_remove(cpu);
2783+ }
2784+
2785+ printk("\nvcpu on list is:\n");
2786+ //init each vcpu;
2787+ list_for_each(iter, &ds_priv.active) {
2788+ struct ds_vcpu * iter_dvc = list_entry(iter, struct ds_vcpu, active_elem);
2789+ if (__vcpu_on_runq(iter_dvc)) {
2790+ __runq_remove(iter_dvc);
2791+ }
2792+ if (__vcpu_on_rdyq(iter_dvc)) {
2793+ __rdyq_remove(iter_dvc);
2794+ }
2795+ iter_dvc->cur_budget = iter_dvc->budget;
2796+ iter_dvc->last_start_time = NOW();
2797+ iter_dvc->next_time = NOW() + BUDGET(1) * iter_dvc->period;
2798+ iter_dvc->burn_total = 0;
2799+ ds_dump_vcpu(iter_dvc);
2800+ }
2801+
2802+ printk("\nafter reset\n");
2803+ ds_dump_pcpu(cpu);
2804+
2805+ //insert into Queues
2806+ list_for_each(iter, &ds_priv.active) {
2807+ struct ds_vcpu * iter_dvc = list_entry(iter, struct ds_vcpu, active_elem);
2808+ if (vcpu_runnable(iter_dvc->vcpu)) {
2809+ if (!__vcpu_on_runq(iter_dvc)) {
2810+ __runq_insert(cpu, iter_dvc);
2811+ }
2812+ } else {
2813+ if (!__vcpu_on_rdyq(iter_dvc)) {
2814+ __rdyq_insert(cpu, iter_dvc);
2815+ }
2816+ }
2817+ if (ds_priv.type != SS) {
2818+ ds_repq_insert(iter_dvc->vcpu->processor, iter_dvc, iter_dvc->budget);
2819+ }
2820+ }
2821+
2822+ printk("\nafter insert\n");
2823+ ds_dump_pcpu(cpu);
2824+}
2825+
2826+//adjust the domain's budget & period, also used to trigger the record
2827+static int
2828+ds_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
2829+ struct ds_dom * const ddom = DS_DOM(d);
2830+ unsigned long flags;
2831+ struct ds_vcpu *dvc = DS_VCPU(d->vcpu[0]);
2832+ int flag = 0;
2833+
2834+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
2835+ op->u.ds.budget = ddom->budget;
2836+ op->u.ds.period = ddom->period;
2837+ op->u.ds.level = ddom->level;
2838+ //ds_dump_vcpu(dvc);
2839+ } else {
2840+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
2841+
2842+ spin_lock_irqsave(&ds_priv.lock, flags);
2843+ if (op->u.ds.budget != 0) {
2844+ ddom->budget = op->u.ds.budget;
2845+ dvc->budget = op->u.ds.budget;
2846+ }
2847+ if (op->u.ds.period != 0) {
2848+ ddom->period = op->u.ds.period;
2849+ dvc->period = op->u.ds.period;
2850+ }
2851+ if (op->u.ds.level != 0) {
2852+ ddom->level = op->u.ds.level;
2853+ dvc->level = op->u.ds.level;
2854+ }
2855+ dvc->cur_budget = dvc->budget;
2856+ spin_unlock_irqrestore(&ds_priv.lock, flags);
2857+
2858+ if (dvc->vcpu->domain->domain_id == 0) {
2859+ switch (op->u.ds.budget) {
2860+ case 100:
2861+ ds_priv.type = DS;
2862+ flag = 1;
2863+ break;
2864+ case 200:
2865+ ds_priv.type = CS;
2866+ flag = 1;
2867+ break;
2868+ case 300:
2869+ ds_priv.type = PES;
2870+ flag = 1;
2871+ break;
2872+ case 400:
2873+ ds_priv.type = POS;
2874+ flag = 1;
2875+ break;
2876+ case 500:
2877+ ds_priv.type = SS;
2878+ flag = 1;
2879+ break;
2880+ case 600:
2881+ return 1; // return to record the overhead!
2882+ break;
2883+ case 700:
2884+ ds_dump_pcpu(1);
2885+ break;
2886+ default:
2887+ printk("set budget of Domain-0 to : 100 (DS), 200 (CS), 300 (PES), 400 (POS), 500 (SS), 600 (record overhead), 700 (dump PCPU)\n");
2888+ break;
2889+ }
2890+ printk("Currently running with Scheduler ");
2891+ switch (ds_priv.type) {
2892+ case CS:
2893+ printk("CS\n");
2894+ break;
2895+ case POS:
2896+ printk("POS\n");
2897+ break;
2898+ case PES:
2899+ printk("PES\n");
2900+ break;
2901+ case DS:
2902+ printk("DS\n");
2903+ break;
2904+ case SS:
2905+ printk("SS\n");
2906+ break;
2907+ default:
2908+ printk("Wrong!!!\n");
2909+ break;
2910+ }
2911+ if (flag == 1) {
2912+ ds_reset(1);
2913+ cpu_raise_softirq(1, SCHEDULE_SOFTIRQ);
2914+ flag = 0;
2915+ }
2916+ }
2917+ }
2918+
2919+ return 0;
2920+}
2921+
2922+//init a dom
2923+static int
2924+ds_dom_init(struct domain *dom) {
2925+ struct ds_dom *ddom;
2926+
2927+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
2928+
2929+ if (is_idle_domain(dom)) {
2930+ printk("\t# init an idle domain\n");
2931+ return 0;
2932+ }
2933+
2934+ ddom = xmalloc(struct ds_dom);
2935+ if (ddom == NULL)
2936+ return -ENOMEM;
2937+ memset(ddom, 0, sizeof (*ddom));
2938+
2939+ /* Initialize budget and period */
2940+ ddom->dom = dom;
2941+
2942+ switch(dom->domain_id) {
2943+ case 32767:
2944+ ddom->budget = DS_IDLE_PERIOD;
2945+ ddom->period = DS_IDLE_PERIOD;
2946+ ddom->level = 100;
2947+ break;
2948+ case 0:
2949+ ddom->budget = DS_DOM_0_PERIOD;
2950+ ddom->period = DS_DOM_0_PERIOD;
2951+ ddom->level = 1;
2952+ break;
2953+ default:
2954+ ddom->budget = DS_DOM_BUDGET;
2955+ ddom->period = DS_DOM_PERIOD;
2956+ ddom->level = 10;
2957+ break;
2958+ }
2959+
2960+ dom->sched_priv = ddom;
2961+
2962+ return 0;
2963+}
2964+
2965+//destory a domain
2966+static void
2967+ds_dom_destroy(struct domain *dom) {
2968+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
2969+ xfree(DS_DOM(dom));
2970+}
2971+
2972+//ticked by pcpu tick in pcpu.
2973+static void
2974+ds_tick(void *_cpu) {
2975+ unsigned int cpu = (unsigned long) _cpu;
2976+ struct ds_pcpu *ppc = DS_PCPU(cpu);
2977+
2978+ BUG_ON(current->processor != cpu);
2979+
2980+ if (check_cpu_for_repl(cpu)) {
2981+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2982+ }
2983+
2984+ if (ds_cpu_pick(current) != cpu) {
2985+ set_bit(_VPF_migrating, &current->pause_flags);
2986+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2987+ }
2988+
2989+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
2990+}
2991+
2992+// most important function, called every budget time
2993+static struct task_slice
2994+ds_schedule(s_time_t now) {
2995+ const int cpu = smp_processor_id();
2996+ struct list_head *runq = RUNQ(cpu);
2997+ // struct list_head *rdyq = RDYQ(cpu);
2998+ struct ds_vcpu *scurr = DS_VCPU(current);
2999+ struct ds_vcpu *snext;
3000+ struct task_slice ret;
3001+
3002+ DS_VCPU_CHECK(current);
3003+
3004+// need to consider idle_vcpu for CS and PES
3005+ if (scurr->vcpu->domain->domain_id != 0) {
3006+ if (!is_idle_vcpu(scurr->vcpu)) {
3007+ // for the first time the VCPU is executed
3008+ if (scurr->flag == 0) {
3009+ scurr->flag = 1;
3010+ BUG_ON(!list_empty(&scurr->active_elem));
3011+ list_add(&scurr->active_elem, &ds_priv.active);
3012+ scurr->next_time = now + BUDGET(1) * scurr->period;
3013+ ds_repq_insert(scurr->vcpu->processor, scurr, scurr->budget);
3014+ }
3015+ if (cpu == 1) {
3016+ burn_budgets(scurr, now);
3017+ }
3018+ } else if (cpu == 1) { // scurr is the IDLE VCPU, have to deal with specially in CS and PES
3019+ burn_extra(scurr, now);
3020+ }
3021+ }
3022+
3023+ if (vcpu_runnable(current)) {
3024+ if (!__vcpu_on_runq(scurr)) {
3025+ __runq_insert(cpu, scurr);
3026+ }
3027+ } else {
3028+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
3029+ //for POS server
3030+ if (cpu == 1 && scurr->vcpu->domain->domain_id != 0 && ds_priv.type == POS) {
3031+ scurr->cur_budget = 0;
3032+ }
3033+ if (!__vcpu_on_rdyq(scurr)) {
3034+ __rdyq_insert(cpu, scurr);
3035+ }
3036+ }
3037+
3038+ if (cpu != 1) {
3039+ snext = __runq_pick(cpu);
3040+ } else if (ds_priv.type != CS) {
3041+ snext = __runq_pick(cpu);
3042+ } else { // now runs CS scheduler
3043+ // printk("\n\trdy empty? %d, run: %d, rdy: %d\n", list_empty(rdyq), __runq_pick(cpu)->level, __rdyq_pick(cpu)->level);
3044+ if ( __rdyq_pick(cpu) == NULL || (__runq_pick(cpu)->level < __rdyq_pick(cpu)->level) ) {
3045+ snext = __runq_pick(cpu); //we are fine here
3046+ // printk("\npicked %d\n", snext->vcpu->domain->domain_id);
3047+ } else {
3048+ // if ( __rdyq_pick(cpu) == NULL ) {
3049+ // printk("\n\t\trdyq is null\n");
3050+ // } else {
3051+ // printk("\n\t\trun: %d, rdy: %d\n", __runq_pick(cpu)->level, __rdyq_pick(cpu)->level);
3052+ // }
3053+ snext = __runq_pick_idle(cpu); // pick the IDLE VCPU for the VCPU on the RdyQ
3054+ // ds_dump_pcpu(1);
3055+ }
3056+ }
3057+
3058+ if (cpu == 1 && snext->vcpu->domain->domain_id != 0) {
3059+ snext->last_start_time = NOW();
3060+ }
3061+
3062+ BUG_ON(!__vcpu_on_runq(snext));
3063+ __runq_remove(snext);
3064+
3065+ //context switch happens
3066+ if (cpu == 1 && snext != scurr) {
3067+ if (ds_priv.type == SS) {
3068+ if (!is_idle_vcpu(snext->vcpu)) {
3069+ snext->next_time = now + BUDGET(1) * snext->period;
3070+ }
3071+ if (!is_idle_vcpu(scurr->vcpu)) {
3072+ ds_repq_insert(cpu, scurr, scurr->burn_total);
3073+ scurr->burn_total = 0;
3074+ }
3075+ }
3076+ }
3077+
3078+ // ret.time = is_idle_vcpu(snext->vcpu) ? BUDGET(1) : BUDGET(1) * snext->cur_budget;
3079+ ret.time = BUDGET(1); // used to test the enhanced old periodic server
3080+ ret.task = snext->vcpu;
3081+
3082+ DS_VCPU_CHECK(ret.task);
3083+
3084+ BUG_ON(!vcpu_runnable(snext->vcpu));
3085+
3086+ return ret;
3087+}
3088+
3089+//init the global data
3090+static void
3091+ds_init(void) {
3092+ printk("\n# into %s\n", __func__);
3093+ spin_lock_init(&ds_priv.lock);
3094+ ds_priv.ncpus = 0;
3095+ ds_priv.type = DS;
3096+ INIT_LIST_HEAD(&ds_priv.active);
3097+}
3098+
3099+/* Tickers cannot be kicked until SMP subsystem is alive. */
3100+static __init int
3101+ds_start_tickers(void) {
3102+ struct ds_pcpu *ppc;
3103+ unsigned int cpu;
3104+
3105+ printk("\n# into %s, start all tickers right now\n", __func__);
3106+
3107+ if (ds_priv.ncpus == 0)
3108+ return 0;
3109+
3110+ for_each_online_cpu(cpu) {
3111+ ppc = DS_PCPU(cpu);
3112+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
3113+ }
3114+
3115+ return 0;
3116+}
3117+__initcall(ds_start_tickers);
3118+
3119+static void ds_tick_suspend(void) {
3120+ struct ds_pcpu *ppc;
3121+
3122+ printk("\n# into %s, why is this called?\n", __func__);
3123+
3124+ ppc = DS_PCPU(smp_processor_id());
3125+
3126+ stop_timer(&ppc->ticker);
3127+}
3128+
3129+static void ds_tick_resume(void) {
3130+ struct ds_pcpu *ppc;
3131+ uint64_t now = NOW();
3132+
3133+ printk("\n# into %s, why is this called?\n", __func__);
3134+
3135+ ppc = DS_PCPU(smp_processor_id());
3136+
3137+ set_timer(&ppc->ticker, now + BUDGET(1));
3138+}
3139+
3140+const struct scheduler sched_ds_def = {
3141+ .name = "Deferrable Server Scheduler",
3142+ .opt_name = "ds",
3143+ .sched_id = XEN_SCHEDULER_DS,
3144+
3145+ .init_domain = ds_dom_init,
3146+ .destroy_domain = ds_dom_destroy,
3147+
3148+ .init_vcpu = ds_vcpu_init,
3149+ .destroy_vcpu = ds_vcpu_destroy,
3150+
3151+ .init = ds_init,
3152+
3153+ .pick_cpu = ds_cpu_pick,
3154+
3155+ .tick_suspend = ds_tick_suspend,
3156+ .tick_resume = ds_tick_resume,
3157+
3158+ .do_schedule = ds_schedule,
3159+
3160+ .sleep = ds_vcpu_sleep,
3161+ .wake = ds_vcpu_wake,
3162+
3163+ .adjust = ds_dom_cntl,
3164+
3165+ .dump_cpu_state = ds_dump_pcpu,
3166+ .dump_settings = ds_dump,
3167+};
3168diff -ubrN xen/xen-4.0.1/xen/common/sched_rt.c xen-4.0.1/xen/common/sched_rt.c
3169--- xen/xen-4.0.1/xen/common/sched_rt.c 1969-12-31 17:00:00.000000000 -0700
3170+++ xen-4.0.1/xen/common/sched_rt.c 2011-05-01 00:42:25.000000000 -0600
3171@@ -0,0 +1,584 @@
3172+/******************************************************************************
3173+ * Real Time Xen scheduler Framework
3174+ *
3175+ * by Sisu Xi (C) 2010 Washington University in St. Louis
3176+ * based on code by Jaewoo Lee (C) 2010 University of Pennsylvania
3177+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
3178+ ******************************************************************************/
3179+
3180+#include <xen/config.h>
3181+#include <xen/init.h>
3182+#include <xen/lib.h>
3183+#include <xen/sched.h>
3184+#include <xen/domain.h>
3185+#include <xen/delay.h>
3186+#include <xen/event.h>
3187+#include <xen/time.h>
3188+#include <xen/perfc.h>
3189+#include <xen/sched-if.h>
3190+#include <xen/softirq.h>
3191+#include <asm/atomic.h>
3192+#include <xen/errno.h>
3193+#include <xen/keyhandler.h>
3194+#include "sched_rt.h"
3195+
3196+extern const struct rt_scheduler sched_deferrable_def;
3197+extern const struct rt_scheduler sched_periodic_def;
3198+extern const struct rt_scheduler sched_wcps_def;
3199+extern const struct rt_scheduler sched_ssps_def;
3200+//extern const struct rt_scheduler sched_polling_def;
3201+//extern const struct rt_scheduler sched_sporadic_def;
3202+
3203+static struct rt_private rt_priv;
3204+
3205+static void rt_tick(void *_cpu);
3206+
3207+
3208+//init the global data, picking schedulers!
3209+static void
3210+rt_init(void) {
3211+ printk("\n# into %s\n", __func__);
3212+
3213+ spin_lock_init(&rt_priv.lock);
3214+ rt_priv.ncpus = 0;
3215+ rt_priv.type = DS;
3216+ INIT_LIST_HEAD(&rt_priv.active);
3217+}
3218+
3219+//dump the physical cpu
3220+static void
3221+rt_dump_pcpu(int cpu) {
3222+ struct list_head *iter;
3223+ struct rt_pcpu *ppc = RT_PCPU(cpu);
3224+ struct list_head *runq = &ppc->runq;
3225+ struct list_head *rdyq = &ppc->rdyq;
3226+ struct rt_vcpu *dvc = RT_CUR(cpu);
3227+ int loop = 0;
3228+
3229+ printk("### cpu: %d, now is: %lu\n", cpu, NOW());
3230+
3231+ if (dvc) {
3232+ printk("\trun: ");
3233+ rt_dump_vcpu(dvc);
3234+ }
3235+
3236+ printk("runq:\n");
3237+ list_for_each(iter, runq) {
3238+ dvc = __runq_elem(iter);
3239+ if (dvc) {
3240+ printk("\t%3d: ", ++loop);
3241+ rt_dump_vcpu(dvc);
3242+ }
3243+ }
3244+
3245+ printk("rdyq:\n");
3246+ list_for_each(iter, rdyq) {
3247+ dvc = __rdyq_elem(iter);
3248+ if (dvc) {
3249+ printk("\t%3d: ", ++loop);
3250+ rt_dump_vcpu(dvc);
3251+ }
3252+ }
3253+
3254+ rt_dump_repq(cpu);
3255+ printk("\n");
3256+}
3257+
3258+//dump dump function
3259+static void
3260+rt_dump(void) {
3261+ rt_dump_pcpu(1);
3262+}
3263+
3264+//init the physical cpu
3265+static int
3266+rt_pcpu_init(int cpu) {
3267+ struct rt_pcpu *ppc;
3268+ unsigned long flags;
3269+
3270+ /* Allocate per-PCPU info */
3271+ ppc = xmalloc(struct rt_pcpu);
3272+ if (ppc == NULL)
3273+ return -1;
3274+ memset(ppc, 0, sizeof (*ppc));
3275+
3276+ spin_lock_irqsave(&rt_priv.lock, flags);
3277+
3278+ if (rt_priv.ncpus < cpu)
3279+ rt_priv.ncpus = cpu + 1;
3280+
3281+ init_timer(&ppc->ticker, rt_tick, (void *) (unsigned long) cpu, cpu);
3282+ INIT_LIST_HEAD(&ppc->runq);
3283+ INIT_LIST_HEAD(&ppc->rdyq);
3284+ per_cpu(schedule_data, cpu).sched_priv = ppc;
3285+
3286+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
3287+
3288+ ppc->rep_capacity = REPQ_CAPACITY;
3289+ ppc->repq = xmalloc_array(struct rep_elem, ppc->rep_capacity);
3290+ BUG_ON(ppc->repq == NULL);
3291+ ppc->rep_size = 0;
3292+
3293+ spin_unlock_irqrestore(&rt_priv.lock, flags);
3294+
3295+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
3296+
3297+ return 0;
3298+}
3299+
3300+//pick a cpu to run, used to migrate from different cpus
3301+static int
3302+rt_cpu_pick(struct vcpu *vc) {
3303+ cpumask_t cpus;
3304+ int cpu;
3305+
3306+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
3307+
3308+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
3309+ return cycle_cpu(vc->processor, cpus);
3310+ }
3311+
3312+ cpu = cpu_isset(vc->processor, cpus)
3313+ ? vc->processor
3314+ : cycle_cpu(vc->processor, cpus);
3315+
3316+ return cpu;
3317+}
3318+
3319+//init the virtual cpu
3320+static int
3321+rt_vcpu_init(struct vcpu *vc) {
3322+ struct domain * const dom = vc->domain;
3323+ struct rt_dom *ddom = RT_DOM(dom);
3324+ struct rt_vcpu *dvc;
3325+
3326+ /* Allocate per-VCPU info */
3327+ dvc = xmalloc(struct rt_vcpu);
3328+ if (dvc == NULL) {
3329+ return -1;
3330+ }
3331+ memset(dvc, 0, sizeof (*dvc));
3332+
3333+ INIT_LIST_HEAD(&dvc->runq_elem);
3334+ INIT_LIST_HEAD(&dvc->rdyq_elem);
3335+ INIT_LIST_HEAD(&dvc->active_elem); // init for active list
3336+ dvc->ddom = ddom;
3337+ dvc->vcpu = vc;
3338+ dvc->budget = is_idle_vcpu(vc)? RT_IDLE_PERIOD: ddom->budget;
3339+ dvc->period = is_idle_vcpu(vc)? RT_IDLE_PERIOD: ddom->period;
3340+ dvc->level = is_idle_vcpu(vc)? RT_IDLE_PERIOD: ddom->level;
3341+ dvc->cur_budget = dvc->budget;
3342+ dvc->repq_pending = 0;
3343+
3344+ dvc->last_start_time = 0;
3345+
3346+ dvc->burn_total = 0;
3347+ dvc->next_time = 0;
3348+
3349+ vc->sched_priv = dvc;
3350+
3351+ /* Allocate per-PCPU info */
3352+ if (unlikely(!RT_PCPU(vc->processor))) {
3353+ if (rt_pcpu_init(vc->processor) != 0)
3354+ return -1;
3355+ }
3356+
3357+ RT_VCPU_CHECK(vc);
3358+
3359+ BUG_ON(!list_empty(&dvc->active_elem));
3360+ list_add(&dvc->active_elem, &rt_priv.active);
3361+ dvc->next_time = NOW() + BUDGET(1) * dvc->period;
3362+ rt_repq_insert(dvc->vcpu->processor, dvc, dvc->budget);
3363+
3364+ printk("\n# into %s, vcpu init: ", __func__);
3365+ rt_dump_vcpu(dvc);
3366+
3367+ return 0;
3368+}
3369+
3370+//destory the vcpu
3371+static void
3372+rt_vcpu_destroy(struct vcpu *vc) {
3373+ struct rt_vcpu * const dvc = RT_VCPU(vc);
3374+ struct rt_dom * const ddom = dvc->ddom;
3375+
3376+ printk("\n# into %s, vcpu destroy: ", __func__);
3377+ rt_dump_vcpu(dvc);
3378+
3379+ BUG_ON(ddom == NULL);
3380+ BUG_ON(!list_empty(&dvc->runq_elem));
3381+ list_del_init(&dvc->active_elem);
3382+
3383+ xfree(dvc);
3384+}
3385+
3386+//init a dom
3387+static int
3388+rt_dom_init(struct domain *dom) {
3389+ struct rt_dom *ddom;
3390+
3391+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
3392+
3393+ if (is_idle_domain(dom)) {
3394+ printk("\t# init an idle domain\n");
3395+ return 0;
3396+ }
3397+
3398+ ddom = xmalloc(struct rt_dom);
3399+ if (ddom == NULL)
3400+ return -ENOMEM;
3401+ memset(ddom, 0, sizeof (*ddom));
3402+
3403+ /* Initialize budget and period */
3404+ ddom->dom = dom;
3405+
3406+ switch(dom->domain_id) {
3407+ case 32767:
3408+ ddom->budget = RT_IDLE_PERIOD;
3409+ ddom->period = RT_IDLE_PERIOD;
3410+ ddom->level = 100;
3411+ break;
3412+ case 0:
3413+ ddom->budget = RT_DOM_0_PERIOD;
3414+ ddom->period = RT_DOM_0_PERIOD;
3415+ ddom->level = 1;
3416+ break;
3417+ default:
3418+ ddom->budget = RT_DOM_BUDGET;
3419+ ddom->period = RT_DOM_PERIOD;
3420+ ddom->level = 10;
3421+ break;
3422+ }
3423+
3424+ dom->sched_priv = ddom;
3425+
3426+ return 0;
3427+}
3428+
3429+//destory a domain
3430+static void
3431+rt_dom_destroy(struct domain *dom) {
3432+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
3433+ xfree(RT_DOM(dom));
3434+}
3435+
3436+/* Tickers cannot be kicked until SMP subsystem is alive. */
3437+static __init int
3438+rt_start_tickers(void) {
3439+ struct rt_pcpu *ppc;
3440+ unsigned int cpu;
3441+
3442+ printk("\n# into %s, start all tickers right now\n", __func__);
3443+
3444+ if (rt_priv.ncpus == 0)
3445+ return 0;
3446+
3447+ for_each_online_cpu(cpu) {
3448+ ppc = RT_PCPU(cpu);
3449+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
3450+ }
3451+
3452+ return 0;
3453+}
3454+__initcall(rt_start_tickers);
3455+
3456+static void rt_tick_suspend(void) {
3457+ struct rt_pcpu *ppc;
3458+
3459+ printk("\n# into %s, why is this called?\n", __func__);
3460+
3461+ ppc = RT_PCPU(smp_processor_id());
3462+
3463+ stop_timer(&ppc->ticker);
3464+}
3465+
3466+static void rt_tick_resume(void) {
3467+ struct rt_pcpu *ppc;
3468+ uint64_t now = NOW();
3469+
3470+ printk("\n# into %s, why is this called?\n", __func__);
3471+
3472+ ppc = RT_PCPU(smp_processor_id());
3473+
3474+ set_timer(&ppc->ticker, now + BUDGET(1));
3475+}
3476+
3477+
3478+/*********************************************
3479+ * Four Subscheduler Specific Functions
3480+*********************************************/
3481+
3482+//sleep the vcpu
3483+static void
3484+rt_vcpu_sleep(struct vcpu *vc) {
3485+ //SCHED_OP(vcpu_sleep, vc);
3486+ struct rt_vcpu * const dvc = RT_VCPU(vc);
3487+
3488+ BUG_ON(is_idle_vcpu(vc));
3489+
3490+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
3491+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
3492+ } else if (__vcpu_on_runq(dvc)) {
3493+ __runq_remove(dvc);
3494+ } else if (__vcpu_on_rdyq(dvc)) {
3495+ __rdyq_remove(dvc);
3496+ }
3497+
3498+ return;
3499+}
3500+
3501+//wake up the vcpu, insert it into runq, raise a softirq
3502+static void
3503+rt_vcpu_wake(struct vcpu *vc) {
3504+ //SCHED_OP(vcpu_wake, vc);
3505+ struct rt_vcpu * const dvc = RT_VCPU(vc);
3506+ const unsigned int cpu = vc->processor;
3507+
3508+ BUG_ON(is_idle_vcpu(vc));
3509+
3510+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
3511+ if (vc->domain->domain_id != 0) {
3512+ printk("\nwake running\n");
3513+ }
3514+ return;
3515+ }
3516+ if (unlikely(__vcpu_on_runq(dvc))) {
3517+ if (vc->domain->domain_id != 0) {
3518+ printk("\nwake on runq\n");
3519+ }
3520+ return;
3521+ }
3522+
3523+ if (__vcpu_on_rdyq(dvc)) {
3524+ __rdyq_remove(dvc);
3525+ }
3526+
3527+ if (!__vcpu_on_runq(dvc)) {
3528+ __runq_insert(cpu, dvc);
3529+ }
3530+
3531+ if (dvc->level < RT_CUR(cpu)->level) {
3532+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
3533+ }
3534+
3535+ return;
3536+}
3537+
3538+//ticked by pcpu tick in pcpu.
3539+static void
3540+rt_tick(void *_cpu) {
3541+ unsigned int cpu = (unsigned long) _cpu;
3542+ switch (rt_priv.type) {
3543+ case DS:
3544+ sched_deferrable_def.tick(_cpu);
3545+ break;
3546+ case PPS:
3547+ sched_periodic_def.tick(_cpu);
3548+ break;
3549+ case WCPS:
3550+ sched_wcps_def.tick(_cpu);
3551+ break;
3552+ case SSPS:
3553+ sched_ssps_def.tick(_cpu);
3554+ break;
3555+ default:
3556+ printk("Wrong in %s\n", __func__);
3557+ sched_deferrable_def.tick(_cpu);
3558+ break;
3559+ }
3560+
3561+ if (rt_cpu_pick(current) != cpu) {
3562+ set_bit(_VPF_migrating, &current->pause_flags);
3563+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
3564+ }
3565+}
3566+
3567+// most important function, called every budget time
3568+static struct task_slice
3569+rt_schedule(s_time_t now) {
3570+ switch (rt_priv.type) {
3571+ case DS:
3572+ return sched_deferrable_def.schedule(now);
3573+ break;
3574+ case PPS:
3575+ return sched_periodic_def.schedule(now);
3576+ break;
3577+ case WCPS:
3578+ return sched_wcps_def.schedule(now);
3579+ break;
3580+ case SSPS:
3581+ return sched_ssps_def.schedule(now);
3582+ break;
3583+ default:
3584+ printk("Wrong in %s\n", __func__);
3585+ return sched_deferrable_def.schedule(now);
3586+ break;
3587+ }
3588+}
3589+
3590+/*********************************************
3591+ * Used to Adjust Domain parameters and switch schedulers
3592+*********************************************/
3593+/*
3594+// !!! Need to consider SS! for the repl queue!! have not done yet!
3595+static inline void
3596+rt_reset(int cpu) {
3597+ struct rt_pcpu * ppc = RT_PCPU(cpu);
3598+ struct list_head * iter;
3599+
3600+ printk("\nBefore reset\n");
3601+ rt_dump_pcpu(cpu);
3602+
3603+ // empty the RepQ
3604+ while(ppc->rep_size != 0) {
3605+ rt_repq_remove(cpu);
3606+ }
3607+
3608+ printk("\nvcpu on list is:\n");
3609+ //init each vcpu;
3610+ list_for_each(iter, &rt_priv.active) {
3611+ struct rt_vcpu * iter_dvc = list_entry(iter, struct rt_vcpu, active_elem);
3612+ if (__vcpu_on_runq(iter_dvc)) {
3613+ __runq_remove(iter_dvc);
3614+ }
3615+ if (__vcpu_on_rdyq(iter_dvc)) {
3616+ __rdyq_remove(iter_dvc);
3617+ }
3618+ iter_dvc->cur_budget = iter_dvc->budget;
3619+ iter_dvc->last_start_time = NOW();
3620+ iter_dvc->next_time = NOW() + BUDGET(1) * iter_dvc->period;
3621+ iter_dvc->burn_total = 0;
3622+ rt_dump_vcpu(iter_dvc);
3623+ }
3624+
3625+ //insert into Queues
3626+ list_for_each(iter, &rt_priv.active) {
3627+ struct rt_vcpu * iter_dvc = list_entry(iter, struct rt_vcpu, active_elem);
3628+ if (vcpu_runnable(iter_dvc->vcpu)) {
3629+ if (!__vcpu_on_runq(iter_dvc)) {
3630+ __runq_insert(cpu, iter_dvc);
3631+ }
3632+ } else {
3633+ if (!__vcpu_on_rdyq(iter_dvc)) {
3634+ __rdyq_insert(cpu, iter_dvc);
3635+ }
3636+ }
3637+ }
3638+
3639+ printk("\nAfter Reset\n");
3640+ rt_dump_pcpu(cpu);
3641+}
3642+*/
3643+//adjust the domain's budget & period, also used to trigger the record
3644+static int
3645+rt_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
3646+ struct rt_dom * const ddom = RT_DOM(d);
3647+ unsigned long flags;
3648+ struct rt_vcpu *dvc = RT_VCPU(d->vcpu[0]);
3649+
3650+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
3651+ op->u.rt.budget = ddom->budget;
3652+ op->u.rt.period = ddom->period;
3653+ op->u.rt.level = ddom->level;
3654+ } else {
3655+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
3656+
3657+ spin_lock_irqsave(&rt_priv.lock, flags);
3658+
3659+ if (op->u.rt.budget != 0) {
3660+ ddom->budget = op->u.rt.budget;
3661+ dvc->budget = op->u.rt.budget;
3662+ }
3663+
3664+ if (op->u.rt.period != 0) {
3665+ ddom->period = op->u.rt.period;
3666+ dvc->period = op->u.rt.period;
3667+ }
3668+
3669+ if (op->u.rt.level != 0) {
3670+ ddom->level = op->u.rt.level;
3671+ dvc->level = op->u.rt.level;
3672+ }
3673+ dvc->cur_budget = dvc->budget; // reset its budget
3674+ spin_unlock_irqrestore(&rt_priv.lock, flags);
3675+
3676+ if (dvc->vcpu->domain->domain_id == 0) {
3677+ switch (op->u.rt.budget) {
3678+ case 100:
3679+ printk("############################\n100: dump info\n200: DS\n300: PPS\n400: WC-PS\n500: SS-PS\n\n");
3680+ rt_dump_pcpu(1);
3681+ break;
3682+ case 200:
3683+ rt_priv.type = DS; //change to DS;
3684+ //rt_reset(1);
3685+ break;
3686+ case 300:
3687+ rt_priv.type = PPS; // to PPS
3688+ //rt_reset(1);
3689+ break;
3690+ case 400:
3691+ rt_priv.type = WCPS; // WCPS
3692+ //rt_reset(1);
3693+ break;
3694+ case 500:
3695+ rt_priv.type = SSPS; // SSPS
3696+ //rt_reset(1);
3697+ break;
3698+ default:
3699+ printk("############################\n100: dump info\n200: DS\n300: PPS\n400: WC-PS\n500: SS-PS\n\n");
3700+ break;
3701+ }
3702+ printk("Current Scheduler: ");
3703+ switch (rt_priv.type) {
3704+ case DS:
3705+ printk("%s\n", sched_deferrable_def.name);
3706+ break;
3707+ case PPS:
3708+ printk("%s\n", sched_periodic_def.name);
3709+ break;
3710+ case WCPS:
3711+ printk("%s\n", sched_wcps_def.name);
3712+ break;
3713+ case SSPS:
3714+ printk("%s\n", sched_ssps_def.name);
3715+ break;
3716+ default:
3717+ printk("wrong, reset to DS\n");
3718+ rt_priv.type = DS;
3719+ break;
3720+ }
3721+
3722+ }
3723+ }
3724+
3725+ return 0;
3726+}
3727+
3728+const struct scheduler sched_rt_def = {
3729+ .name = "Real Time Scheduler",
3730+ .opt_name = "rt",
3731+ .sched_id = XEN_SCHEDULER_RT,
3732+
3733+ .init_domain = rt_dom_init,
3734+ .destroy_domain = rt_dom_destroy,
3735+
3736+ .init_vcpu = rt_vcpu_init,
3737+ .destroy_vcpu = rt_vcpu_destroy,
3738+
3739+ .init = rt_init,
3740+
3741+ .pick_cpu = rt_cpu_pick,
3742+
3743+ .tick_suspend = rt_tick_suspend,
3744+ .tick_resume = rt_tick_resume,
3745+
3746+ .do_schedule = rt_schedule,
3747+
3748+ .sleep = rt_vcpu_sleep,
3749+ .wake = rt_vcpu_wake,
3750+
3751+ .adjust = rt_dom_cntl,
3752+
3753+ .dump_cpu_state = rt_dump_pcpu,
3754+ .dump_settings = rt_dump,
3755+};
3756diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_deferrable.c xen-4.0.1/xen/common/sched_rt_deferrable.c
3757--- xen/xen-4.0.1/xen/common/sched_rt_deferrable.c 1969-12-31 17:00:00.000000000 -0700
3758+++ xen-4.0.1/xen/common/sched_rt_deferrable.c 2011-04-24 21:23:02.000000000 -0600
3759@@ -0,0 +1,79 @@
3760+/******************************************************************************
3761+ * Real Time Xen scheduler Framework
3762+ *
3763+ * by Sisu Xi (C) 2010 Washington University in St. Louis
3764+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
3765+ ******************************************************************************/
3766+
3767+#include <xen/config.h>
3768+#include <xen/init.h>
3769+#include <xen/lib.h>
3770+#include <xen/sched.h>
3771+#include <xen/domain.h>
3772+#include <xen/delay.h>
3773+#include <xen/event.h>
3774+#include <xen/time.h>
3775+#include <xen/perfc.h>
3776+#include <xen/sched-if.h>
3777+#include <xen/softirq.h>
3778+#include <asm/atomic.h>
3779+#include <xen/errno.h>
3780+#include <xen/keyhandler.h>
3781+#include "sched_rt.h"
3782+#include "sched_rt_repq.h"
3783+
3784+
3785+// most important function, called every budget time
3786+static struct task_slice
3787+deferrable_schedule(s_time_t now) {
3788+ const int cpu = smp_processor_id();
3789+ struct list_head *runq = RUNQ(cpu);
3790+ struct rt_vcpu *scurr = RT_VCPU(current);
3791+ struct rt_vcpu *snext;
3792+ struct task_slice ret;
3793+
3794+ RT_VCPU_CHECK(current);
3795+
3796+ if ((scurr->vcpu->domain->domain_id != 0) && (!is_idle_vcpu(scurr->vcpu))) {
3797+ repq_burn(scurr, now);
3798+ }
3799+
3800+ if (vcpu_runnable(current)) {
3801+ if (!__vcpu_on_runq(scurr)) {
3802+ __runq_insert(cpu, scurr);
3803+ }
3804+ } else {
3805+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
3806+ if (!__vcpu_on_rdyq(scurr)) {
3807+ __rdyq_insert(cpu, scurr);
3808+ }
3809+ }
3810+
3811+ snext = __runq_pick(cpu);
3812+
3813+ if (snext->vcpu->domain->domain_id != 0) {
3814+ snext->last_start_time = NOW();
3815+ }
3816+
3817+ BUG_ON(!__vcpu_on_runq(snext));
3818+ __runq_remove(snext);
3819+
3820+ ret.time = is_idle_vcpu(snext->vcpu) ? BUDGET(1) : BUDGET(1) * snext->cur_budget;
3821+ ret.task = snext->vcpu;
3822+
3823+ RT_VCPU_CHECK(ret.task);
3824+
3825+ BUG_ON(!vcpu_runnable(snext->vcpu));
3826+
3827+ return ret;
3828+}
3829+
3830+const struct rt_scheduler sched_deferrable_def = {
3831+ .name = "Deferrable Server Scheduler",
3832+ .opt_name = "ds",
3833+
3834+ .tick = repq_tick,
3835+ .vcpu_wake = NULL,
3836+ .vcpu_sleep = NULL,
3837+ .schedule = deferrable_schedule
3838+};
3839diff -ubrN xen/xen-4.0.1/xen/common/sched_rt.h xen-4.0.1/xen/common/sched_rt.h
3840--- xen/xen-4.0.1/xen/common/sched_rt.h 1969-12-31 17:00:00.000000000 -0700
3841+++ xen-4.0.1/xen/common/sched_rt.h 2011-04-24 22:23:43.000000000 -0600
3842@@ -0,0 +1,348 @@
3843+/******************************************************************************
3844+ * Real Time Xen scheduler Headfile, including the common data structures
3845+ *
3846+ * by Sisu Xi (C) 2010 Washington University in St. Louis
3847+ * based on code by Jaewoo Lee (C) 2010 University of Pennsylvania
3848+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
3849+ ******************************************************************************/
3850+
3851+#define RT_DOM(_dom) ((struct rt_dom *) (_dom)->sched_priv)
3852+#define RT_PCPU(_c) ((struct rt_pcpu *)per_cpu(schedule_data, _c).sched_priv)
3853+#define RT_VCPU(_vcpu) ((struct rt_vcpu *) (_vcpu)->sched_priv)
3854+#define RUNQ(_cpu) (&(RT_PCPU(_cpu)->runq))
3855+#define RDYQ(_cpu) (&(RT_PCPU(_cpu)->rdyq))
3856+#define RT_CUR(_cpu) RT_VCPU(per_cpu(schedule_data, _cpu).curr)
3857+#define BUDGET(_b) (MILLISECS(1*_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
3858+
3859+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
3860+
3861+#define RT_DOM_0_PERIOD 100
3862+#define RT_IDLE_PERIOD 200
3863+
3864+#define RT_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
3865+#define RT_DOM_PERIOD 50
3866+
3867+enum server_type {DS, PPS, WCPS, SSPS};
3868+
3869+
3870+/*********************************************
3871+ * Data Structure
3872+*********************************************/
3873+
3874+//physical cpu
3875+struct rt_pcpu {
3876+ struct list_head runq; // runQ on the pcpu, organized by linked list
3877+ struct list_head rdyq;
3878+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
3879+ int rep_size; // current size, for later dynamic reqQ use. currently set equals to capacity
3880+ int rep_capacity; // upper limit
3881+ struct timer ticker; // for preemptive use, tick every budget
3882+};
3883+
3884+//virtual cpu
3885+struct rt_vcpu {
3886+ struct list_head runq_elem;
3887+ struct list_head rdyq_elem;
3888+ struct list_head active_elem; //used to link all active vcpu except domain 0 and idle one!
3889+ struct rt_dom *ddom;
3890+ struct vcpu *vcpu;
3891+
3892+ uint16_t repq_pending; // used to calculate how many items are on repq
3893+
3894+ uint16_t budget;
3895+ uint16_t period;
3896+ uint16_t level;
3897+
3898+ uint16_t cur_budget;
3899+ s_time_t last_start_time; // used for burn_budget
3900+ s_time_t next_time; //the next repl time
3901+
3902+ uint16_t burn_total; // used only for Sporadic Server
3903+};
3904+
3905+//used for replenishment
3906+struct rep_elem {
3907+ s_time_t re_time;
3908+ int16_t re_amount;
3909+ struct rt_vcpu *dvc;
3910+};
3911+
3912+//domain
3913+struct rt_dom {
3914+ struct domain *dom;
3915+ uint16_t budget;
3916+ uint16_t period;
3917+ uint16_t level;
3918+};
3919+
3920+//global variable, records the number of cpus
3921+struct rt_private {
3922+ spinlock_t lock; // used for init
3923+ uint32_t ncpus; //number of physical cpus
3924+ struct list_head active; //active_vcpu except domain 0 and idle vcpu!
3925+ enum server_type type; //used to represent scheduler
3926+};
3927+
3928+struct rt_scheduler {
3929+ char *name;
3930+ char *opt_name;
3931+
3932+ void (*vcpu_sleep)(struct vcpu *vc);
3933+ void (*tick)(void *_cpu);
3934+ struct task_slice (*schedule)(s_time_t);
3935+ void (*vcpu_wake)(struct vcpu *vc);
3936+};
3937+
3938+/*********************************************
3939+ * Common Code
3940+*********************************************/
3941+
3942+//check the vcpu
3943+static inline void
3944+__rt_vcpu_check(struct vcpu *vc) {
3945+ struct rt_vcpu * const dvc = RT_VCPU(vc);
3946+ struct rt_dom * const ddom = dvc->ddom;
3947+
3948+ BUG_ON(dvc->vcpu != vc);
3949+ BUG_ON(ddom != RT_DOM(vc->domain));
3950+ if (ddom) {
3951+ BUG_ON(is_idle_vcpu(vc));
3952+ BUG_ON(ddom->dom != vc->domain);
3953+ } else {
3954+ BUG_ON(!is_idle_vcpu(vc));
3955+ }
3956+}
3957+#define RT_VCPU_CHECK(_vc) (__rt_vcpu_check(_vc))
3958+
3959+//inlined code
3960+static inline struct rt_vcpu *
3961+__runq_elem(struct list_head *elem) {
3962+ return list_entry(elem, struct rt_vcpu, runq_elem);
3963+}
3964+
3965+//inlined code
3966+static inline struct rt_vcpu *
3967+__rdyq_elem(struct list_head *elem) {
3968+ return list_entry(elem, struct rt_vcpu, rdyq_elem);
3969+}
3970+
3971+// the current vcpu is on runQ?
3972+static inline int
3973+__vcpu_on_runq(struct rt_vcpu *dvc) {
3974+ return !list_empty(&dvc->runq_elem);
3975+}
3976+
3977+// the current vcpu is on runQ?
3978+static inline int
3979+__vcpu_on_rdyq(struct rt_vcpu *dvc) {
3980+ return !list_empty(&dvc->rdyq_elem);
3981+}
3982+
3983+/*********************************************
3984+ * Dump Settings Related
3985+*********************************************/
3986+
3987+//dump the repq
3988+static inline void
3989+rt_dump_repq(int cpu) {
3990+ int loop = 0;
3991+ struct rt_pcpu *ppc = RT_PCPU(cpu);
3992+
3993+ printk("repq: size: %d\n", ppc->rep_size);
3994+ for (loop = 0; loop < ppc->rep_size; loop++) {
3995+ printk("\t[%d, %d]: %d @ %lu\n",
3996+ ppc->repq[loop].dvc->vcpu->domain->domain_id,
3997+ ppc->repq[loop].dvc->vcpu->vcpu_id,
3998+ ppc->repq[loop].re_amount,
3999+ ppc->repq[loop].re_time);
4000+ }
4001+}
4002+
4003+//dump the virtual cpu
4004+static inline void
4005+rt_dump_vcpu(struct rt_vcpu *dvc) {
4006+ printk("\t[%i, %i], cur: %i, rep: %d, last: %lu, next: %lu, \n", dvc->vcpu->domain->domain_id, dvc->vcpu->vcpu_id, dvc->cur_budget, dvc->repq_pending, dvc->last_start_time, dvc->next_time);
4007+}
4008+
4009+/*********************************************
4010+ * RunQ, RdyQ, and RepQ Related
4011+*********************************************/
4012+
4013+//pick the first vcpu whose budget is >0 from the runq
4014+static inline struct rt_vcpu *
4015+__runq_pick(unsigned int cpu) {
4016+ struct list_head * runq = RUNQ(cpu);
4017+ struct list_head * iter;
4018+
4019+ list_for_each(iter, runq) {
4020+ struct rt_vcpu * iter_dvc = __runq_elem(iter);
4021+ if (iter_dvc->cur_budget > 0) {
4022+ return iter_dvc;
4023+ }
4024+ }
4025+
4026+ BUG_ON(1);
4027+ return NULL;
4028+}
4029+
4030+//pick the first one with budget > 0, regardless of runnable or not
4031+static inline struct rt_vcpu *
4032+__rdyq_pick(unsigned int cpu) {
4033+ struct list_head * rdyq = RDYQ(cpu);
4034+ struct list_head * iter;
4035+
4036+ list_for_each(iter, rdyq) {
4037+ struct rt_vcpu *iter_dvc = __rdyq_elem(iter);
4038+ if (iter_dvc->cur_budget > 0) {
4039+ return iter_dvc;
4040+ }
4041+ }
4042+
4043+ return NULL;
4044+}
4045+
4046+//pick the IDLE VCPU from RunQ, for Periodic Server
4047+static inline struct rt_vcpu *
4048+__runq_pick_idle(unsigned int cpu) {
4049+ struct list_head * runq = RUNQ(cpu);
4050+ struct list_head * iter;
4051+
4052+ list_for_each(iter, runq) {
4053+ struct rt_vcpu * iter_dvc = __runq_elem(iter);
4054+ if (is_idle_vcpu(iter_dvc->vcpu)) {
4055+ return iter_dvc;
4056+ }
4057+ }
4058+
4059+ BUG_ON(1);
4060+ return NULL;
4061+}
4062+
4063+//insert into the runq, followed a FIFO way. sorted by level
4064+static inline void
4065+__runq_insert(unsigned int cpu, struct rt_vcpu *dvc) {
4066+ struct list_head * runq = RUNQ(cpu);
4067+ struct list_head * iter;
4068+
4069+ BUG_ON(__vcpu_on_runq(dvc));
4070+ BUG_ON(cpu != dvc->vcpu->processor);
4071+
4072+ list_for_each(iter, runq) {
4073+ struct rt_vcpu * iter_dvc = __runq_elem(iter);
4074+ if (dvc->level < iter_dvc->level) {
4075+ break;
4076+ }
4077+ }
4078+
4079+ list_add_tail(&dvc->runq_elem, iter);
4080+}
4081+
4082+//insert into the runq, followed a FIFO way. sorted by level
4083+static inline void
4084+__rdyq_insert(unsigned int cpu, struct rt_vcpu *dvc) {
4085+ struct list_head * rdyq = RDYQ(cpu);
4086+ struct list_head * iter;
4087+
4088+ BUG_ON(__vcpu_on_rdyq(dvc));
4089+ BUG_ON(cpu != dvc->vcpu->processor);
4090+
4091+ list_for_each(iter, rdyq) {
4092+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4093+ if (dvc->level <= iter_dvc->level) {
4094+ break;
4095+ }
4096+ }
4097+
4098+ list_add_tail(&dvc->rdyq_elem, iter);
4099+}
4100+
4101+//remove it from runQ
4102+static inline void
4103+__runq_remove(struct rt_vcpu *dvc) {
4104+ BUG_ON(!__vcpu_on_runq(dvc));
4105+ list_del_init(&dvc->runq_elem);
4106+}
4107+
4108+//remove it from runQ
4109+static inline void
4110+__rdyq_remove(struct rt_vcpu *dvc) {
4111+ BUG_ON(!__vcpu_on_rdyq(dvc));
4112+ list_del_init(&dvc->rdyq_elem);
4113+}
4114+
4115+//used for the heap, repQ
4116+static inline int
4117+rt_rep_parent(int childIdx) {
4118+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
4119+}
4120+
4121+//insert into the repQ
4122+static inline void
4123+rt_repq_insert(unsigned int cpu, struct rt_vcpu *dvc, int amount) {
4124+ struct rt_pcpu * ppc = RT_PCPU(cpu);
4125+ int childIdx, parentIdx;
4126+
4127+ if (dvc->next_time == 0) {
4128+ return;
4129+ }
4130+
4131+ if (amount == 0) {
4132+ return;
4133+ }
4134+
4135+ if (ppc->rep_size == ppc->rep_capacity) {
4136+ printk("\n# into %s, repQ full!!\n", __func__);
4137+ BUG_ON(1);
4138+ }
4139+
4140+ childIdx = ppc->rep_size;
4141+ parentIdx = rt_rep_parent(childIdx);
4142+
4143+ while (childIdx > 0 && dvc->next_time < ppc->repq[parentIdx].re_time) {
4144+ ppc->repq[childIdx] = ppc->repq[parentIdx];
4145+ childIdx = parentIdx;
4146+ parentIdx = rt_rep_parent(childIdx);
4147+ }
4148+
4149+ ppc->repq[childIdx].re_time = dvc->next_time;
4150+ ppc->repq[childIdx].dvc = dvc;
4151+ ppc->repq[childIdx].re_amount = amount;
4152+ ppc->rep_size++;
4153+
4154+ // dvc->next_time = 0;
4155+ dvc->repq_pending++;
4156+}
4157+
4158+//remove from the repQ
4159+static inline void
4160+rt_repq_remove(unsigned int cpu) {
4161+ struct rt_pcpu * ppc = RT_PCPU(cpu);
4162+ int childIdx = 1;
4163+ int rightChildIdx;
4164+ int rootIdx = 0;
4165+ struct rep_elem temp;
4166+
4167+ BUG_ON(ppc->rep_size <= 0);
4168+
4169+ ppc->repq[0].dvc->repq_pending--;
4170+ ppc->repq[0] = ppc->repq[ppc->rep_size - 1];
4171+ ppc->rep_size--;
4172+
4173+ temp = ppc->repq[0];
4174+
4175+ while (childIdx < ppc->rep_size) {
4176+ rightChildIdx = childIdx + 1;
4177+ if (rightChildIdx < ppc->rep_size && ppc->repq[rightChildIdx].re_time < ppc->repq[childIdx].re_time) {
4178+ childIdx = rightChildIdx;
4179+ }
4180+ if (ppc->repq[childIdx].re_time < temp.re_time) {
4181+ ppc->repq[rootIdx] = ppc->repq[childIdx];
4182+ rootIdx = childIdx;
4183+ childIdx = 2 * rootIdx + 1;
4184+ } else {
4185+ break;
4186+ }
4187+ }
4188+ ppc->repq[rootIdx] = temp;
4189+}
4190+
4191diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_periodic.c xen-4.0.1/xen/common/sched_rt_periodic.c
4192--- xen/xen-4.0.1/xen/common/sched_rt_periodic.c 1969-12-31 17:00:00.000000000 -0700
4193+++ xen-4.0.1/xen/common/sched_rt_periodic.c 2011-04-24 21:23:44.000000000 -0600
4194@@ -0,0 +1,125 @@
4195+/******************************************************************************
4196+ * Real Time Xen scheduler Framework
4197+ *
4198+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4199+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4200+ ******************************************************************************/
4201+
4202+#include <xen/config.h>
4203+#include <xen/init.h>
4204+#include <xen/lib.h>
4205+#include <xen/sched.h>
4206+#include <xen/domain.h>
4207+#include <xen/delay.h>
4208+#include <xen/event.h>
4209+#include <xen/time.h>
4210+#include <xen/perfc.h>
4211+#include <xen/sched-if.h>
4212+#include <xen/softirq.h>
4213+#include <asm/atomic.h>
4214+#include <xen/errno.h>
4215+#include <xen/keyhandler.h>
4216+#include "sched_rt.h"
4217+#include "sched_rt_repq.h"
4218+
4219+
4220+
4221+//burn the extra budget on RdyQ
4222+static void
4223+repq_burn_rdyq(struct rt_vcpu *dvc, s_time_t now) {
4224+ s_time_t delta;
4225+ unsigned int consume;
4226+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
4227+ struct list_head * iter;
4228+
4229+ BUG_ON(dvc != RT_CUR(dvc->vcpu->processor));
4230+
4231+ if (dvc->last_start_time == 0) {
4232+ dvc->last_start_time = now;
4233+ return;
4234+ }
4235+
4236+ delta = now - dvc->last_start_time;
4237+ BUG_ON(delta <= 0);
4238+
4239+ consume = ( delta/BUDGET(1) );
4240+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
4241+
4242+ // burn budgets on RdyQ
4243+ list_for_each(iter, rdyq) {
4244+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4245+ if (iter_dvc->cur_budget > 0) {
4246+ iter_dvc->cur_budget -= consume;
4247+ if (iter_dvc->cur_budget < 0) {
4248+ iter_dvc->budget = 0;
4249+ }
4250+ return; // only burn one budget
4251+ }
4252+ }
4253+
4254+ return;
4255+}
4256+
4257+
4258+// most important function, called every budget time
4259+static struct task_slice
4260+periodic_schedule(s_time_t now) {
4261+ const int cpu = smp_processor_id();
4262+ struct list_head *runq = RUNQ(cpu);
4263+ struct rt_vcpu *scurr = RT_VCPU(current);
4264+ struct rt_vcpu *snext;
4265+ struct task_slice ret;
4266+
4267+ RT_VCPU_CHECK(current);
4268+
4269+ if ((scurr->vcpu->domain->domain_id != 0)) {
4270+ if (!is_idle_vcpu(scurr->vcpu)) {
4271+ repq_burn(scurr, now);
4272+ } else if (cpu == 1) { //scurr is the idle vcpu on cpu 1, need to deal with periodic server
4273+ repq_burn_rdyq(scurr, now);
4274+ }
4275+ }
4276+
4277+ if (vcpu_runnable(current)) {
4278+ if (!__vcpu_on_runq(scurr)) {
4279+ __runq_insert(cpu, scurr);
4280+ }
4281+ } else {
4282+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
4283+ if (!__vcpu_on_rdyq(scurr)) {
4284+ __rdyq_insert(cpu, scurr);
4285+ }
4286+ }
4287+
4288+ if ( (__rdyq_pick(cpu) == NULL) || (__runq_pick(cpu)->level < __rdyq_pick(cpu)->level) ) {
4289+ snext = __runq_pick(cpu);
4290+ } else {
4291+ snext = __runq_pick_idle(cpu); // pick the IDLE to mimic the as if budget idled away behavior
4292+ }
4293+
4294+ if (snext->vcpu->domain->domain_id != 0) {
4295+ snext->last_start_time = NOW();
4296+ }
4297+
4298+ BUG_ON(!__vcpu_on_runq(snext));
4299+ __runq_remove(snext);
4300+
4301+ ret.time = BUDGET(1);
4302+ ret.task = snext->vcpu;
4303+
4304+ RT_VCPU_CHECK(ret.task);
4305+
4306+ BUG_ON(!vcpu_runnable(snext->vcpu));
4307+
4308+ return ret;
4309+}
4310+
4311+const struct rt_scheduler sched_periodic_def = {
4312+ .name = "Pure Periodic Server Scheduler",
4313+ .opt_name = "pps",
4314+
4315+ .tick = repq_tick,
4316+ .vcpu_sleep = NULL,
4317+ .vcpu_wake = NULL,
4318+ .schedule = periodic_schedule
4319+};
4320diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_repq.h xen-4.0.1/xen/common/sched_rt_repq.h
4321--- xen/xen-4.0.1/xen/common/sched_rt_repq.h 1969-12-31 17:00:00.000000000 -0700
4322+++ xen-4.0.1/xen/common/sched_rt_repq.h 2011-05-02 21:06:21.000000000 -0600
4323@@ -0,0 +1,86 @@
4324+/******************************************************************************
4325+ * Real Time Xen scheduler Headfile, including the common data structures
4326+ *
4327+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4328+ * based on code by Jaewoo Lee (C) 2010 University of Pennsylvania
4329+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4330+ ******************************************************************************/
4331+
4332+
4333+/*********************************************
4334+ * Shared by the subschedulers
4335+*********************************************/
4336+
4337+//check the current repQ to see if a repl needs to happen
4338+//Even if the IDLE VCPU is running, just raise an interrupt to trigger the schedule function!!
4339+static int
4340+check_cpu_for_repl(int cpu) {
4341+ struct rt_pcpu * ppc = RT_PCPU(cpu);
4342+ int flag = 0; //used for interrupt
4343+
4344+ while((ppc->rep_size != 0) && ppc->repq[0].re_time < NOW()) {
4345+ ppc->repq[0].dvc->cur_budget += ppc->repq[0].re_amount;
4346+ if (ppc->repq[0].dvc->cur_budget > ppc->repq[0].dvc->budget) {
4347+ ppc->repq[0].dvc->cur_budget = ppc->repq[0].dvc->budget;
4348+ }
4349+
4350+ while (ppc->repq[0].dvc->next_time <= NOW()) {
4351+ ppc->repq[0].dvc->next_time += BUDGET(1) * ppc->repq[0].dvc->period;
4352+ }
4353+ rt_repq_insert(ppc->repq[0].dvc->vcpu->processor, ppc->repq[0].dvc, ppc->repq[0].dvc->budget);
4354+
4355+ if (ppc->repq[0].dvc->level < RT_CUR(cpu)->level) flag = 1; // need to raise an interrupt
4356+
4357+ // bug fix 0501
4358+ if (ppc->repq[0].dvc->level != RT_CUR(cpu)->level) { // do not change the current running one
4359+ ppc->repq[0].dvc->last_start_time = NOW();
4360+ }
4361+
4362+ rt_repq_remove(cpu);
4363+ }
4364+
4365+ return flag;
4366+}
4367+
4368+//ticked by pcpu tick in pcpu, used in the repq way
4369+static void
4370+repq_tick(void *_cpu) {
4371+ unsigned int cpu = (unsigned long) _cpu;
4372+ struct rt_pcpu *ppc = RT_PCPU(cpu);
4373+
4374+ BUG_ON(current->processor != cpu);
4375+
4376+ if (check_cpu_for_repl(cpu)) {
4377+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
4378+ }
4379+
4380+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
4381+}
4382+
4383+static int
4384+repq_burn(struct rt_vcpu *dvc, s_time_t now) {
4385+ s_time_t delta;
4386+ unsigned int consume;
4387+
4388+ BUG_ON(dvc != RT_CUR(dvc->vcpu->processor));
4389+
4390+ if (dvc->last_start_time == 0) {
4391+ dvc->last_start_time = now;
4392+ return 0;
4393+ }
4394+
4395+ delta = now - dvc->last_start_time;
4396+ BUG_ON(delta <= 0);
4397+
4398+ consume = ( delta/BUDGET(1) );
4399+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
4400+
4401+ if (consume > dvc->cur_budget) {
4402+ dvc->cur_budget = 0;
4403+ } else {
4404+ dvc->cur_budget -= consume;
4405+ }
4406+
4407+ return consume;
4408+}
4409+
4410diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_ssps.c xen-4.0.1/xen/common/sched_rt_ssps.c
4411--- xen/xen-4.0.1/xen/common/sched_rt_ssps.c 1969-12-31 17:00:00.000000000 -0700
4412+++ xen-4.0.1/xen/common/sched_rt_ssps.c 2011-05-01 19:41:06.000000000 -0600
4413@@ -0,0 +1,197 @@
4414+/******************************************************************************
4415+ * Real Time Xen scheduler Framework
4416+ *
4417+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4418+ * based on code by Jaewoo Lee (C) U Penn
4419+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4420+ ******************************************************************************/
4421+
4422+#include <xen/config.h>
4423+#include <xen/init.h>
4424+#include <xen/lib.h>
4425+#include <xen/sched.h>
4426+#include <xen/domain.h>
4427+#include <xen/delay.h>
4428+#include <xen/event.h>
4429+#include <xen/time.h>
4430+#include <xen/perfc.h>
4431+#include <xen/sched-if.h>
4432+#include <xen/softirq.h>
4433+#include <asm/atomic.h>
4434+#include <xen/errno.h>
4435+#include <xen/keyhandler.h>
4436+#include "sched_rt.h"
4437+#include "sched_rt_repq.h"
4438+
4439+
4440+static int
4441+check_rdyq(int cpu) {
4442+ struct list_head * rdyq = RDYQ(cpu);
4443+ struct list_head * iter;
4444+
4445+ list_for_each(iter, rdyq) {
4446+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4447+ if (iter_dvc->cur_budget > 0) {
4448+ return 1;
4449+ }
4450+ }
4451+
4452+ return 0;
4453+}
4454+
4455+//burn the extra budget on RdyQ
4456+static void
4457+ssps_burn_rdyq(struct rt_vcpu *dvc, s_time_t now) {
4458+ s_time_t delta;
4459+ unsigned int consume;
4460+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
4461+ struct list_head * iter;
4462+
4463+ BUG_ON(dvc != RT_CUR(dvc->vcpu->processor));
4464+
4465+ if (dvc->last_start_time == 0) {
4466+ dvc->last_start_time = now;
4467+ return;
4468+ }
4469+
4470+ delta = now - dvc->last_start_time;
4471+ BUG_ON(delta <= 0);
4472+
4473+ consume = ( delta/BUDGET(1) );
4474+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
4475+
4476+ // burn budgets on RdyQ
4477+ list_for_each(iter, rdyq) {
4478+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4479+ if (iter_dvc->cur_budget > 0) {
4480+ //bug fix 0501
4481+
4482+ delta = now - iter_dvc->last_start_time;
4483+ // just get repled, skip this VCPU
4484+ if (delta < BUDGET(1)) {
4485+ continue;
4486+ }
4487+ if (consume > iter_dvc->cur_budget) {
4488+ iter_dvc->cur_budget = 0;
4489+ } else {
4490+ iter_dvc->cur_budget -= consume;
4491+ }
4492+ return; // only burn one budget
4493+ }
4494+ }
4495+
4496+ return;
4497+}
4498+
4499+static void
4500+ssps_burn_extra(int cpu, int consume) {
4501+ struct list_head * rdyq = RDYQ(cpu);
4502+ struct list_head * iter;
4503+
4504+ // burn budgets on RdyQ
4505+ list_for_each(iter, rdyq) {
4506+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4507+ if (iter_dvc->cur_budget > 0) {
4508+ if (consume > iter_dvc->cur_budget) {
4509+ iter_dvc->cur_budget = 0;
4510+ } else {
4511+ iter_dvc->cur_budget -= consume;
4512+ }
4513+ return; // only burn one budget
4514+ }
4515+ }
4516+
4517+ return;
4518+}
4519+
4520+//pick the first vcpu whose budget is >0 from the runq
4521+static inline struct rt_vcpu *
4522+__ssps_runq_pick(unsigned int cpu) {
4523+ struct list_head * runq = RUNQ(cpu);
4524+ struct list_head * iter;
4525+
4526+ list_for_each(iter, runq) {
4527+ struct rt_vcpu * iter_dvc = __runq_elem(iter);
4528+ return iter_dvc;
4529+ }
4530+
4531+ BUG_ON(1);
4532+ return NULL;
4533+}
4534+
4535+// most important function, called every budget time
4536+static struct task_slice
4537+ssps_schedule(s_time_t now) {
4538+ const int cpu = smp_processor_id();
4539+ struct list_head *runq = RUNQ(cpu);
4540+ struct rt_vcpu *scurr = RT_VCPU(current);
4541+ struct rt_vcpu *snext;
4542+ struct task_slice ret;
4543+ int consume;
4544+ int old_budget;
4545+
4546+ RT_VCPU_CHECK(current);
4547+
4548+ if ((scurr->vcpu->domain->domain_id != 0)) {
4549+ if (!is_idle_vcpu(scurr->vcpu)) {
4550+ //check how many budget should burn
4551+ old_budget = scurr->cur_budget;
4552+ if (old_budget > 0) {
4553+ consume = repq_burn(scurr, now);
4554+ if (consume != 0 && __rdyq_pick(cpu) != NULL && __rdyq_pick(cpu)->level < scurr->level) {
4555+ scurr->cur_budget = old_budget; //restore its original budget
4556+ ssps_burn_extra(cpu, consume); // burn the one on rdyq instead
4557+ }
4558+ } else {
4559+ ssps_burn_rdyq(scurr, now);
4560+ }
4561+ } else {
4562+ ssps_burn_rdyq(scurr, now); // idle VCPU, still need to burn the ones on rdyq
4563+ }
4564+ }
4565+
4566+ if (vcpu_runnable(current)) {
4567+ if (!__vcpu_on_runq(scurr)) {
4568+ __runq_insert(cpu, scurr);
4569+ }
4570+ } else {
4571+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
4572+ if (!__vcpu_on_rdyq(scurr)) {
4573+ __rdyq_insert(cpu, scurr);
4574+ }
4575+ }
4576+
4577+ snext = __runq_pick(cpu);
4578+ //slack stealing!!
4579+ if (is_idle_vcpu(snext->vcpu)) {
4580+ if (check_rdyq(snext->vcpu->processor)) {
4581+ snext = __ssps_runq_pick(cpu);
4582+ }
4583+ }
4584+
4585+ if (snext->vcpu->domain->domain_id != 0) {
4586+ snext->last_start_time = NOW();
4587+ }
4588+
4589+ BUG_ON(!__vcpu_on_runq(snext));
4590+ __runq_remove(snext);
4591+
4592+ ret.time = BUDGET(1);
4593+ ret.task = snext->vcpu;
4594+
4595+ RT_VCPU_CHECK(ret.task);
4596+
4597+ BUG_ON(!vcpu_runnable(snext->vcpu));
4598+
4599+ return ret;
4600+}
4601+
4602+
4603+const struct rt_scheduler sched_ssps_def = {
4604+ .name = "Slack Stealing Periodic Server Scheduler",
4605+ .opt_name = "ssps",
4606+ .tick = repq_tick,
4607+ .vcpu_sleep = NULL,
4608+ .vcpu_wake = NULL,
4609+ .schedule = ssps_schedule
4610+};
4611diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_wcps.c xen-4.0.1/xen/common/sched_rt_wcps.c
4612--- xen/xen-4.0.1/xen/common/sched_rt_wcps.c 1969-12-31 17:00:00.000000000 -0700
4613+++ xen-4.0.1/xen/common/sched_rt_wcps.c 2011-05-01 13:24:27.000000000 -0600
4614@@ -0,0 +1,146 @@
4615+/******************************************************************************
4616+ * Real Time Xen scheduler Framework
4617+ *
4618+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4619+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4620+ ******************************************************************************/
4621+
4622+#include <xen/config.h>
4623+#include <xen/init.h>
4624+#include <xen/lib.h>
4625+#include <xen/sched.h>
4626+#include <xen/domain.h>
4627+#include <xen/delay.h>
4628+#include <xen/event.h>
4629+#include <xen/time.h>
4630+#include <xen/perfc.h>
4631+#include <xen/sched-if.h>
4632+#include <xen/softirq.h>
4633+#include <asm/atomic.h>
4634+#include <xen/errno.h>
4635+#include <xen/keyhandler.h>
4636+#include "sched_rt.h"
4637+#include "sched_rt_repq.h"
4638+
4639+//burn the extra budget on RdyQ
4640+static void
4641+wcps_burn_rdyq(struct rt_vcpu *dvc, s_time_t now) {
4642+ s_time_t delta;
4643+ unsigned int consume;
4644+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
4645+ struct list_head * iter;
4646+
4647+ BUG_ON(dvc != RT_CUR(dvc->vcpu->processor));
4648+
4649+ if (dvc->last_start_time == 0) {
4650+ dvc->last_start_time = now;
4651+ return;
4652+ }
4653+
4654+ delta = now - dvc->last_start_time;
4655+ BUG_ON(delta <= 0);
4656+
4657+ consume = ( delta/BUDGET(1) );
4658+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
4659+
4660+ // burn budgets on RdyQ
4661+ list_for_each(iter, rdyq) {
4662+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4663+ if (iter_dvc->cur_budget > 0) {
4664+ if (consume > iter_dvc->cur_budget) {
4665+ iter_dvc->cur_budget = 0;
4666+ } else {
4667+ iter_dvc->cur_budget -= consume;
4668+ }
4669+ return; // only burn one budget
4670+ }
4671+ }
4672+
4673+ return;
4674+}
4675+
4676+
4677+static void
4678+wcps_burn_extra(int cpu, int consume) {
4679+ struct list_head * rdyq = RDYQ(cpu);
4680+ struct list_head * iter;
4681+
4682+ // burn budgets on RdyQ
4683+ list_for_each(iter, rdyq) {
4684+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4685+ if (iter_dvc->cur_budget > 0) {
4686+ if (consume > iter_dvc->cur_budget) {
4687+ iter_dvc->cur_budget = 0;
4688+ } else {
4689+ iter_dvc->cur_budget -= consume;
4690+ }
4691+ return; // only burn one budget
4692+ }
4693+ }
4694+
4695+ return;
4696+}
4697+
4698+
4699+// most important function, called every budget time
4700+static struct task_slice
4701+wcps_schedule(s_time_t now) {
4702+ const int cpu = smp_processor_id();
4703+ struct list_head *runq = RUNQ(cpu);
4704+ struct rt_vcpu *scurr = RT_VCPU(current);
4705+ struct rt_vcpu *snext;
4706+ struct task_slice ret;
4707+ int consume;
4708+
4709+ RT_VCPU_CHECK(current);
4710+
4711+ if ((scurr->vcpu->domain->domain_id != 0)) {
4712+ if (!is_idle_vcpu(scurr->vcpu)) {
4713+ consume = repq_burn(scurr, now);
4714+ if (consume != 0 && __rdyq_pick(cpu) != NULL && __rdyq_pick(cpu)->level < scurr->level) {
4715+ wcps_burn_extra(cpu, consume); // burn the extra budget on rdyq, mimic the idled away behavior
4716+ }
4717+ } else if (cpu == 1) {
4718+ wcps_burn_rdyq(scurr, now);
4719+ }
4720+ }
4721+
4722+ if (vcpu_runnable(current)) {
4723+ if (!__vcpu_on_runq(scurr)) {
4724+ __runq_insert(cpu, scurr);
4725+ }
4726+ } else {
4727+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
4728+ if (!__vcpu_on_rdyq(scurr)) {
4729+ __rdyq_insert(cpu, scurr);
4730+ }
4731+ }
4732+
4733+ snext = __runq_pick(cpu);
4734+
4735+ if (snext->vcpu->domain->domain_id != 0) {
4736+ snext->last_start_time = NOW();
4737+ }
4738+
4739+ BUG_ON(!__vcpu_on_runq(snext));
4740+ __runq_remove(snext);
4741+
4742+ ret.time = BUDGET(1);
4743+ ret.task = snext->vcpu;
4744+
4745+ RT_VCPU_CHECK(ret.task);
4746+
4747+ BUG_ON(!vcpu_runnable(snext->vcpu));
4748+
4749+ return ret;
4750+}
4751+
4752+const struct rt_scheduler sched_wcps_def = {
4753+ .name = "Work Conserving Periodic Server Scheduler",
4754+ .opt_name = "wcps",
4755+
4756+ .tick = repq_tick,
4757+ .vcpu_sleep = NULL,
4758+ .vcpu_wake = NULL,
4759+ .schedule = wcps_schedule,
4760+};
4761diff -ubrN xen/xen-4.0.1/xen/common/sched_sedf.c xen-4.0.1/xen/common/sched_sedf.c
4762--- xen/xen-4.0.1/xen/common/sched_sedf.c 2010-08-25 04:22:12.000000000 -0600
4763+++ xen-4.0.1/xen/common/sched_sedf.c 2011-04-09 23:29:38.000000000 -0600
4764@@ -1429,6 +1429,11 @@
4765 }
4766
4767 rc = sedf_adjust_weights(op);
4768+
4769+ if (p->domain_id == 0) {
4770+ return 1;
4771+ }
4772+
4773 if ( rc )
4774 return rc;
4775
4776@@ -1453,6 +1458,7 @@
4777 }
4778
4779 PRINT(2,"sedf_adjust_finished\n");
4780+
4781 return 0;
4782 }
4783
4784diff -ubrN xen/xen-4.0.1/xen/common/sched_ss.c xen-4.0.1/xen/common/sched_ss.c
4785--- xen/xen-4.0.1/xen/common/sched_ss.c 1969-12-31 17:00:00.000000000 -0700
4786+++ xen-4.0.1/xen/common/sched_ss.c 2011-01-21 08:38:10.000000000 -0700
4787@@ -0,0 +1,884 @@
4788+/******************************************************************************
4789+ * Sporadic Server scheduler for xen
4790+ *
4791+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4792+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4793+ ******************************************************************************/
4794+
4795+#include <xen/config.h>
4796+#include <xen/init.h>
4797+#include <xen/lib.h>
4798+#include <xen/sched.h>
4799+#include <xen/domain.h>
4800+#include <xen/delay.h>
4801+#include <xen/event.h>
4802+#include <xen/time.h>
4803+#include <xen/perfc.h>
4804+#include <xen/sched-if.h>
4805+#include <xen/softirq.h>
4806+#include <asm/atomic.h>
4807+#include <xen/errno.h>
4808+#include <xen/keyhandler.h>
4809+
4810+#define SS_DOM(_dom) ((struct ss_dom *) (_dom)->sched_priv)
4811+#define SS_PCPU(_c) ((struct ss_pcpu *)per_cpu(schedule_data, _c).sched_priv)
4812+#define SS_VCPU(_vcpu) ((struct ss_vcpu *) (_vcpu)->sched_priv)
4813+#define RUNQ(_cpu) (&(SS_PCPU(_cpu)->runq))
4814+#define SS_CUR(_cpu) SS_VCPU(per_cpu(schedule_data, _cpu).curr)
4815+#define BUDGET(_b) (MILLISECS(_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
4816+
4817+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
4818+
4819+#define SS_DOM_0_PERIOD 100
4820+#define SS_IDLE_PERIOD 200
4821+
4822+#define SS_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
4823+#define SS_DOM_PERIOD 50
4824+
4825+//used for status
4826+#define IDLE 0
4827+#define ACTIVE 1
4828+
4829+//used for replenishment
4830+struct rep_elem {
4831+ s_time_t re_time;
4832+ uint16_t re_amount;
4833+ struct ss_vcpu *svc;
4834+};
4835+
4836+//physical cpu
4837+struct ss_pcpu {
4838+ struct list_head runq; // runQ on the pcpu, organized by linked list
4839+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
4840+ int rep_size; // current size
4841+ int rep_capacity; // upper limit
4842+ struct timer ticker; // for preemptive use, tick every budget
4843+};
4844+
4845+//virtual cpu
4846+struct ss_vcpu {
4847+ struct list_head runq_elem;
4848+ struct ss_dom *sdom;
4849+ struct vcpu *vcpu;
4850+
4851+ uint16_t budget;
4852+ uint16_t period;
4853+
4854+ uint16_t cur_budget;
4855+ s_time_t last_start_time; // used for burn_budget
4856+ uint16_t burn_total; // used for budget repl
4857+ int status;
4858+
4859+ s_time_t next_time; // used for repl
4860+};
4861+
4862+//domain
4863+struct ss_dom {
4864+ struct domain *dom;
4865+ uint16_t budget;
4866+ uint16_t period;
4867+};
4868+
4869+//global variable, records the number of cpus
4870+struct ss_private {
4871+ spinlock_t lock;
4872+ uint32_t ncpus;
4873+};
4874+static struct ss_private ss_priv;
4875+
4876+/*
4877+//used for record, overhead measurement
4878+#define RECORD 4000
4879+struct record_elem{
4880+ int curr;
4881+ int next;
4882+ s_time_t enter_base; // enter rep insert time
4883+ s_time_t leave_base; // leave rep insert time
4884+ s_time_t enter; // enter schedule time
4885+ s_time_t leave; // leave schedule time
4886+};
4887+*/
4888+struct timer ss_start_timer; // would start after 10s, used only once
4889+int ss_start_flag = 0; // start to record or not
4890+int ss_wake = 0;
4891+/*
4892+int idx = 0; //idx to record
4893+struct record_elem res[RECORD]; // domain_id, time in ms;
4894+//finish for the record
4895+*/
4896+static void ss_tick(void *_cpu);
4897+
4898+//dump the repq
4899+static void
4900+ss_dump_repq(int cpu) {
4901+ int loop = 0;
4902+ struct ss_pcpu *spc = SS_PCPU(cpu);
4903+
4904+ printk("\n# into %s on cpu %d, now is %lu, size: %d, the repQ is :\n", __func__, cpu, NOW(), spc->rep_size);
4905+ for (loop = 0; loop < spc->rep_size; loop++) {
4906+ printk("\t[%d. %d]: %d @ %lu\n",
4907+ spc->repq[loop].svc->vcpu->domain->domain_id,
4908+ spc->repq[loop].svc->vcpu->vcpu_id,
4909+ spc->repq[loop].re_amount,
4910+ spc->repq[loop].re_time);
4911+ }
4912+}
4913+
4914+//dump the virtual cpu
4915+static void
4916+ss_dump_vcpu(struct ss_vcpu *svc) {
4917+ printk("\t[%i, %i], (%i, %i), cpu: %i, cur_budget: %i, last_start_time: %lu, burn_total: %i, status %d, next_time: %lu\n",
4918+ svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id, svc->budget, svc->period, svc->vcpu->processor,
4919+ svc->cur_budget, svc->last_start_time, svc->burn_total, svc->status, svc->next_time);
4920+}
4921+
4922+//inlined code
4923+static inline struct ss_vcpu *
4924+__runq_elem(struct list_head *elem) {
4925+ return list_entry(elem, struct ss_vcpu, runq_elem);
4926+}
4927+
4928+//dump the physical cpu
4929+static void
4930+ss_dump_pcpu(int cpu) {
4931+ struct list_head *iter;
4932+ struct ss_pcpu *spc = SS_PCPU(cpu);
4933+ struct list_head *runq = &spc->runq;
4934+ struct ss_vcpu *svc = SS_CUR(cpu);
4935+ int loop = 0;
4936+
4937+ printk("\n# into %s, on cpu: %d, now is: %lu\n", __func__, cpu, NOW());
4938+
4939+ if (svc) {
4940+ printk("\trun: ");
4941+ ss_dump_vcpu(svc);
4942+ }
4943+
4944+ list_for_each(iter, runq) {
4945+ svc = __runq_elem(iter);
4946+ if (svc) {
4947+ printk("\t%3d: ", ++loop);
4948+ ss_dump_vcpu(svc);
4949+ }
4950+ }
4951+
4952+ ss_dump_repq(cpu);
4953+}
4954+/*
4955+//dump the record out.
4956+static void
4957+ss_dump_record(void) {
4958+ int i;
4959+
4960+ for (i = 1; i < RECORD; i++) {
4961+ printk("%-3d %-3d %13lu %13lu %13lu %13lu\n", res[i].curr, res[i].next, res[i].enter_base, res[i].leave_base, res[i].enter, res[i].leave);
4962+ }
4963+ ss_dump_pcpu(1);
4964+ idx = 0;
4965+ start_flag = 0;
4966+}
4967+
4968+*/
4969+// the current vcpu is on runQ?
4970+static inline int
4971+__vcpu_on_runq(struct ss_vcpu *svc) {
4972+ return !list_empty(&svc->runq_elem);
4973+}
4974+
4975+//pick the first vcpu whose budget is >0 from the runq
4976+static inline struct ss_vcpu *
4977+__runq_pick(unsigned int cpu) {
4978+ struct list_head * runq = RUNQ(cpu);
4979+ struct list_head * iter;
4980+
4981+ list_for_each(iter, runq) {
4982+ struct ss_vcpu * iter_svc = __runq_elem(iter);
4983+ if (iter_svc->cur_budget > 0) {
4984+ return iter_svc;
4985+ }
4986+ }
4987+
4988+ BUG_ON(1);
4989+ return NULL;
4990+}
4991+
4992+//insert into the runq, followed a FIFO way. sorted by period
4993+static inline void
4994+__runq_insert(unsigned int cpu, struct ss_vcpu *svc) {
4995+ struct list_head * runq = RUNQ(cpu);
4996+ struct list_head * iter;
4997+
4998+ BUG_ON(__vcpu_on_runq(svc));
4999+ BUG_ON(cpu != svc->vcpu->processor);
5000+
5001+ list_for_each(iter, runq) {
5002+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5003+ if (svc->vcpu->domain->domain_id <= iter_svc->vcpu->domain->domain_id) {
5004+ break;
5005+ }
5006+ }
5007+
5008+ list_add_tail(&svc->runq_elem, iter);
5009+}
5010+
5011+//remove it from runQ
5012+static inline void
5013+__runq_remove(struct ss_vcpu *svc) {
5014+ BUG_ON(!__vcpu_on_runq(svc));
5015+ list_del_init(&svc->runq_elem);
5016+}
5017+
5018+//used for the heap, repQ
5019+static inline int
5020+ss_rep_parent(int childIdx) {
5021+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
5022+}
5023+
5024+//insert into the repQ
5025+static inline void
5026+ss_repq_insert(unsigned int cpu, struct ss_vcpu *svc, int amount) {
5027+ struct ss_pcpu * spc = SS_PCPU(cpu);
5028+ int childIdx, parentIdx;
5029+
5030+ if (amount == 0) {
5031+ svc->next_time = 0;
5032+ return;
5033+ }
5034+
5035+ if (svc->next_time == 0) {
5036+ printk("\n# in %s, ERROR! svc is:", __func__);
5037+ ss_dump_vcpu(svc);
5038+ ss_dump_pcpu(cpu);
5039+ BUG_ON(1);
5040+ }
5041+
5042+ if (spc->rep_size == spc->rep_capacity) {
5043+ printk("\n# into %s, repQ full!!\n", __func__);
5044+ BUG_ON(1);
5045+ }
5046+
5047+ childIdx = spc->rep_size;
5048+ parentIdx = ss_rep_parent(childIdx);
5049+
5050+
5051+ while (childIdx > 0 && svc->next_time < spc->repq[parentIdx].re_time) {
5052+ spc->repq[childIdx] = spc->repq[parentIdx];
5053+ childIdx = parentIdx;
5054+ parentIdx = ss_rep_parent(childIdx);
5055+ }
5056+
5057+ spc->repq[childIdx].re_time = svc->next_time;
5058+ spc->repq[childIdx].re_amount = amount;
5059+ spc->repq[childIdx].svc = svc;
5060+ spc->rep_size++;
5061+/*
5062+ printk("\t add a repl. now: %lu, cpu: %d, re_time: %lu, amount: %d, for cpu [%d, %d]\n",
5063+ NOW(), cpu, svc->next_time, amount, svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id);
5064+ ss_dump_vcpu(svc);
5065+*/
5066+ svc->next_time = 0;
5067+}
5068+
5069+//remove from the repQ
5070+static inline void
5071+ss_repq_remove(unsigned int cpu) {
5072+ struct ss_pcpu * spc = SS_PCPU(cpu);
5073+ int childIdx = 1;
5074+ int rightChildIdx;
5075+ int rootIdx = 0;
5076+ struct rep_elem temp;
5077+
5078+ BUG_ON(spc->rep_size <= 0);
5079+
5080+ spc->repq[0] = spc->repq[spc->rep_size - 1];
5081+ spc->rep_size--;
5082+
5083+ temp = spc->repq[0];
5084+
5085+ while (childIdx < spc->rep_size) {
5086+ rightChildIdx = childIdx + 1;
5087+ if (rightChildIdx < spc->rep_size && spc->repq[rightChildIdx].re_time < spc->repq[childIdx].re_time) {
5088+ childIdx = rightChildIdx;
5089+ }
5090+ if (spc->repq[childIdx].re_time < temp.re_time) {
5091+ spc->repq[rootIdx] = spc->repq[childIdx];
5092+ rootIdx = childIdx;
5093+ childIdx = 2 * rootIdx + 1;
5094+ } else {
5095+ break;
5096+ }
5097+ }
5098+ spc->repq[rootIdx] = temp;
5099+}
5100+
5101+//svc should be snext. Doing this is because we can not get snext->period
5102+//scan the runQ to change status, deside next time or amount
5103+static void
5104+ss_scan_runq(unsigned int cpu, struct ss_vcpu *svc) {
5105+ struct list_head * runq = RUNQ(cpu);
5106+ struct ss_vcpu *cur = svc;
5107+ struct list_head * iter;
5108+ int re_amount;
5109+
5110+ list_for_each(iter, runq) {
5111+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5112+ if (is_idle_vcpu(iter_svc->vcpu)) {
5113+ return;
5114+ }
5115+
5116+ if (iter_svc->vcpu->domain->domain_id < cur->vcpu->domain->domain_id) {
5117+ if (iter_svc->status == ACTIVE) {
5118+ //change from ACTIVE to IDLE, decide the repl amount
5119+ BUG_ON(iter_svc->next_time == 0);
5120+ iter_svc->status = IDLE;
5121+ re_amount = iter_svc->burn_total;
5122+ iter_svc->burn_total = 0;
5123+ ss_repq_insert(cpu, iter_svc, re_amount);
5124+ }
5125+ } else {
5126+ if (iter_svc->status == IDLE) {
5127+ //mark it to be ACTIVE, decide the repl time
5128+ iter_svc->status = ACTIVE;
5129+ BUG_ON(iter_svc->next_time != 0);
5130+ iter_svc->next_time = NOW() + BUDGET(iter_svc->period);
5131+ }
5132+ }
5133+ }
5134+}
5135+
5136+//dump dump function
5137+static void
5138+ss_dump(void) {
5139+ printk("# into %s.\n", __func__);
5140+}
5141+
5142+//burn the scurr budget
5143+static void
5144+burn_budgets(struct ss_vcpu *svc, s_time_t now) {
5145+ s_time_t delta;
5146+ unsigned int consume;
5147+
5148+ BUG_ON(svc != SS_CUR(svc->vcpu->processor));
5149+
5150+ if (svc->last_start_time == 0) {
5151+ svc->last_start_time = now;
5152+ return;
5153+ }
5154+
5155+ delta = now - svc->last_start_time;
5156+ BUG_ON(delta <= 0);
5157+
5158+ consume = ( delta/BUDGET(1) );
5159+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
5160+ if (consume > svc->cur_budget) {
5161+ //printk("\n# into %s, this should not happen!\n", __func__);
5162+ consume = svc->cur_budget;
5163+ }
5164+
5165+ svc->cur_budget -= consume;
5166+ svc->burn_total += consume;
5167+}
5168+
5169+//init the physical cpu
5170+static int
5171+ss_pcpu_init(int cpu) {
5172+ struct ss_pcpu *spc;
5173+ unsigned long flags;
5174+
5175+ /* Allocate per-PCPU info */
5176+ spc = xmalloc(struct ss_pcpu);
5177+ if (spc == NULL)
5178+ return -1;
5179+ memset(spc, 0, sizeof (*spc));
5180+
5181+ spin_lock_irqsave(&ss_priv.lock, flags);
5182+
5183+ if (ss_priv.ncpus < cpu)
5184+ ss_priv.ncpus = cpu + 1;
5185+
5186+ init_timer(&spc->ticker, ss_tick, (void *) (unsigned long) cpu, cpu);
5187+ INIT_LIST_HEAD(&spc->runq);
5188+ per_cpu(schedule_data, cpu).sched_priv = spc;
5189+
5190+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
5191+
5192+ spc->rep_capacity = REPQ_CAPACITY;
5193+ spc->repq = xmalloc_array(struct rep_elem, spc->rep_capacity);
5194+ BUG_ON(spc->repq == NULL);
5195+ spc->rep_size = 0;
5196+
5197+ spin_unlock_irqrestore(&ss_priv.lock, flags);
5198+
5199+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
5200+
5201+ return 0;
5202+}
5203+
5204+//check the vcpu
5205+static inline void
5206+__ss_vcpu_check(struct vcpu *vc) {
5207+ struct ss_vcpu * const svc = SS_VCPU(vc);
5208+ struct ss_dom * const sdom = svc->sdom;
5209+
5210+ BUG_ON(svc->vcpu != vc);
5211+ BUG_ON(sdom != SS_DOM(vc->domain));
5212+ if (sdom) {
5213+ BUG_ON(is_idle_vcpu(vc));
5214+ BUG_ON(sdom->dom != vc->domain);
5215+ } else {
5216+ BUG_ON(!is_idle_vcpu(vc));
5217+ }
5218+}
5219+#define SS_VCPU_CHECK(_vc) (__ss_vcpu_check(_vc))
5220+
5221+//pick a cpu to run, used to migrate from different cpus
5222+static int
5223+ss_cpu_pick(struct vcpu *vc) {
5224+ cpumask_t cpus;
5225+ int cpu;
5226+
5227+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
5228+
5229+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
5230+ return cycle_cpu(vc->processor, cpus);
5231+ }
5232+
5233+ cpu = cpu_isset(vc->processor, cpus)
5234+ ? vc->processor
5235+ : cycle_cpu(vc->processor, cpus);
5236+
5237+ return cpu;
5238+}
5239+
5240+//check the current repQ to see if a repl needs to happen
5241+static int
5242+check_cpu_for_repl(int cpu) {
5243+ int ret = 0;
5244+ struct ss_pcpu * spc = SS_PCPU(cpu);
5245+
5246+ while((spc->rep_size != 0) && spc->repq[0].re_time < NOW()) {
5247+ spc->repq[0].svc->cur_budget += spc->repq[0].re_amount;
5248+ if (spc->repq[0].svc->cur_budget > spc->repq[0].svc->budget) {
5249+ printk("\n# into %s, this should not happen!\n", __func__);
5250+ spc->repq[0].svc->cur_budget = spc->repq[0].svc->budget;
5251+ }
5252+ ss_repq_remove(cpu);
5253+ ret = 1;
5254+ }
5255+
5256+ return ret;
5257+}
5258+
5259+//if a repl happens, do we need an interrupt? (higher priority than current running one)
5260+static void
5261+check_runq_for_interrupt(int cpu) {
5262+ struct list_head * runq = RUNQ(cpu);
5263+ struct list_head * iter;
5264+ struct ss_vcpu * cur = SS_CUR(cpu);
5265+
5266+ list_for_each(iter, runq) {
5267+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5268+ if (iter_svc->vcpu->domain->domain_id >= cur->vcpu->domain->domain_id) {
5269+ return;
5270+ } else if (iter_svc->cur_budget > 0) {
5271+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
5272+ }
5273+ }
5274+}
5275+
5276+//init the virtual cpu
5277+static int
5278+ss_vcpu_init(struct vcpu *vc) {
5279+ struct domain * const dom = vc->domain;
5280+ struct ss_dom *sdom = SS_DOM(dom);
5281+ struct ss_vcpu *svc;
5282+
5283+ /* Allocate per-VCPU info */
5284+ svc = xmalloc(struct ss_vcpu);
5285+ if (svc == NULL) {
5286+ return -1;
5287+ }
5288+ memset(svc, 0, sizeof (*svc));
5289+
5290+ INIT_LIST_HEAD(&svc->runq_elem);
5291+ svc->sdom = sdom;
5292+ svc->vcpu = vc;
5293+ svc->budget = is_idle_vcpu(vc)? SS_IDLE_PERIOD: sdom->budget;
5294+ svc->period = is_idle_vcpu(vc)? SS_IDLE_PERIOD: sdom->period;
5295+ svc->cur_budget = svc->budget;
5296+
5297+ svc->last_start_time = 0;
5298+ svc->burn_total = 0;
5299+ svc->next_time = 0;
5300+ svc->status = IDLE;
5301+ vc->sched_priv = svc;
5302+
5303+ /* Allocate per-PCPU info */
5304+ if (unlikely(!SS_PCPU(vc->processor))) {
5305+ if (ss_pcpu_init(vc->processor) != 0)
5306+ return -1;
5307+ }
5308+
5309+ SS_VCPU_CHECK(vc);
5310+
5311+ printk("\n# into %s, vcpu init: ", __func__);
5312+ ss_dump_vcpu(svc);
5313+
5314+ return 0;
5315+}
5316+
5317+//destory the vcpu
5318+static void
5319+ss_vcpu_destroy(struct vcpu *vc) {
5320+ struct ss_vcpu * const svc = SS_VCPU(vc);
5321+ struct ss_dom * const sdom = svc->sdom;
5322+
5323+ printk("\n# into %s, vcpu destroy: ", __func__);
5324+ ss_dump_vcpu(svc);
5325+
5326+ BUG_ON(sdom == NULL);
5327+ BUG_ON(!list_empty(&svc->runq_elem));
5328+
5329+ xfree(svc);
5330+}
5331+
5332+//sleep the vcpu
5333+static void
5334+ss_vcpu_sleep(struct vcpu *vc) {
5335+ struct ss_vcpu * const svc = SS_VCPU(vc);
5336+
5337+ if (vc->domain->domain_id != 0) {
5338+ printk("\n# into %s: now %lu, sleep vcpu: \n", __func__, NOW());
5339+ ss_dump_vcpu(svc);
5340+ }
5341+
5342+ BUG_ON(is_idle_vcpu(vc));
5343+
5344+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
5345+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
5346+ } else if (__vcpu_on_runq(svc)) {
5347+ //BUG_ON(svc->status == ACTIVE);
5348+ __runq_remove(svc);
5349+ }
5350+}
5351+
5352+//wake up the vcpu, insert it into runq, raise a softirq
5353+static void
5354+ss_vcpu_wake(struct vcpu *vc) {
5355+ struct ss_vcpu * const svc = SS_VCPU(vc);
5356+ const unsigned int cpu = vc->processor;
5357+
5358+ BUG_ON(is_idle_vcpu(vc));
5359+
5360+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
5361+ //printk("\n# why wake up running? migration?\n");
5362+ return;
5363+ }
5364+ if (unlikely(__vcpu_on_runq(svc))) {
5365+ //printk("\n# why wake up on runq ones? migration?\n");
5366+ return;
5367+ }
5368+
5369+ __runq_insert(cpu, svc);
5370+ if (svc->vcpu->domain->domain_id < SS_CUR(cpu)->vcpu->domain->domain_id) {
5371+ if (svc->vcpu->processor == 1 && ss_start_flag == 1) {
5372+ ss_wake++;
5373+ }
5374+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
5375+ }
5376+}
5377+
5378+//used for record data, for overhead measurement
5379+static void
5380+ss_ss_finish_timer(void * temp) {
5381+ ss_start_flag = 0;
5382+ printk("wake up %d times\n", ss_wake);
5383+ ss_wake = 0;
5384+}
5385+
5386+static void
5387+ss_ss_start_timer(void * temp) {
5388+ ss_start_flag = 1;
5389+ init_timer(&ss_start_timer, ss_ss_finish_timer, (void *) (unsigned int) 1, 1);
5390+ set_timer(&ss_start_timer, NOW() + MILLISECS(10000));
5391+}
5392+
5393+//adjust the domain's budget & period, also used to trigger the record
5394+static int
5395+ss_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
5396+ struct ss_dom * const sdom = SS_DOM(d);
5397+ unsigned long flags;
5398+ struct ss_vcpu *svc = SS_VCPU(d->vcpu[0]);
5399+
5400+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
5401+ op->u.ss.budget = sdom->budget;
5402+ op->u.ss.period = sdom->period;
5403+ //ss_dump_vcpu(svc);
5404+ } else {
5405+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
5406+
5407+ spin_lock_irqsave(&ss_priv.lock, flags);
5408+ if (op->u.ss.budget != 0) {
5409+ sdom->budget = op->u.ss.budget;
5410+ svc->budget = op->u.ss.budget;
5411+ }
5412+ if (op->u.ss.period != 0) {
5413+ sdom->period = op->u.ss.period;
5414+ svc->period = op->u.ss.period;
5415+ }
5416+ svc->cur_budget = svc->budget;
5417+ spin_unlock_irqrestore(&ss_priv.lock, flags);
5418+
5419+ if (svc->vcpu->domain->domain_id == 0) {
5420+ init_timer(&ss_start_timer, ss_ss_start_timer, (void *) (unsigned int) 1, 1);
5421+ set_timer(&ss_start_timer, NOW() + MILLISECS(5000));
5422+ return 1;
5423+ }
5424+
5425+ //ss_dump_vcpu(svc);
5426+ }
5427+
5428+ return 0;
5429+}
5430+
5431+//init a dom
5432+static int
5433+ss_dom_init(struct domain *dom) {
5434+ struct ss_dom *sdom;
5435+
5436+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
5437+
5438+ if (is_idle_domain(dom)) {
5439+ printk("\t# init an idle domain\n");
5440+ return 0;
5441+ }
5442+
5443+ sdom = xmalloc(struct ss_dom);
5444+ if (sdom == NULL)
5445+ return -ENOMEM;
5446+ memset(sdom, 0, sizeof (*sdom));
5447+
5448+ /* Initialize budget and period */
5449+ sdom->dom = dom;
5450+
5451+ switch(dom->domain_id) {
5452+ case 32767:
5453+ sdom->budget = SS_IDLE_PERIOD;
5454+ sdom->period = SS_IDLE_PERIOD;
5455+ break;
5456+ case 0:
5457+ sdom->budget = SS_DOM_0_PERIOD;
5458+ sdom->period = SS_DOM_0_PERIOD;
5459+ break;
5460+ default:
5461+ sdom->budget = SS_DOM_BUDGET;
5462+ sdom->period = SS_DOM_PERIOD;
5463+ break;
5464+ }
5465+
5466+ dom->sched_priv = sdom;
5467+
5468+ return 0;
5469+}
5470+
5471+//destory a domain
5472+static void
5473+ss_dom_destroy(struct domain *dom) {
5474+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
5475+ xfree(SS_DOM(dom));
5476+}
5477+
5478+//ticked by pcpu tick in pcpu.
5479+static void
5480+ss_tick(void *_cpu) {
5481+ unsigned int cpu = (unsigned long) _cpu;
5482+ struct ss_pcpu *spc = SS_PCPU(cpu);
5483+
5484+ BUG_ON(current->processor != cpu);
5485+
5486+ if (check_cpu_for_repl(cpu)) {
5487+ check_runq_for_interrupt(cpu);
5488+ }
5489+
5490+ if (ss_cpu_pick(current) != cpu) {
5491+ set_bit(_VPF_migrating, &current->pause_flags);
5492+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
5493+ }
5494+
5495+ set_timer(&spc->ticker, NOW() + BUDGET(1));
5496+}
5497+
5498+// most important function, called every budget time
5499+static struct task_slice
5500+ss_schedule(s_time_t now) {
5501+ const int cpu = smp_processor_id();
5502+ struct list_head *runq = RUNQ(cpu);
5503+ struct ss_vcpu *scurr = SS_VCPU(current);
5504+ struct ss_vcpu *snext;
5505+ struct task_slice ret;
5506+ int re_amount;
5507+
5508+ SS_VCPU_CHECK(current);
5509+/*
5510+// for record
5511+ if (smp_processor_id() == 1 && start_flag == 1) {
5512+ if(is_idle_vcpu(scurr->vcpu)) res[idx].curr = 10;
5513+ else res[idx].curr = scurr->vcpu->domain->domain_id;
5514+ res[idx].enter_base = NOW();
5515+ res[idx].leave_base = NOW();
5516+ res[idx].enter = NOW();
5517+ }
5518+*/
5519+ if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
5520+ //if (!is_idle_vcpu(scurr->vcpu)) {
5521+ burn_budgets(scurr, now);
5522+ }
5523+
5524+ if (vcpu_runnable(current)) {
5525+ __runq_insert(cpu, scurr);
5526+ } else {
5527+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
5528+ }
5529+
5530+ snext = __runq_pick(cpu);
5531+
5532+ __runq_remove(snext);
5533+
5534+//context switch do happen!, and snext is not an idle vcpu
5535+ if (cpu == 1 && snext != scurr) {
5536+ //if (snext != scurr) {
5537+ //for the scurr:
5538+ //if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
5539+ if (!is_idle_vcpu(scurr->vcpu)) {
5540+ BUG_ON(scurr->status != ACTIVE);
5541+ BUG_ON(scurr->next_time == 0);
5542+ scurr->status = IDLE;
5543+ re_amount = scurr->burn_total;
5544+ scurr->burn_total = 0;
5545+ //printk("\n# into %s, change status to IDLE, decide repl amount here! now is %lu, for vcpu[%d, %d], re_amount is: %d, re_time is %lu\n",
5546+ // __func__, NOW(), scurr->vcpu->domain->domain_id, scurr->vcpu->vcpu_id, re_amount, scurr->next_time);
5547+ ss_repq_insert(cpu, scurr, re_amount);
5548+ }
5549+
5550+ //for the snext:
5551+ //if (!is_idle_vcpu(snext->vcpu) && snext->vcpu->domain->domain_id != 0) {
5552+ if (!is_idle_vcpu(snext->vcpu)) {
5553+ if (snext->status == IDLE) {
5554+ BUG_ON(snext->next_time != 0);
5555+ snext->status = ACTIVE;
5556+ snext->next_time = NOW() + BUDGET(snext->period);
5557+ //printk("\n# into %s, change status to ACTIVE, decide repl time here! now is %lu, for vcpu [%d, %d], re_time is %lu\n",
5558+ // __func__, NOW(), snext->vcpu->domain->domain_id, snext->vcpu->vcpu_id, snext->next_time);
5559+ }
5560+ }
5561+
5562+ //scan the whole runq
5563+ ss_scan_runq(cpu, snext);
5564+ }
5565+
5566+ if (cpu == 1 && snext->vcpu->domain->domain_id != 0) {
5567+ snext->last_start_time = NOW();
5568+ }
5569+
5570+ ret.time = (is_idle_vcpu(snext->vcpu) ? -1 : BUDGET(1));
5571+ //ret.time = BUDGET(1);
5572+ ret.task = snext->vcpu;
5573+
5574+ SS_VCPU_CHECK(ret.task);
5575+
5576+ BUG_ON(!vcpu_runnable(snext->vcpu));
5577+ //printk("now is %lu\n", now);
5578+
5579+/*
5580+// for record
5581+
5582+ if (smp_processor_id() == 1 && start_flag == 1) {
5583+ if(is_idle_vcpu(snext->vcpu)) res[idx].next = 10;
5584+ else res[idx].next = snext->vcpu->domain->domain_id;
5585+ res[idx].leave = NOW();
5586+ if(idx++ >= RECORD) {
5587+ ss_dump_pcpu(1);
5588+ ss_dump_record();
5589+ }
5590+ }
5591+*/
5592+ return ret;
5593+}
5594+
5595+//init the global data
5596+static void
5597+ss_init(void) {
5598+ printk("\n# into %s\n", __func__);
5599+ spin_lock_init(&ss_priv.lock);
5600+ ss_priv.ncpus = 0;
5601+}
5602+
5603+/* Tickers cannot be kicked until SMP subsystem is alive. */
5604+static __init int
5605+ss_start_tickers(void) {
5606+ struct ss_pcpu *spc;
5607+ unsigned int cpu;
5608+
5609+ printk("\n# into %s, start all tickers right now\n", __func__);
5610+
5611+ if (ss_priv.ncpus == 0)
5612+ return 0;
5613+
5614+ for_each_online_cpu(cpu) {
5615+ spc = SS_PCPU(cpu);
5616+ set_timer(&spc->ticker, NOW() + BUDGET(1));
5617+ }
5618+
5619+ return 0;
5620+}
5621+__initcall(ss_start_tickers);
5622+
5623+static void ss_tick_suspend(void) {
5624+ struct ss_pcpu *spc;
5625+
5626+ printk("\n# into %s, why is this called?\n", __func__);
5627+
5628+ spc = SS_PCPU(smp_processor_id());
5629+
5630+ stop_timer(&spc->ticker);
5631+}
5632+
5633+static void ss_tick_resume(void) {
5634+ struct ss_pcpu *spc;
5635+ uint64_t now = NOW();
5636+
5637+ printk("\n# into %s, why is this called?\n", __func__);
5638+
5639+ spc = SS_PCPU(smp_processor_id());
5640+
5641+ set_timer(&spc->ticker, now + BUDGET(1));
5642+}
5643+
5644+const struct scheduler sched_ss_def = {
5645+ .name = "Sporadic Server Scheduler",
5646+ .opt_name = "ss",
5647+ .sched_id = XEN_SCHEDULER_SS,
5648+
5649+ .init_domain = ss_dom_init,
5650+ .destroy_domain = ss_dom_destroy,
5651+
5652+ .init_vcpu = ss_vcpu_init,
5653+ .destroy_vcpu = ss_vcpu_destroy,
5654+
5655+ .init = ss_init,
5656+
5657+ .pick_cpu = ss_cpu_pick,
5658+
5659+ .tick_suspend = ss_tick_suspend,
5660+ .tick_resume = ss_tick_resume,
5661+
5662+ .do_schedule = ss_schedule,
5663+
5664+ .sleep = ss_vcpu_sleep,
5665+ .wake = ss_vcpu_wake,
5666+
5667+ .adjust = ss_dom_cntl,
5668+
5669+ .dump_cpu_state = ss_dump_pcpu,
5670+ .dump_settings = ss_dump,
5671+};
5672diff -ubrN xen/xen-4.0.1/xen/common/sched_ss_rtas11.c xen-4.0.1/xen/common/sched_ss_rtas11.c
5673--- xen/xen-4.0.1/xen/common/sched_ss_rtas11.c 1969-12-31 17:00:00.000000000 -0700
5674+++ xen-4.0.1/xen/common/sched_ss_rtas11.c 2010-12-16 00:46:03.000000000 -0700
5675@@ -0,0 +1,893 @@
5676+/******************************************************************************
5677+ * Sporadic Server scheduler for xen
5678+ *
5679+ * by Sisu Xi (C) 2010 Washington University in St. Louis
5680+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
5681+ ******************************************************************************/
5682+
5683+#include <xen/config.h>
5684+#include <xen/init.h>
5685+#include <xen/lib.h>
5686+#include <xen/sched.h>
5687+#include <xen/domain.h>
5688+#include <xen/delay.h>
5689+#include <xen/event.h>
5690+#include <xen/time.h>
5691+#include <xen/perfc.h>
5692+#include <xen/sched-if.h>
5693+#include <xen/softirq.h>
5694+#include <asm/atomic.h>
5695+#include <xen/errno.h>
5696+#include <xen/keyhandler.h>
5697+
5698+#define SS_DOM(_dom) ((struct ss_dom *) (_dom)->sched_priv)
5699+#define SS_PCPU(_c) ((struct ss_pcpu *)per_cpu(schedule_data, _c).sched_priv)
5700+#define SS_VCPU(_vcpu) ((struct ss_vcpu *) (_vcpu)->sched_priv)
5701+#define RUNQ(_cpu) (&(SS_PCPU(_cpu)->runq))
5702+#define SS_CUR(_cpu) SS_VCPU(per_cpu(schedule_data, _cpu).curr)
5703+#define BUDGET(_b) (MILLISECS(_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
5704+
5705+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
5706+
5707+#define SS_DOM_0_PERIOD 100
5708+#define SS_IDLE_PERIOD 200
5709+
5710+#define SS_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
5711+#define SS_DOM_PERIOD 50
5712+
5713+//used for status
5714+#define IDLE 0
5715+#define ACTIVE 1
5716+
5717+//used for replenishment
5718+struct rep_elem {
5719+ s_time_t re_time;
5720+ uint16_t re_amount;
5721+ struct ss_vcpu *svc;
5722+};
5723+
5724+//physical cpu
5725+struct ss_pcpu {
5726+ struct list_head runq; // runQ on the pcpu, organized by linked list
5727+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
5728+ int rep_size; // current size, for later dynamic reqQ use. currently set equals to capacity
5729+ int rep_capacity; // upper limit
5730+ struct timer ticker; // for preemptive use, tick every budget
5731+};
5732+
5733+//virtual cpu
5734+struct ss_vcpu {
5735+ struct list_head runq_elem;
5736+ struct ss_dom *sdom;
5737+ struct vcpu *vcpu;
5738+
5739+ uint16_t budget;
5740+ uint16_t period;
5741+
5742+ uint16_t cur_budget;
5743+ s_time_t last_start_time; // used for burn_budget
5744+ uint16_t burn_total; // used for budget repl
5745+ int status;
5746+
5747+ s_time_t next_time; // used for repl
5748+};
5749+
5750+//domain
5751+struct ss_dom {
5752+ struct domain *dom;
5753+ uint16_t budget;
5754+ uint16_t period;
5755+};
5756+
5757+//global variable, records the number of cpus
5758+struct ss_private {
5759+ spinlock_t lock; // used for init
5760+ uint32_t ncpus; //number of physical cpus
5761+};
5762+static struct ss_private ss_priv;
5763+
5764+//used for record, overhead measurement
5765+#define RECORD 4000
5766+struct record_elem{
5767+ int curr;
5768+ int next;
5769+ s_time_t enter_base; // enter rep insert time
5770+ s_time_t leave_base; // leave rep insert time
5771+ s_time_t enter; // enter schedule time
5772+ s_time_t leave; // leave schedule time
5773+};
5774+
5775+struct timer start_timer; // would start after 10s, used only once
5776+int start_flag = 0; // start to record or not
5777+int idx = 0; //idx to record
5778+struct record_elem res[RECORD]; // domain_id, time in ms;
5779+//finish for the record
5780+
5781+static void ss_tick(void *_cpu);
5782+
5783+//dump the repq
5784+static void
5785+ss_dump_repq(int cpu) {
5786+ int loop = 0;
5787+ struct ss_pcpu *spc = SS_PCPU(cpu);
5788+
5789+ printk("\n# into %s on cpu %d, now is %lu, size: %d, the repQ is :\n", __func__, cpu, NOW(), spc->rep_size);
5790+ for (loop = 0; loop < spc->rep_size; loop++) {
5791+ printk("\t[%d. %d]: %d @ %lu\n",
5792+ spc->repq[loop].svc->vcpu->domain->domain_id,
5793+ spc->repq[loop].svc->vcpu->vcpu_id,
5794+ spc->repq[loop].re_amount,
5795+ spc->repq[loop].re_time);
5796+ }
5797+}
5798+
5799+//dump the virtual cpu
5800+static void
5801+ss_dump_vcpu(struct ss_vcpu *svc) {
5802+ printk("\t[%i, %i], (%i, %i), cpu: %i, cur_budget: %i, last_start_time: %lu, burn_total: %i, status %d, next_time: %lu\n",
5803+ svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id, svc->budget, svc->period, svc->vcpu->processor,
5804+ svc->cur_budget, svc->last_start_time, svc->burn_total, svc->status, svc->next_time);
5805+}
5806+
5807+//inlined code
5808+static inline struct ss_vcpu *
5809+__runq_elem(struct list_head *elem) {
5810+ return list_entry(elem, struct ss_vcpu, runq_elem);
5811+}
5812+
5813+//dump the physical cpu
5814+static void
5815+ss_dump_pcpu(int cpu) {
5816+ struct list_head *iter;
5817+ struct ss_pcpu *spc = SS_PCPU(cpu);
5818+ struct list_head *runq = &spc->runq;
5819+ struct ss_vcpu *svc = SS_CUR(cpu);
5820+ int loop = 0;
5821+
5822+ printk("\n# into %s, on cpu: %d, now is: %lu\n", __func__, cpu, NOW());
5823+
5824+ if (svc) {
5825+ printk("\trun: ");
5826+ ss_dump_vcpu(svc);
5827+ }
5828+
5829+ list_for_each(iter, runq) {
5830+ svc = __runq_elem(iter);
5831+ if (svc) {
5832+ printk("\t%3d: ", ++loop);
5833+ ss_dump_vcpu(svc);
5834+ }
5835+ }
5836+
5837+ ss_dump_repq(cpu);
5838+}
5839+
5840+//dump the record out.
5841+static void
5842+ss_dump_record(void) {
5843+ int i;
5844+
5845+ for (i = 1; i < RECORD; i++) {
5846+ printk("%-3d %-3d %13lu %13lu %13lu %13lu\n", res[i].curr, res[i].next, res[i].enter_base, res[i].leave_base, res[i].enter, res[i].leave);
5847+ }
5848+ //ss_dump_pcpu(1);
5849+ idx = 0;
5850+ start_flag = 0;
5851+}
5852+
5853+// the current vcpu is on runQ?
5854+static inline int
5855+__vcpu_on_runq(struct ss_vcpu *svc) {
5856+ return !list_empty(&svc->runq_elem);
5857+}
5858+
5859+//pick the first vcpu whose budget is >0 from the runq
5860+static inline struct ss_vcpu *
5861+__runq_pick(unsigned int cpu) {
5862+ struct list_head * runq = RUNQ(cpu);
5863+ struct list_head * iter;
5864+
5865+ list_for_each(iter, runq) {
5866+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5867+ if (iter_svc->cur_budget > 0) {
5868+ return iter_svc;
5869+ }
5870+ }
5871+
5872+ BUG_ON(1);
5873+ return NULL;
5874+}
5875+
5876+//insert into the runq, followed a FIFO way. sorted by period
5877+static inline void
5878+__runq_insert(unsigned int cpu, struct ss_vcpu *svc) {
5879+ struct list_head * runq = RUNQ(cpu);
5880+ struct list_head * iter;
5881+
5882+ BUG_ON(__vcpu_on_runq(svc));
5883+ BUG_ON(cpu != svc->vcpu->processor);
5884+
5885+ list_for_each(iter, runq) {
5886+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5887+ if (svc->period <= iter_svc->period) {
5888+ break;
5889+ }
5890+ }
5891+
5892+ list_add_tail(&svc->runq_elem, iter);
5893+}
5894+
5895+//remove it from runQ
5896+static inline void
5897+__runq_remove(struct ss_vcpu *svc) {
5898+ BUG_ON(!__vcpu_on_runq(svc));
5899+ list_del_init(&svc->runq_elem);
5900+}
5901+
5902+//used for the heap, repQ
5903+static inline int
5904+ss_rep_parent(int childIdx) {
5905+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
5906+}
5907+
5908+//insert into the repQ
5909+static inline void
5910+ss_repq_insert(unsigned int cpu, struct ss_vcpu *svc, int amount) {
5911+ struct ss_pcpu * spc = SS_PCPU(cpu);
5912+ int childIdx, parentIdx;
5913+
5914+ if (amount == 0) {
5915+ svc->next_time = 0;
5916+ return;
5917+ }
5918+
5919+ if (svc->next_time == 0) {
5920+ printk("\n# in %s, ERROR! svc is:", __func__);
5921+ ss_dump_vcpu(svc);
5922+ ss_dump_pcpu(cpu);
5923+ BUG_ON(1);
5924+ }
5925+
5926+ if (spc->rep_size == spc->rep_capacity) {
5927+ printk("\n# into %s, repQ full!!\n", __func__);
5928+ BUG_ON(1);
5929+ }
5930+
5931+ childIdx = spc->rep_size;
5932+ parentIdx = ss_rep_parent(childIdx);
5933+
5934+
5935+ while (childIdx > 0 && svc->next_time < spc->repq[parentIdx].re_time) {
5936+ spc->repq[childIdx] = spc->repq[parentIdx];
5937+ childIdx = parentIdx;
5938+ parentIdx = ss_rep_parent(childIdx);
5939+ }
5940+
5941+ spc->repq[childIdx].re_time = svc->next_time;
5942+ spc->repq[childIdx].re_amount = amount;
5943+ spc->repq[childIdx].svc = svc;
5944+ spc->rep_size++;
5945+/*
5946+ printk("\t add a repl. now: %lu, cpu: %d, re_time: %lu, amount: %d, for cpu [%d, %d]\n",
5947+ NOW(), cpu, svc->next_time, amount, svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id);
5948+ ss_dump_vcpu(svc);
5949+*/
5950+ svc->next_time = 0;
5951+}
5952+
5953+//remove from the repQ
5954+static inline void
5955+ss_repq_remove(unsigned int cpu) {
5956+ struct ss_pcpu * spc = SS_PCPU(cpu);
5957+ int childIdx = 1;
5958+ int rightChildIdx;
5959+ int rootIdx = 0;
5960+ struct rep_elem temp;
5961+
5962+ BUG_ON(spc->rep_size <= 0);
5963+
5964+ spc->repq[0] = spc->repq[spc->rep_size - 1];
5965+ spc->rep_size--;
5966+
5967+ temp = spc->repq[0];
5968+
5969+ while (childIdx < spc->rep_size) {
5970+ rightChildIdx = childIdx + 1;
5971+ if (rightChildIdx < spc->rep_size && spc->repq[rightChildIdx].re_time < spc->repq[childIdx].re_time) {
5972+ childIdx = rightChildIdx;
5973+ }
5974+ if (spc->repq[childIdx].re_time < temp.re_time) {
5975+ spc->repq[rootIdx] = spc->repq[childIdx];
5976+ rootIdx = childIdx;
5977+ childIdx = 2 * rootIdx + 1;
5978+ } else {
5979+ break;
5980+ }
5981+ }
5982+ spc->repq[rootIdx] = temp;
5983+}
5984+
5985+//svc should be snext. Doing this is because we can not get snext->period
5986+//scan the runQ to change status, deside next time or amount
5987+static void
5988+ss_scan_runq(unsigned int cpu, struct ss_vcpu *svc) {
5989+ struct list_head * runq = RUNQ(cpu);
5990+ struct ss_vcpu *cur = svc;
5991+ struct list_head * iter;
5992+ int re_amount;
5993+
5994+ list_for_each(iter, runq) {
5995+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5996+ if (is_idle_vcpu(iter_svc->vcpu)) {
5997+ return;
5998+ }
5999+
6000+ //those who has higher priority but run out of budget
6001+ if (iter_svc->period < cur->period) {
6002+ if (iter_svc->status == ACTIVE) {
6003+ //change from ACTIVE to IDLE, decide the repl amount
6004+ BUG_ON(iter_svc->next_time == 0);
6005+ iter_svc->status = IDLE;
6006+ re_amount = iter_svc->burn_total;
6007+ iter_svc->burn_total = 0;
6008+ ss_repq_insert(cpu, iter_svc, re_amount);
6009+ }
6010+ }
6011+ //those who has lower priority, should all be set to IDLE. On runQ means it has work to do!!!
6012+ else {
6013+ /*
6014+ if (iter_svc->status == IDLE) {
6015+ //mark it to be ACTIVE, decide the repl time
6016+ iter_svc->status = ACTIVE;
6017+ BUG_ON(iter_svc->next_time != 0);
6018+ iter_svc->next_time = NOW() + BUDGET(iter_svc->period);
6019+ }
6020+ */
6021+ // modification made according to RTAS 10 paper
6022+ if (iter_svc->status == ACTIVE) {
6023+ //mark it to be IDLE, decide the repl amount
6024+ BUG_ON(iter_svc->next_time == 0);
6025+ iter_svc->status = IDLE;
6026+ re_amount = iter_svc->burn_total;
6027+ iter_svc->burn_total = 0;
6028+ ss_repq_insert(cpu, iter_svc, re_amount);
6029+ printk("# into %s, Mark lower running CPU to be IDLE!\n", __func__);
6030+ }
6031+ }
6032+ }
6033+}
6034+
6035+//dump dump function
6036+static void
6037+ss_dump(void) {
6038+ printk("# into %s. Did Nothing\n", __func__);
6039+}
6040+
6041+//burn the scurr budget
6042+static void
6043+burn_budgets(struct ss_vcpu *svc, s_time_t now) {
6044+ s_time_t delta;
6045+ unsigned int consume;
6046+
6047+ BUG_ON(svc != SS_CUR(svc->vcpu->processor));
6048+
6049+ if (svc->last_start_time == 0) {
6050+ svc->last_start_time = now;
6051+ return;
6052+ }
6053+
6054+ delta = now - svc->last_start_time;
6055+ BUG_ON(delta <= 0);
6056+
6057+ consume = ( delta/BUDGET(1) );
6058+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
6059+ if (consume > svc->cur_budget) {
6060+ printk("\n# into %s, consumed more than cur budget!\n", __func__);
6061+ consume = svc->cur_budget;
6062+ }
6063+
6064+ svc->cur_budget -= consume;
6065+ svc->burn_total += consume;
6066+}
6067+
6068+//init the physical cpu
6069+static int
6070+ss_pcpu_init(int cpu) {
6071+ struct ss_pcpu *spc;
6072+ unsigned long flags;
6073+
6074+ /* Allocate per-PCPU info */
6075+ spc = xmalloc(struct ss_pcpu);
6076+ if (spc == NULL)
6077+ return -1;
6078+ memset(spc, 0, sizeof (*spc));
6079+
6080+ spin_lock_irqsave(&ss_priv.lock, flags);
6081+
6082+ if (ss_priv.ncpus < cpu)
6083+ ss_priv.ncpus = cpu + 1;
6084+
6085+ init_timer(&spc->ticker, ss_tick, (void *) (unsigned long) cpu, cpu);
6086+ INIT_LIST_HEAD(&spc->runq);
6087+ per_cpu(schedule_data, cpu).sched_priv = spc;
6088+
6089+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
6090+
6091+ spc->rep_capacity = REPQ_CAPACITY;
6092+ spc->repq = xmalloc_array(struct rep_elem, spc->rep_capacity);
6093+ BUG_ON(spc->repq == NULL);
6094+ spc->rep_size = 0;
6095+
6096+ spin_unlock_irqrestore(&ss_priv.lock, flags);
6097+
6098+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
6099+
6100+ return 0;
6101+}
6102+
6103+//check the vcpu
6104+static inline void
6105+__ss_vcpu_check(struct vcpu *vc) {
6106+ struct ss_vcpu * const svc = SS_VCPU(vc);
6107+ struct ss_dom * const sdom = svc->sdom;
6108+
6109+ BUG_ON(svc->vcpu != vc);
6110+ BUG_ON(sdom != SS_DOM(vc->domain));
6111+ if (sdom) {
6112+ BUG_ON(is_idle_vcpu(vc));
6113+ BUG_ON(sdom->dom != vc->domain);
6114+ } else {
6115+ BUG_ON(!is_idle_vcpu(vc));
6116+ }
6117+}
6118+#define SS_VCPU_CHECK(_vc) (__ss_vcpu_check(_vc))
6119+
6120+//pick a cpu to run, used to migrate from different cpus
6121+static int
6122+ss_cpu_pick(struct vcpu *vc) {
6123+ cpumask_t cpus;
6124+ int cpu;
6125+
6126+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
6127+
6128+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
6129+ return cycle_cpu(vc->processor, cpus);
6130+ }
6131+
6132+ cpu = cpu_isset(vc->processor, cpus)
6133+ ? vc->processor
6134+ : cycle_cpu(vc->processor, cpus);
6135+
6136+ return cpu;
6137+}
6138+
6139+//check the current repQ to see if a repl needs to happen
6140+static int
6141+check_cpu_for_repl(int cpu) {
6142+// int ret = 0;
6143+ struct ss_pcpu * spc = SS_PCPU(cpu);
6144+ int flag = 0; //used for interrupt
6145+ int priority = SS_CUR(cpu)->period; // current running vcpu's period
6146+
6147+ while((spc->rep_size != 0) && spc->repq[0].re_time < NOW()) {
6148+ spc->repq[0].svc->cur_budget += spc->repq[0].re_amount;
6149+ if (spc->repq[0].svc->cur_budget > spc->repq[0].svc->budget) {
6150+ //printk("\n# into %s, repl to more than init budget!\n", __func__);
6151+ spc->repq[0].svc->cur_budget = spc->repq[0].svc->budget;
6152+ }
6153+ if (flag == 0 && spc->repq[0].svc->period < priority) {
6154+ flag = 1; // need interrupt
6155+ }
6156+ ss_repq_remove(cpu);
6157+// ret = 1;
6158+ }
6159+
6160+ return flag;
6161+}
6162+
6163+/*
6164+//if a repl happens, do we need an interrupt? (higher priority than current running one)
6165+static void
6166+check_runq_for_interrupt(int cpu) {
6167+ struct list_head * runq = RUNQ(cpu);
6168+ struct list_head * iter;
6169+ struct ss_vcpu * cur = SS_CUR(cpu);
6170+
6171+ list_for_each(iter, runq) {
6172+ struct ss_vcpu * iter_svc = __runq_elem(iter);
6173+ if (iter_svc->period >= cur->period) {
6174+ return;
6175+ } else if (iter_svc->cur_budget > 0) {
6176+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
6177+ }
6178+ }
6179+}
6180+*/
6181+
6182+//init the virtual cpu
6183+static int
6184+ss_vcpu_init(struct vcpu *vc) {
6185+ struct domain * const dom = vc->domain;
6186+ struct ss_dom *sdom = SS_DOM(dom);
6187+ struct ss_vcpu *svc;
6188+
6189+ /* Allocate per-VCPU info */
6190+ svc = xmalloc(struct ss_vcpu);
6191+ if (svc == NULL) {
6192+ return -1;
6193+ }
6194+ memset(svc, 0, sizeof (*svc));
6195+
6196+ INIT_LIST_HEAD(&svc->runq_elem);
6197+ svc->sdom = sdom;
6198+ svc->vcpu = vc;
6199+ svc->budget = is_idle_vcpu(vc)? SS_IDLE_PERIOD: sdom->budget;
6200+ svc->period = is_idle_vcpu(vc)? SS_IDLE_PERIOD: sdom->period;
6201+ svc->cur_budget = svc->budget;
6202+
6203+ svc->last_start_time = 0;
6204+ svc->burn_total = 0;
6205+ svc->next_time = 0;
6206+ svc->status = IDLE;
6207+ vc->sched_priv = svc;
6208+
6209+ /* Allocate per-PCPU info */
6210+ if (unlikely(!SS_PCPU(vc->processor))) {
6211+ if (ss_pcpu_init(vc->processor) != 0)
6212+ return -1;
6213+ }
6214+
6215+ SS_VCPU_CHECK(vc);
6216+
6217+ printk("\n# into %s, vcpu init: ", __func__);
6218+ ss_dump_vcpu(svc);
6219+
6220+ return 0;
6221+}
6222+
6223+//destory the vcpu
6224+static void
6225+ss_vcpu_destroy(struct vcpu *vc) {
6226+ struct ss_vcpu * const svc = SS_VCPU(vc);
6227+ struct ss_dom * const sdom = svc->sdom;
6228+
6229+ printk("\n# into %s, vcpu destroy: ", __func__);
6230+ ss_dump_vcpu(svc);
6231+
6232+ BUG_ON(sdom == NULL);
6233+ BUG_ON(!list_empty(&svc->runq_elem));
6234+
6235+ xfree(svc);
6236+}
6237+
6238+//sleep the vcpu
6239+static void
6240+ss_vcpu_sleep(struct vcpu *vc) {
6241+ struct ss_vcpu * const svc = SS_VCPU(vc);
6242+
6243+/*
6244+ if (vc->domain->domain_id != 0) {
6245+ printk("\n# into %s: now %lu, sleep vcpu: \n", __func__, NOW());
6246+ ss_dump_vcpu(svc);
6247+ }
6248+*/
6249+ BUG_ON(is_idle_vcpu(vc));
6250+
6251+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
6252+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
6253+ } else if (__vcpu_on_runq(svc)) {
6254+ //BUG_ON(svc->status == ACTIVE);
6255+ __runq_remove(svc);
6256+ }
6257+}
6258+
6259+//wake up the vcpu, insert it into runq, raise a softirq
6260+static void
6261+ss_vcpu_wake(struct vcpu *vc) {
6262+ struct ss_vcpu * const svc = SS_VCPU(vc);
6263+ const unsigned int cpu = vc->processor;
6264+
6265+ BUG_ON(is_idle_vcpu(vc));
6266+
6267+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
6268+ //printk("\n# why wake up running? migration?\n");
6269+ return;
6270+ }
6271+ if (unlikely(__vcpu_on_runq(svc))) {
6272+ //printk("\n# why wake up on runq ones? migration?\n");
6273+ return;
6274+ }
6275+
6276+/*
6277+ if (smp_processor_id() == 1) {
6278+ printk("%s, domain %d, now %lu\n", __func__, vc->domain->domain_id, NOW()/1000000);
6279+ }
6280+*/
6281+ __runq_insert(cpu, svc);
6282+ //if (svc->period < SS_CUR(cpu)->period)
6283+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
6284+}
6285+
6286+//used for record data, for overhead measurement
6287+static void
6288+ss_start_timer(void * temp) {
6289+ start_flag = 1;
6290+}
6291+
6292+//adjust the domain's budget & period, also used to trigger the record
6293+static int
6294+ss_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
6295+ struct ss_dom * const sdom = SS_DOM(d);
6296+ unsigned long flags;
6297+ struct ss_vcpu *svc = SS_VCPU(d->vcpu[0]);
6298+
6299+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
6300+ op->u.ss.budget = sdom->budget;
6301+ op->u.ss.period = sdom->period;
6302+ //ss_dump_vcpu(svc);
6303+ } else {
6304+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
6305+
6306+ spin_lock_irqsave(&ss_priv.lock, flags);
6307+ if (op->u.ss.budget != 0) {
6308+ sdom->budget = op->u.ss.budget;
6309+ svc->budget = op->u.ss.budget;
6310+ }
6311+ if (op->u.ss.period != 0) {
6312+ sdom->period = op->u.ss.period;
6313+ svc->period = op->u.ss.period;
6314+ }
6315+ svc->cur_budget = svc->budget;
6316+ spin_unlock_irqrestore(&ss_priv.lock, flags);
6317+
6318+ if (svc->vcpu->domain->domain_id == 0) {
6319+ printk("into %s, start to record now!\n", __func__);
6320+ init_timer(&start_timer, ss_start_timer, (void *) (unsigned int) 1, 1);
6321+ set_timer(&start_timer, NOW() + MILLISECS(10000));
6322+ }
6323+
6324+ //ss_dump_vcpu(svc);
6325+ }
6326+
6327+ return 0;
6328+}
6329+
6330+//init a dom
6331+static int
6332+ss_dom_init(struct domain *dom) {
6333+ struct ss_dom *sdom;
6334+
6335+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
6336+
6337+ if (is_idle_domain(dom)) {
6338+ printk("\t# init an idle domain\n");
6339+ return 0;
6340+ }
6341+
6342+ sdom = xmalloc(struct ss_dom);
6343+ if (sdom == NULL)
6344+ return -ENOMEM;
6345+ memset(sdom, 0, sizeof (*sdom));
6346+
6347+ /* Initialize budget and period */
6348+ sdom->dom = dom;
6349+
6350+ switch(dom->domain_id) {
6351+ case 32767:
6352+ sdom->budget = SS_IDLE_PERIOD;
6353+ sdom->period = SS_IDLE_PERIOD;
6354+ break;
6355+ case 0:
6356+ sdom->budget = SS_DOM_0_PERIOD;
6357+ sdom->period = SS_DOM_0_PERIOD;
6358+ break;
6359+ default:
6360+ sdom->budget = SS_DOM_BUDGET;
6361+ sdom->period = SS_DOM_PERIOD;
6362+ break;
6363+ }
6364+
6365+ dom->sched_priv = sdom;
6366+
6367+ return 0;
6368+}
6369+
6370+//destory a domain
6371+static void
6372+ss_dom_destroy(struct domain *dom) {
6373+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
6374+ xfree(SS_DOM(dom));
6375+}
6376+
6377+//ticked by pcpu tick in pcpu.
6378+static void
6379+ss_tick(void *_cpu) {
6380+ unsigned int cpu = (unsigned long) _cpu;
6381+ struct ss_pcpu *spc = SS_PCPU(cpu);
6382+
6383+ BUG_ON(current->processor != cpu);
6384+
6385+ if (check_cpu_for_repl(cpu)) {
6386+// check_runq_for_interrupt(cpu);
6387+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
6388+ }
6389+
6390+ if (ss_cpu_pick(current) != cpu) {
6391+ set_bit(_VPF_migrating, &current->pause_flags);
6392+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
6393+ }
6394+
6395+ set_timer(&spc->ticker, NOW() + BUDGET(1));
6396+}
6397+
6398+// most important function, called every budget time
6399+static struct task_slice
6400+ss_schedule(s_time_t now) {
6401+ const int cpu = smp_processor_id();
6402+ struct list_head *runq = RUNQ(cpu);
6403+ struct ss_vcpu *scurr = SS_VCPU(current);
6404+ struct ss_vcpu *snext;
6405+ struct task_slice ret;
6406+ int re_amount;
6407+
6408+ SS_VCPU_CHECK(current);
6409+
6410+// for record
6411+ if (smp_processor_id() == 1 && start_flag == 1) {
6412+ if(is_idle_vcpu(scurr->vcpu)) res[idx].curr = 10;
6413+ else res[idx].curr = scurr->vcpu->domain->domain_id;
6414+ res[idx].enter_base = NOW();
6415+ res[idx].leave_base = NOW();
6416+ res[idx].enter = NOW();
6417+ }
6418+
6419+ if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
6420+ //if (!is_idle_vcpu(scurr->vcpu)) {
6421+ burn_budgets(scurr, now);
6422+ }
6423+
6424+ if (vcpu_runnable(current)) {
6425+ __runq_insert(cpu, scurr);
6426+ } else {
6427+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
6428+ }
6429+
6430+ snext = __runq_pick(cpu);
6431+
6432+ __runq_remove(snext);
6433+
6434+//context switch do happen!, and snext is not an idle vcpu
6435+ if (cpu == 1 && snext != scurr) {
6436+ //if (snext != scurr) {
6437+ //for the scurr:
6438+ //if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
6439+ if (!is_idle_vcpu(scurr->vcpu)) {
6440+ BUG_ON(scurr->status != ACTIVE);
6441+ BUG_ON(scurr->next_time == 0);
6442+ scurr->status = IDLE;
6443+ re_amount = scurr->burn_total;
6444+ scurr->burn_total = 0;
6445+ //printk("\n# into %s, change status to IDLE, decide repl amount here! now is %lu, for vcpu[%d, %d], re_amount is: %d, re_time is %lu\n",
6446+ // __func__, NOW(), scurr->vcpu->domain->domain_id, scurr->vcpu->vcpu_id, re_amount, scurr->next_time);
6447+ ss_repq_insert(cpu, scurr, re_amount);
6448+ }
6449+
6450+ //for the snext:
6451+ //if (!is_idle_vcpu(snext->vcpu) && snext->vcpu->domain->domain_id != 0) {
6452+ if (!is_idle_vcpu(snext->vcpu)) {
6453+ if (snext->status == IDLE) {
6454+ BUG_ON(snext->next_time != 0);
6455+ snext->status = ACTIVE;
6456+ snext->next_time = NOW() + BUDGET(snext->period);
6457+ //printk("\n# into %s, change status to ACTIVE, decide repl time here! now is %lu, for vcpu [%d, %d], re_time is %lu\n",
6458+ // __func__, NOW(), snext->vcpu->domain->domain_id, snext->vcpu->vcpu_id, snext->next_time);
6459+ }
6460+ }
6461+
6462+ //scan the whole runq
6463+ ss_scan_runq(cpu, snext);
6464+ }
6465+
6466+ if (cpu == 1 && snext->vcpu->domain->domain_id != 0) {
6467+ snext->last_start_time = NOW();
6468+ }
6469+
6470+ ret.time = (is_idle_vcpu(snext->vcpu) ? -1 : BUDGET(1));
6471+ //ret.time = BUDGET(1);
6472+ ret.task = snext->vcpu;
6473+
6474+ SS_VCPU_CHECK(ret.task);
6475+
6476+ BUG_ON(!vcpu_runnable(snext->vcpu));
6477+ //printk("now is %lu\n", now);
6478+
6479+// for record
6480+ if (smp_processor_id() == 1 && start_flag == 1) {
6481+ if(is_idle_vcpu(snext->vcpu)) res[idx].next = 10;
6482+ else res[idx].next = snext->vcpu->domain->domain_id;
6483+ res[idx].leave = NOW();
6484+ if(idx++ >= RECORD) {
6485+ ss_dump_record();
6486+ }
6487+ }
6488+
6489+ return ret;
6490+}
6491+
6492+//init the global data
6493+static void
6494+ss_init(void) {
6495+ printk("\n# into %s\n", __func__);
6496+ spin_lock_init(&ss_priv.lock);
6497+ ss_priv.ncpus = 0;
6498+}
6499+
6500+/* Tickers cannot be kicked until SMP subsystem is alive. */
6501+static __init int
6502+ss_start_tickers(void) {
6503+ struct ss_pcpu *spc;
6504+ unsigned int cpu;
6505+
6506+ printk("\n# into %s, start all tickers right now\n", __func__);
6507+
6508+ if (ss_priv.ncpus == 0)
6509+ return 0;
6510+
6511+ for_each_online_cpu(cpu) {
6512+ spc = SS_PCPU(cpu);
6513+ set_timer(&spc->ticker, NOW() + BUDGET(1));
6514+ }
6515+
6516+ return 0;
6517+}
6518+__initcall(ss_start_tickers);
6519+
6520+static void ss_tick_suspend(void) {
6521+ struct ss_pcpu *spc;
6522+
6523+ printk("\n# into %s, why is this called?\n", __func__);
6524+
6525+ spc = SS_PCPU(smp_processor_id());
6526+
6527+ stop_timer(&spc->ticker);
6528+}
6529+
6530+static void ss_tick_resume(void) {
6531+ struct ss_pcpu *spc;
6532+ uint64_t now = NOW();
6533+
6534+ printk("\n# into %s, why is this called?\n", __func__);
6535+
6536+ spc = SS_PCPU(smp_processor_id());
6537+
6538+ set_timer(&spc->ticker, now + BUDGET(1));
6539+}
6540+
6541+const struct scheduler sched_ss_def = {
6542+ .name = "Sporadic Server Scheduler",
6543+ .opt_name = "ss",
6544+ .sched_id = XEN_SCHEDULER_SS,
6545+
6546+ .init_domain = ss_dom_init,
6547+ .destroy_domain = ss_dom_destroy,
6548+
6549+ .init_vcpu = ss_vcpu_init,
6550+ .destroy_vcpu = ss_vcpu_destroy,
6551+
6552+ .init = ss_init,
6553+
6554+ .pick_cpu = ss_cpu_pick,
6555+
6556+ .tick_suspend = ss_tick_suspend,
6557+ .tick_resume = ss_tick_resume,
6558+
6559+ .do_schedule = ss_schedule,
6560+
6561+ .sleep = ss_vcpu_sleep,
6562+ .wake = ss_vcpu_wake,
6563+
6564+ .adjust = ss_dom_cntl,
6565+
6566+ .dump_cpu_state = ss_dump_pcpu,
6567+ .dump_settings = ss_dump,
6568+};
6569diff -ubrN xen/xen-4.0.1/xen/common/schedule.c xen-4.0.1/xen/common/schedule.c
6570--- xen/xen-4.0.1/xen/common/schedule.c 2010-08-25 04:22:12.000000000 -0600
6571+++ xen-4.0.1/xen/common/schedule.c 2011-04-24 15:43:52.000000000 -0600
6572@@ -34,8 +34,8 @@
6573 #include <public/sched.h>
6574 #include <xsm/xsm.h>
6575
6576-/* opt_sched: scheduler - default to credit */
6577-static char __initdata opt_sched[10] = "credit";
6578+/* opt_sched: scheduler - default to rt */
6579+static char __initdata opt_sched[10] = "rt";
6580 string_param("sched", opt_sched);
6581
6582 /* if sched_smt_power_savings is set,
6583@@ -56,12 +56,32 @@
6584
6585 extern const struct scheduler sched_sedf_def;
6586 extern const struct scheduler sched_credit_def;
6587+// added by Sisu Xi
6588+extern const struct scheduler sched_rt_def;
6589 static const struct scheduler *__initdata schedulers[] = {
6590 &sched_sedf_def,
6591 &sched_credit_def,
6592+ &sched_rt_def,
6593 NULL
6594 };
6595
6596+//for record
6597+#define RECORD 15000
6598+struct record_elem{
6599+ int processor; // 1: idle to busy, 2: busy to idle, 3: busy to busy(dif), 4: same
6600+ int curr;
6601+ int next;
6602+ s_time_t dur_sub;
6603+ s_time_t dur;
6604+};
6605+
6606+//int sched_idx;
6607+int sched_start_flag = 0; // to record data
6608+struct timer sched_start_timer;
6609+s_time_t temp_dur_sub;
6610+s_time_t temp_dur;
6611+//finish record
6612+
6613 static struct scheduler __read_mostly ops;
6614
6615 #define SCHED_OP(fn, ...) \
6616@@ -777,6 +797,37 @@
6617 return ops.sched_id;
6618 }
6619
6620+//for record
6621+static void
6622+record_finish_timer(void * temp) {
6623+// int i = 0;
6624+
6625+ sched_start_flag = 0;
6626+/*
6627+ for (i = 0; i < sched_idx; i++) {
6628+ printk("%d %5d %5d %7lu %7lu\n", sched_res[i].processor, sched_res[i].curr, sched_res[i].next, sched_res[i].dur_sub, sched_res[i].dur);
6629+ }
6630+
6631+ for (i = 0; i < RECORD; i++) {
6632+ sched_res[i].processor = 0;
6633+ sched_res[i].curr = 0;
6634+ sched_res[i].next = 0;
6635+ sched_res[i].dur_sub = 0;
6636+ sched_res[i].dur = 0;
6637+ }
6638+
6639+ sched_idx = 0;
6640+*/
6641+}
6642+
6643+static void
6644+record_start_timer(void * temp) {
6645+ sched_start_flag = 1;
6646+ init_timer(&sched_start_timer, record_finish_timer, (void *) (unsigned int) 1, 1);
6647+ set_timer(&sched_start_timer, NOW() + MILLISECS(10000));
6648+}
6649+//finish recording
6650+
6651 /* Adjust scheduling parameter for a given domain. */
6652 long sched_adjust(struct domain *d, struct xen_domctl_scheduler_op *op)
6653 {
6654@@ -810,9 +861,17 @@
6655 if ( d == current->domain )
6656 vcpu_schedule_lock_irq(current);
6657
6658- if ( (ret = SCHED_OP(adjust, d, op)) == 0 )
6659+ if ( (ret = SCHED_OP(adjust, d, op)) >= 0 )
6660 TRACE_1D(TRC_SCHED_ADJDOM, d->domain_id);
6661
6662+//trigger recording!!
6663+ if (ret == 1) {
6664+ printk("start!\n");
6665+ init_timer(&sched_start_timer, record_start_timer, (void *) (unsigned int) 1, 1);
6666+ set_timer(&sched_start_timer, NOW() + MILLISECS(5000));
6667+ ret = 0;
6668+ }
6669+
6670 if ( d == current->domain )
6671 vcpu_schedule_unlock_irq(current);
6672
6673@@ -860,6 +919,11 @@
6674 struct schedule_data *sd;
6675 struct task_slice next_slice;
6676
6677+//record
6678+ if (prev->processor == 1 && sched_start_flag == 1) {
6679+ temp_dur = now;
6680+ }
6681+
6682 ASSERT(!in_irq());
6683 ASSERT(this_cpu(mc_state).flags == 0);
6684
6685@@ -871,8 +935,16 @@
6686
6687 stop_timer(&sd->s_timer);
6688
6689+//record
6690+ if (prev->processor == 1 && sched_start_flag == 1) {
6691+ temp_dur_sub = NOW();
6692+ }
6693 /* get policy-specific decision on scheduling... */
6694 next_slice = ops.do_schedule(now);
6695+ if (prev->processor == 1 && sched_start_flag == 1) {
6696+ printk("%7lu ", NOW() - temp_dur_sub);
6697+ //sched_res[sched_idx].dur_sub = NOW() - temp_dur_sub;
6698+ }
6699
6700 next = next_slice.task;
6701
6702@@ -881,10 +953,19 @@
6703 if ( next_slice.time >= 0 ) /* -ve means no limit */
6704 set_timer(&sd->s_timer, now + next_slice.time);
6705
6706+ if (prev->processor == 1 && sched_start_flag == 1) {
6707+ printk("%7d %7d %13lu ", prev->domain->domain_id, next->domain->domain_id, NOW());
6708+ }
6709+
6710 if ( unlikely(prev == next) )
6711 {
6712 spin_unlock_irq(&sd->schedule_lock);
6713 trace_continue_running(next);
6714+ if (prev->processor == 1 && sched_start_flag == 1) {
6715+ printk("%13lu\n", NOW());
6716+ //sched_res[sched_idx].dur = NOW() - temp_dur;
6717+ //sched_idx++;
6718+ }
6719 return continue_running(prev);
6720 }
6721
6722@@ -931,7 +1012,11 @@
6723 update_vcpu_system_time(next);
6724 vcpu_periodic_timer_work(next);
6725
6726- context_switch(prev, next);
6727+ if (prev->processor == 1) {
6728+ context_switch(sched_start_flag, prev, next);
6729+ } else {
6730+ context_switch(0, prev, next);
6731+ }
6732 }
6733
6734 void context_saved(struct vcpu *prev)
6735diff -ubrN xen/xen-4.0.1/xen/drivers/char/console.c xen-4.0.1/xen/drivers/char/console.c
6736--- xen/xen-4.0.1/xen/drivers/char/console.c 2010-08-25 04:22:12.000000000 -0600
6737+++ xen-4.0.1/xen/drivers/char/console.c 2011-01-15 10:57:46.000000000 -0700
6738@@ -63,7 +63,9 @@
6739 static uint32_t __initdata opt_conring_size;
6740 size_param("conring_size", opt_conring_size);
6741
6742-#define _CONRING_SIZE 16384
6743+//#define _CONRING_SIZE 16384
6744+//Sisu xi
6745+#define _CONRING_SIZE 1638400
6746 #define CONRING_IDX_MASK(i) ((i)&(conring_size-1))
6747 static char __initdata _conring[_CONRING_SIZE];
6748 static char *__read_mostly conring = _conring;
6749diff -ubrN xen/xen-4.0.1/xen/include/public/domctl.h xen-4.0.1/xen/include/public/domctl.h
6750--- xen/xen-4.0.1/xen/include/public/domctl.h 2010-08-25 04:22:14.000000000 -0600
6751+++ xen-4.0.1/xen/include/public/domctl.h 2011-04-24 15:51:25.000000000 -0600
6752@@ -303,6 +303,9 @@
6753 /* Scheduler types. */
6754 #define XEN_SCHEDULER_SEDF 4
6755 #define XEN_SCHEDULER_CREDIT 5
6756+// added by Sisu Xi
6757+#define XEN_SCHEDULER_RT 7
6758+
6759 /* Set or get info? */
6760 #define XEN_DOMCTL_SCHEDOP_putinfo 0
6761 #define XEN_DOMCTL_SCHEDOP_getinfo 1
6762@@ -321,6 +324,12 @@
6763 uint16_t weight;
6764 uint16_t cap;
6765 } credit;
6766+ // added by Sisu Xi
6767+ struct xen_domctl_sched_rt {
6768+ uint16_t budget;
6769+ uint16_t period;
6770+ uint16_t level;
6771+ } rt;
6772 } u;
6773 };
6774 typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;
6775diff -ubrN xen/xen-4.0.1/xen/include/xen/sched.h xen-4.0.1/xen/include/xen/sched.h
6776--- xen/xen-4.0.1/xen/include/xen/sched.h 2010-08-25 04:22:14.000000000 -0600
6777+++ xen-4.0.1/xen/include/xen/sched.h 2011-01-18 00:58:43.000000000 -0700
6778@@ -492,6 +492,7 @@
6779 * sync_vcpu_execstate() will switch and commit @prev's state.
6780 */
6781 void context_switch(
6782+ int flag,
6783 struct vcpu *prev,
6784 struct vcpu *next);
6785
diff --git a/recipes-extended/xen/xen-rt_4.0.1.bb b/recipes-extended/xen/xen-rt_4.0.1.bb
deleted file mode 100644
index 3422ab3c..00000000
--- a/recipes-extended/xen/xen-rt_4.0.1.bb
+++ /dev/null
@@ -1,25 +0,0 @@
1# Xen official download
2# Using libxl instead of xend. No longer require Python
3
4require xen.inc
5
6SRCREV = "3cf61880403b4e484539596a95937cc066243388"
7
8SRC_URI = "http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz \
9 git://xenbits.xensource.com/qemu-xen-4.1-testing.git \
10 file://ioemu-cross-gl-check.patch \
11 file://rt-xen_0.3_${PV}.patch"
12
13# file://allow_disable_xend.patch"
14
15SRC_URI[md5sum] = "d197afad975ab2396a67323d57388c27"
16SRC_URI[sha256sum] = "6e6d1d29400db93cb8095e034138aa8748b1bd4cffb4d3fd07af4ba15c918873"
17
18S = "${WORKDIR}/xen-${PV}"
19
20do_compile_prepend() {
21
22 export XEN_DISABLE_XEND=1
23
24}
25