[prev in list] [next in list] [prev in thread] [next in thread]
List: xen-cvs
Subject: [Xen-changelog] Extended sedf scheduler (weighted extraqueues),
From: BitKeeper Bot <riel () surriel ! com>
Date: 2005-02-17 18:50:24
Message-ID: E1DVCbt-0005Cp-0V () moria ! surriel ! com
[Download RAW message or body]
ChangeSet 1.1159.170.104, 2005/02/17 18:50:24+00:00, sd386@font.cl.cam.ac.uk
Extended sedf scheduler (weighted extraqueues), added enhanced scheduling histogramm
common/sched_sedf.c | 258 +++++++++++++++++++++++++++++++++++++++----------
common/schedule.c | 92 ++++++++++++++++-
include/xen/sched-if.h | 11 +-
3 files changed, 302 insertions(+), 59 deletions(-)
diff -Nru a/xen/common/sched_sedf.c b/xen/common/sched_sedf.c
--- a/xen/common/sched_sedf.c 2005-05-09 14:04:09 -04:00
+++ b/xen/common/sched_sedf.c 2005-05-09 14:04:09 -04:00
@@ -13,14 +13,33 @@
#include <xen/time.h>
#include <xen/slab.h>
+//#include <xen/adv_sched_hist.h>
+
#define SEDFLEVEL 2
#define PRINT(_f, _a...) \
if ((_f)<=SEDFLEVEL) printk(_a );
+//various ways of unblocking domains
+#define UNBLOCK_ISOCHRONOUS_EDF 1
+#define UNBLOCK_EDF 2
+#define UNBLOCK_ATROPOS 3
+#define UNBLOCK_SHORT_RESUME 4
+#define UNBLOCK_BURST 5
+
+#define UNBLOCK UNBLOCK_BURST
+
+//various ways of treating extra-time
+#define EXTRA_OFF 1
+#define EXTRA_ROUNDR 2
+#define EXTRA_SLICE_WEIGHT 3
+#define EXTRA_BLOCK_WEIGHT 4
+
+#define EXTRA EXTRA_OFF
+
+
/*
TODO:
TESTING!
- implement stylish features!
tracing instead of PRINTs
*/
@@ -29,15 +48,16 @@
#define EXTRA_NONE (0)
#define EXTRA_AWARE (1)
#define EXTRA_RUNNING (2)
-#define EXTRA_QUANTUM (MICROSECS(1000))
+#define EXTRA_QUANTUM (MICROSECS(500))
#define WEIGHT_PERIOD (MILLISECS(100))
#define WEIGHT_SAFETY (MILLISECS(5))
+
struct sedf_dom_info
{
struct domain *owner;
struct list_head list;
- struct list_head extralist;
+ struct list_head extralist[2];
//Parameters for EDF
s_time_t period; //=(relative deadline)
@@ -50,14 +70,17 @@
s_time_t latency;
//extra-time status of domain
short extra;
- //weights for "Scheduling for Beginners/ Lazy/ etc."
+ //weights for "Scheduling for beginners/ lazy/ etc."
short weight;
//Bookkeeping
s_time_t absdead;
s_time_t sched_start;
s_time_t cputime;
- s_time_t absblock;
+ s_time_t absblock;
+ s_time_t absunblock; //time the domain unblocked, used by burst mode to determine \
unblocking intervals + int score[2]; //scores for {util, block penalty}-weighted \
extratime distribution + s_time_t short_block_lost_tot;
//Statistics
s_time_t block_time_tot;
@@ -109,6 +132,37 @@
return (((EXTRALIST(d))->next != NULL) && (EXTRALIST(d)->next != EXTRALIST(d)));
}
+/* adds a domain to the queue of processes which are aware of extra time. List is \
sorted by score, + where a lower score means higher priority for an extra slice. It \
also updates the score, by simply subtracting + a fixed value from each entry, in \
order to avoid overflow. The algorithm works by simply charging each domain + that \
recieved extratime with an inverse of its weight. + */
+static inline void extraq_add_sort_update(struct domain *d, unsigned long sub) {
+ struct list_head *cur;
+ struct sedf_dom_info *curinf;
+
+ PRINT(3,"Adding domain %i (score= %llu) to extraq\n",d->id,DOM_INFO(d)->score);
+ //iterate through all elements to find our "hole" and on our way update all the \
other scores + list_for_each(cur,EXTRAQ(d->processor)){
+ curinf = list_entry(cur,struct sedf_dom_info,extralist);
+ curinf->score -= sub;
+ if (DOM_INFO(d)->score < curinf->score)
+ break;
+ else
+ PRINT(4,"\tbehind domain %i (score= %llu)\n",curinf->owner->id,curinf->score);
+ }
+ //cur now contains the element, before which we'll enqueue
+ PRINT(3,"\tlist_add to %x\n",cur->prev);
+ list_add(EXTRALIST(d),cur->prev);
+
+ //continue updating the extraq
+ if ((cur != EXTRAQ(d->processor)) && sub)
+ for (cur = cur->next; cur != EXTRAQ(d->processor); cur = cur-> next) {
+ curinf = list_entry(cur,struct sedf_dom_info,extralist);
+ curinf->score -= sub;
+ PRINT(4,"\tupdating domain %i (score= %llu)\n",curinf->owner->id,curinf->score);
+ }
+}
static inline void extraq_check(struct domain *d) {
if (extraq_on(d)) {
PRINT(2,"Dom %i is on extraQ\n",d->id);
@@ -120,11 +174,10 @@
PRINT(2,"Dom %i is NOT on extraQ\n",d->id);
if (DOM_INFO(d)->extra != EXTRA_NONE) {
PRINT(2,"Added dom %i to extraQ\n",d->id);
- extraq_add_tail(d);
+ extraq_add_sort_update(d, 0);
}
}
}
-
static inline void __del_from_queue(struct domain *d)
{
struct list_head *list = LIST(d);
@@ -277,29 +330,45 @@
int cpu = current->processor;
struct list_head *runq = RUNQ(cpu);
struct list_head *waitq = WAITQ(cpu);
+ #if (EXTRA > EXTRA_OFF)
struct list_head *extraq = EXTRAQ(cpu);
+ #endif
struct list_head *cur,*tmp;
struct sedf_dom_info *curinf;
task_slice_t ret;
-
+ #if (EXTRA == EXTRA_SLICE_WEIGHT)
+ unsigned long oldscore;
+ #endif
//idle tasks don't need any of the following stuf
if (is_idle_task(inf->owner))
goto check_waitq; //idle task doesn't get scheduled on the runq
-
+
+ #if (EXTRA > EXTRA_OFF)
if (unlikely(inf->extra == EXTRA_RUNNING)) {
//special treatment of domains running in extra time
inf->extra = EXTRA_AWARE;
inf->cputime=0;
inf->extra_time_tot += now - inf->sched_start;
- extraq_del(current); //remove extradomain from head of the queue
- if (domain_runnable(inf->owner))
- extraq_add_tail(current); //and add to the tail if it is runnable => round-robin
+ extraq_del(current); //remove extradomain from head of the queue
+
+ #if (EXTRA == EXTRA_ROUNDR)
+ if (domain_runnable(current))
+ extraq_add_tail(current); //and add to the tail if it is runnable => \
round-robin + #elif (EXTRA == EXTRA_SLICE_WEIGHT)
+ oldscore = inf->score; //update the score
+ inf->score = (inf->period << 10) / inf->slice; //use fixed point arithmetic with \
10 bits +
+ if (domain_runnable(current))
+ extraq_add_sort_update(current, oldscore); //add according to score: weighted \
round robin + #endif
else
- __del_from_queue(inf->owner); //if domain blocked in extratime remove it from \
waitq(/runq) as well + __del_from_queue(inf->owner); //if domain blocked in \
extratime remove it from waitq(/runq) as well }
- else {
+ else
+ #endif
+ {
//current domain is running in real time mode
//update the domains cputime
inf->cputime += now - inf->sched_start;
@@ -315,13 +384,18 @@
inf->cputime -= inf->slice;
if (inf->period < inf->period_orig) {
- //this domain runs in latency scaling mode
- inf->period *= 2;
- inf->slice *= 2;
- if ((inf->period > inf->period_orig) || (inf->slice > inf->slice_orig)) {
- //now switch back to standard timing
- inf->period = inf->period_orig;
- inf->slice = inf->slice_orig;
+ //this domain runs in latency scaling or burst mode
+ #if (UNBLOCK == UNBLOCK_BURST)
+ if (now - inf->absunblock >= 2 * inf->period)
+ #endif
+ {
+ inf->period *= 2;
+ inf->slice *= 2;
+ if ((inf->period > inf->period_orig) || (inf->slice > inf->slice_orig)) {
+ //now switch back to standard timing
+ inf->period = inf->period_orig;
+ inf->slice = inf->slice_orig;
+ }
}
}
inf->absdead += inf->period; //set next deadline
@@ -333,9 +407,11 @@
__add_to_waitqueue_sort(inf->owner);
else {
//we have a blocked realtime task
- inf->absblock=now;
+ inf->absblock = now;
+ #if (EXTRA > EXTRA_OFF)
if (inf->extra == EXTRA_AWARE)
extraq_del(inf->owner); //remove a blocked domain from the extraq aswell
+ #endif
}
}
check_waitq:
@@ -393,13 +469,16 @@
if (!list_empty(waitq)) {
waitinf = list_entry(waitq->next,struct sedf_dom_info,list);
//we could not find any suitable domain => look for domains that are aware of \
extratime + #if (EXTRA > EXTRA_OFF)
if (!list_empty(extraq) && (PERIOD_BEGIN(waitinf) - now >= EXTRA_QUANTUM)) {
runinf = list_entry(extraq->next,struct sedf_dom_info,extralist);
runinf->extra = EXTRA_RUNNING;
ret.task = runinf->owner;
ret.time = EXTRA_QUANTUM;
}
- else {
+ else
+ #endif
+ {
//we have an empty run- and extraqueue or too less time => idle task!
ret.task = IDLETASK(cpu);
ret.time = PERIOD_BEGIN(waitinf) - now;
@@ -420,13 +499,19 @@
static void sedf_sleep(struct domain *d) {
PRINT(2,"sedf_sleep was called, domain-id %i\n",d->id);
- if ( test_bit(DF_RUNNING, &d->flags) )
+ if ( test_bit(DF_RUNNING, &d->flags) ) {
+#ifdef ADV_SCHED_HISTO
+ adv_sched_hist_start(d->processor);
+#endif
cpu_raise_softirq(d->processor, SCHEDULE_SOFTIRQ);
+ }
else {
_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic