direct-io.hg
changeset 4729:93a7ffae49b3
bitkeeper revision 1.1346.1.3 (42764c17j3s2X1M-F05_xvwcUN6KPA)
Port of the sedf scheduler to unstable tree.
Signed-off: Stephan.Diestelhorst@{cl.cam.ac.uk , inf.tu-dresden.de}
Port of the sedf scheduler to unstable tree.
Signed-off: Stephan.Diestelhorst@{cl.cam.ac.uk , inf.tu-dresden.de}
author | sd386@font.cl.cam.ac.uk |
---|---|
date | Mon May 02 15:49:43 2005 +0000 (2005-05-02) |
parents | 214ccc480724 |
children | e7c55a144530 |
files | xen/common/sched_sedf.c xen/common/schedule.c |
line diff
1.1 --- a/xen/common/sched_sedf.c Fri Apr 22 17:05:34 2005 +0000 1.2 +++ b/xen/common/sched_sedf.c Mon May 02 15:49:43 2005 +0000 1.3 @@ -1,4 +1,4 @@ 1.4 -/**************************************************************************** 1.5 +/******************************************************************************* 1.6 * Simple EDF scheduler for xen 1.7 * 1.8 * by Stephan Diestelhorst (C) 2004 Cambridge University 1.9 @@ -20,8 +20,13 @@ 1.10 #define PRINT(_f, _a...) \ 1.11 if ((_f)<=SEDFLEVEL) printk(_a ); 1.12 1.13 -#ifdef DEBUG 1.14 +#ifndef NDEBUG 1.15 #define SEDF_STATS 1.16 + #define CHECK(_p) if ( !(_p) ) \ 1.17 + { printk("Check '%s' failed, line %d, file %s\n", #_p , __LINE__,\ 1.18 + __FILE__);} 1.19 +#else 1.20 + #define CHECK(_p) ((void)0) 1.21 #endif 1.22 1.23 /*various ways of unblocking domains*/ 1.24 @@ -48,14 +53,16 @@ if ((_f)<=SEDFLEVEL) printk(_a ); 1.25 #define EXTRA_WANT_PEN_Q (8) 1.26 #define EXTRA_PEN_Q (0) 1.27 #define EXTRA_UTIL_Q (1) 1.28 - 1.29 -#define extra_runs(inf) ((inf->extra) & 6) 1.30 -#define extra_get_cur_q(inf) (((inf->extra & 6) >> 1)-1) 1.31 +#define SEDF_ASLEEP (16) 1.32 1.33 #define EXTRA_QUANTUM (MICROSECS(500)) 1.34 #define WEIGHT_PERIOD (MILLISECS(100)) 1.35 #define WEIGHT_SAFETY (MILLISECS(5)) 1.36 1.37 +#define IMPLY(a, b) (!(a) || (b)) 1.38 +#define EQ(a, b) ((!!(a)) == (!!(b))) 1.39 + 1.40 + 1.41 struct sedf_dom_info { 1.42 struct domain *domain; 1.43 }; 1.44 @@ -75,12 +82,12 @@ struct sedf_edom_info 1.45 s_time_t slice_orig; 1.46 s_time_t latency; 1.47 1.48 - /*extra-time status of domain*/ 1.49 - short extra; 1.50 + /*status of domain*/ 1.51 + int status; 1.52 /*weights for "Scheduling for beginners/ lazy/ etc." ;)*/ 1.53 short weight; 1.54 - 1.55 - /*Bookkeeping*/ 1.56 + short extraweight; 1.57 + /*Bookkeeping*/ 1.58 s_time_t deadl_abs; 1.59 s_time_t sched_start_abs; 1.60 s_time_t cputime; 1.61 @@ -127,6 +134,11 @@ struct sedf_cpu_info { 1.62 #define MIN(x,y) (((x)<(y))?(x):(y)) 1.63 #define DIV_UP(x,y) (((x) + (y) - 1) / y) 1.64 1.65 +#define extra_runs(inf) ((inf->status) & 6) 1.66 +#define extra_get_cur_q(inf) (((inf->status & 6) >> 1)-1) 1.67 +#define sedf_runnable(edom) (!(EDOM_INFO(edom)->status & SEDF_ASLEEP)) 1.68 + 1.69 + 1.70 static void sedf_dump_cpu_state(int i); 1.71 1.72 static inline int extraq_on(struct exec_domain *d, int i) { 1.73 @@ -137,25 +149,24 @@ static inline int extraq_on(struct exec_ 1.74 static inline void extraq_add_head(struct exec_domain *d, int i) 1.75 { 1.76 list_add(EXTRALIST(d,i), EXTRAQ(d->processor,i)); 1.77 + ASSERT(extraq_on(d, i)); 1.78 } 1.79 1.80 static inline void extraq_add_tail(struct exec_domain *d, int i) 1.81 { 1.82 list_add_tail(EXTRALIST(d,i), EXTRAQ(d->processor,i)); 1.83 + ASSERT(extraq_on(d, i)); 1.84 } 1.85 1.86 static inline void extraq_del(struct exec_domain *d, int i) 1.87 { 1.88 struct list_head *list = EXTRALIST(d,i); 1.89 - /*if (!extraq_on(d,i)) { 1.90 - PRINT(0,"extraq_del: domain %i.%i is NOT on L%i extraq "\ 1.91 - "HALTING\n",d->domain->id, d->eid,i); 1.92 - sedf_dump_cpu_state(0);(*((int*)0))++; 1.93 - }*/ 1.94 + ASSERT(extraq_on(d,i)); 1.95 PRINT(3, "Removing domain %i.%i from L%i extraq\n", d->domain->id, 1.96 d->eid, i); 1.97 list_del(list); 1.98 list->next = NULL; 1.99 + ASSERT(!extraq_on(d, i)); 1.100 } 1.101 1.102 /* adds a domain to the queue of processes which are aware of extra time. List 1.103 @@ -168,11 +179,7 @@ static inline void extraq_add_sort_updat 1.104 struct list_head *cur; 1.105 struct sedf_edom_info *curinf; 1.106 1.107 - /*if (extraq_on(d,i)) { 1.108 - PRINT(0,"extraq_add_sort_update: domain %i.%i is already on "\ 1.109 - "L%i extraq! HALTING\n",d->domain->id, d->eid, i); 1.110 - sedf_dump_cpu_state(0);(*((int*)0))++; 1.111 - }*/ 1.112 + ASSERT(!extraq_on(d,i)); 1.113 PRINT(3, "Adding domain %i.%i (score= %i, short_pen= %lli) to L%i "\ 1.114 "extraq\n", d->domain->id, d->eid, EDOM_INFO(d)->score[i], 1.115 EDOM_INFO(d)->short_block_lost_tot, i); 1.116 @@ -203,11 +210,12 @@ static inline void extraq_add_sort_updat 1.117 curinf->exec_domain->domain->id, 1.118 curinf->exec_domain->eid, curinf->score[i]); 1.119 } 1.120 + ASSERT(extraq_on(d,i)); 1.121 } 1.122 static inline void extraq_check(struct exec_domain *d) { 1.123 if (extraq_on(d, EXTRA_UTIL_Q)) { 1.124 - PRINT(2,"Dom %i is on extraQ\n",d->domain->id, d->eid); 1.125 - if (!(EDOM_INFO(d)->extra & EXTRA_AWARE) && 1.126 + PRINT(2,"Dom %i.%i is on L1 extraQ\n",d->domain->id, d->eid); 1.127 + if (!(EDOM_INFO(d)->status & EXTRA_AWARE) && 1.128 !extra_runs(EDOM_INFO(d))) { 1.129 extraq_del(d, EXTRA_UTIL_Q); 1.130 PRINT(2,"Removed dom %i.%i from L1 extraQ\n", 1.131 @@ -216,10 +224,9 @@ static inline void extraq_check(struct e 1.132 } else { 1.133 PRINT(2,"Dom %i.%i is NOT on L1 extraQ\n",d->domain->id, 1.134 d->eid); 1.135 - if ((EDOM_INFO(d)->extra & EXTRA_AWARE) && domain_runnable(d)) 1.136 + if ((EDOM_INFO(d)->status & EXTRA_AWARE) && sedf_runnable(d)) 1.137 { 1.138 #if (EXTRA == EXTRA_ROUNDR) 1.139 - /*Favour domains which got short unblocked*/ 1.140 extraq_add_tail(d, EXTRA_UTIL_Q); 1.141 #elif (EXTRA == EXTRA_SLICE_WEIGHT || \ 1.142 EXTRA == EXTRA_BLOCK_WEIGHT) 1.143 @@ -232,39 +239,78 @@ static inline void extraq_check(struct e 1.144 } 1.145 } 1.146 } 1.147 + 1.148 +static inline void extraq_check_add_unblocked(struct exec_domain *d, 1.149 + int priority) { 1.150 + struct sedf_edom_info *inf = EDOM_INFO(d); 1.151 + if (inf->status & EXTRA_AWARE) 1.152 + #if (EXTRA == EXTRA_ROUNDR) 1.153 + if (priority) 1.154 + extraq_add_head(d,EXTRA_UTIL_Q); 1.155 + else 1.156 + extraq_add_tail(d,EXTRA_UTIL_Q); 1.157 + #elif (EXTRA == EXTRA_SLICE_WEIGHT \ 1.158 + || EXTRA == EXTRA_BLOCK_WEIGHT) 1.159 + /*put in on the weighted extraq, 1.160 + without updating any scores*/ 1.161 + extraq_add_sort_update(d, EXTRA_UTIL_Q, 0); 1.162 + #else 1.163 + ; 1.164 + #endif 1.165 +} 1.166 + 1.167 +static inline int __task_on_queue(struct exec_domain *d) { 1.168 + return (((LIST(d))->next != NULL) && (LIST(d)->next != LIST(d))); 1.169 +} 1.170 static inline void __del_from_queue(struct exec_domain *d) 1.171 { 1.172 struct list_head *list = LIST(d); 1.173 + ASSERT(__task_on_queue(d)); 1.174 PRINT(3,"Removing domain %i.%i (bop= %llu) from runq/waitq\n", d->domain->id, 1.175 d->eid, PERIOD_BEGIN(EDOM_INFO(d))); 1.176 list_del(list); 1.177 list->next = NULL; 1.178 + ASSERT(!__task_on_queue(d)); 1.179 } 1.180 1.181 +typedef int(*list_comparer)(struct list_head* el1, struct list_head* el2); 1.182 + 1.183 +static inline void list_insert_sort(struct list_head *list, 1.184 + struct list_head *element, list_comparer comp) { 1.185 + struct list_head *cur; 1.186 + /*iterate through all elements to find our "hole"*/ 1.187 + list_for_each(cur,list){ 1.188 + if (comp(element, cur) < 0) 1.189 + break; 1.190 + } 1.191 + /*cur now contains the element, before which we'll enqueue*/ 1.192 + PRINT(3,"\tlist_add to %x\n",cur->prev); 1.193 + list_add(element, cur->prev); 1.194 +} 1.195 +#define DOMAIN_COMPARER(name, field, comp1, comp2) \ 1.196 +int name##_comp(struct list_head* el1, struct list_head* el2) \ 1.197 +{ \ 1.198 + struct sedf_edom_info *d1, *d2; \ 1.199 + d1 = list_entry(el1,struct sedf_edom_info, field); \ 1.200 + d2 = list_entry(el2,struct sedf_edom_info, field); \ 1.201 + if ((comp1) == (comp2)) \ 1.202 + return 0; \ 1.203 + if ((comp1) < (comp2)) \ 1.204 + return -1; \ 1.205 + else \ 1.206 + return 1; \ 1.207 +} 1.208 /* adds a domain to the queue of processes which wait for the beginning of the 1.209 next period; this list is therefore sortet by this time, which is simply 1.210 absol. deadline - period 1.211 */ 1.212 +DOMAIN_COMPARER(waitq, list, PERIOD_BEGIN(d1), PERIOD_BEGIN(d2)) 1.213 static inline void __add_to_waitqueue_sort(struct exec_domain *d) { 1.214 - struct list_head *cur; 1.215 - struct sedf_edom_info *curinf; 1.216 - 1.217 + ASSERT(!__task_on_queue(d)); 1.218 PRINT(3,"Adding domain %i.%i (bop= %llu) to waitq\n", d->domain->id, 1.219 - d->eid, PERIOD_BEGIN(EDOM_INFO(d))); 1.220 - 1.221 - /*iterate through all elements to find our "hole"*/ 1.222 - list_for_each(cur, WAITQ(d->processor)){ 1.223 - curinf = list_entry(cur,struct sedf_edom_info,list); 1.224 - if (PERIOD_BEGIN(EDOM_INFO(d)) < PERIOD_BEGIN(curinf)) 1.225 - break; 1.226 - else 1.227 - PRINT(4,"\tbehind domain %i.%i (bop= %llu)\n", 1.228 - curinf->exec_domain->domain->id, 1.229 - curinf->exec_domain->eid, PERIOD_BEGIN(curinf)); 1.230 - } 1.231 - /*cur now contains the element, before which we'll enqueue*/ 1.232 - PRINT(3,"\tlist_add to %x\n",cur->prev); 1.233 - list_add(LIST(d),cur->prev); 1.234 + d->eid, PERIOD_BEGIN(EDOM_INFO(d))); 1.235 + list_insert_sort(WAITQ(d->processor), LIST(d), waitq_comp); 1.236 + ASSERT(__task_on_queue(d)); 1.237 } 1.238 1.239 /* adds a domain to the queue of processes which have started their current 1.240 @@ -272,30 +318,11 @@ static inline void __add_to_waitqueue_so 1.241 on this list is running on the processor, if the list is empty the idle 1.242 task will run. As we are implementing EDF, this list is sorted by deadlines. 1.243 */ 1.244 +DOMAIN_COMPARER(runq, list, d1->deadl_abs, d2->deadl_abs) 1.245 static inline void __add_to_runqueue_sort(struct exec_domain *d) { 1.246 - struct list_head *cur; 1.247 - struct sedf_edom_info *curinf; 1.248 - 1.249 PRINT(3,"Adding domain %i.%i (deadl= %llu) to runq\n", d->domain->id, 1.250 - d->eid, EDOM_INFO(d)->deadl_abs); 1.251 - 1.252 - /*iterate through all elements to find our "hole"*/ 1.253 - list_for_each(cur, RUNQ(d->processor)) { 1.254 - curinf = list_entry(cur, struct sedf_edom_info, list); 1.255 - if (EDOM_INFO(d)->deadl_abs < curinf->deadl_abs) 1.256 - break; 1.257 - else 1.258 - PRINT(4,"\tbehind domain %i.%i (deadl= %llu)\n", 1.259 - curinf->exec_domain->domain->id, 1.260 - curinf->exec_domain->eid, curinf->deadl_abs); 1.261 - } 1.262 - 1.263 - /*cur now contains the element, before which we'll enqueue*/ 1.264 - PRINT(3,"\tlist_add to %x\n",cur->prev); 1.265 - list_add(LIST(d),cur->prev); 1.266 -} 1.267 -static inline int __task_on_queue(struct exec_domain *d) { 1.268 - return (((LIST(d))->next != NULL) && (LIST(d)->next != LIST(d))); 1.269 + d->eid, EDOM_INFO(d)->deadl_abs); 1.270 + list_insert_sort(RUNQ(d->processor), LIST(d), runq_comp); 1.271 } 1.272 1.273 /* Initialises the queues */ 1.274 @@ -313,15 +340,6 @@ static int sedf_init_scheduler() { 1.275 INIT_LIST_HEAD(EXTRAQ(i,EXTRA_PEN_Q)); 1.276 INIT_LIST_HEAD(EXTRAQ(i,EXTRA_UTIL_Q)); 1.277 } 1.278 -//TODO: Remove this stuff if things work! 1.279 - /*dom_info_cache = xmem_cache_create("SEDF dom info", 1.280 - sizeof(struct sedf_dom_info), 0, 0, 0, NULL); 1.281 - if ( dom_info_cache == NULL ) 1.282 - { 1.283 - printk("Could not allocate SLAB cache.\n"); 1.284 - return -1; 1.285 - }*/ 1.286 - 1.287 return 0; 1.288 } 1.289 1.290 @@ -344,7 +362,7 @@ static int sedf_alloc_task(struct exec_d 1.291 /* Setup the sedf_dom_info */ 1.292 static void sedf_add_task(struct exec_domain *d) 1.293 { 1.294 - struct sedf_edom_info *inf=EDOM_INFO(d); 1.295 + struct sedf_edom_info *inf = EDOM_INFO(d); 1.296 inf->exec_domain = d; 1.297 1.298 PRINT(2,"sedf_add_task was called, domain-id %i.%i\n",d->domain->id, 1.299 @@ -356,20 +374,25 @@ static void sedf_add_task(struct exec_do 1.300 inf->slice = MILLISECS(15); 1.301 inf->latency = 0; 1.302 inf->deadl_abs = 0; 1.303 - inf->extra = EXTRA_NONE;/*EXTRA_AWARE; */ 1.304 + inf->status = EXTRA_NONE | SEDF_ASLEEP;/*EXTRA_AWARE; */ 1.305 } 1.306 else { 1.307 /*other domains run in best effort mode*/ 1.308 - inf->period = MILLISECS(20); 1.309 + inf->period = WEIGHT_PERIOD; 1.310 inf->slice = 0; 1.311 inf->deadl_abs = 0; 1.312 inf->latency = 0; 1.313 - inf->extra = EXTRA_AWARE; 1.314 + inf->status = EXTRA_AWARE | SEDF_ASLEEP; 1.315 + inf->extraweight = 1; 1.316 } 1.317 inf->period_orig = inf->period; inf->slice_orig = inf->slice; 1.318 INIT_LIST_HEAD(&(inf->list)); 1.319 INIT_LIST_HEAD(&(inf->extralist[EXTRA_PEN_Q])); 1.320 INIT_LIST_HEAD(&(inf->extralist[EXTRA_UTIL_Q])); 1.321 + 1.322 + if (d->domain->id != IDLE_DOMAIN_ID) { 1.323 + extraq_check(d); 1.324 + } 1.325 } 1.326 1.327 /* Frees memory used by domain info */ 1.328 @@ -396,6 +419,7 @@ static int sedf_init_idle_task(struct ex 1.329 1.330 sedf_add_task(d); 1.331 EDOM_INFO(d)->deadl_abs = 0; 1.332 + EDOM_INFO(d)->status &= ~SEDF_ASLEEP; 1.333 set_bit(EDF_RUNNING, &d->ed_flags); 1.334 /*the idle task doesn't have to turn up on any list...*/ 1.335 return 0; 1.336 @@ -406,21 +430,17 @@ static inline void desched_edf_dom (s_ti 1.337 struct sedf_edom_info* inf = EDOM_INFO(d); 1.338 /*current domain is running in real time mode*/ 1.339 1.340 + ASSERT(__task_on_queue(d)); 1.341 /*update the domains cputime*/ 1.342 inf->cputime += now - inf->sched_start_abs; 1.343 1.344 /*scheduling decisions, which don't remove the running domain 1.345 from the runq*/ 1.346 - if ((inf->cputime < inf->slice) && domain_runnable(d)) 1.347 + if ((inf->cputime < inf->slice) && sedf_runnable(d)) 1.348 return; 1.349 1.350 __del_from_queue(d); 1.351 - /*if (__task_on_queue(d)) { 1.352 - PRINT(0,"domain %i.%i was removed but still on run/waitq => "\ 1.353 - "HALT\n",d->domain->id, d->eid); 1.354 - sedf_dump_cpu_state(0);(*((int*)0))++; 1.355 - }*/ 1.356 - 1.357 + 1.358 /*manage bookkeeping (i.e. calculate next deadline, 1.359 memorize overun-time of slice) of finished domains*/ 1.360 if (inf->cputime >= inf->slice) { 1.361 @@ -429,6 +449,8 @@ static inline void desched_edf_dom (s_ti 1.362 if (inf->period < inf->period_orig) { 1.363 /*this domain runs in latency scaling or burst mode*/ 1.364 #if (UNBLOCK == UNBLOCK_BURST) 1.365 + /*if we are runnig in burst scaling wait for two periods 1.366 + before scaling periods up again*/ 1.367 if (now - inf->unblock_abs >= 2 * inf->period) 1.368 #endif 1.369 { 1.370 @@ -444,17 +466,12 @@ static inline void desched_edf_dom (s_ti 1.371 /*set next deadline*/ 1.372 inf->deadl_abs += inf->period; 1.373 } 1.374 - /*if (inf->deadl_abs < now) 1.375 - printk("Domain %i.%i exceeded it't deadline!!!! "\ 1.376 - "(now: %llu ddl: %llu)\n", d->domain->id, d->eid, now, 1.377 - inf->deadl_abs);*/ 1.378 - 1.379 + 1.380 /*add a runnable domain to the waitqueue*/ 1.381 - if (domain_runnable(d)) 1.382 + if (sedf_runnable(d)) 1.383 __add_to_waitqueue_sort(d); 1.384 else { 1.385 /*we have a blocked realtime task -> remove it from exqs too*/ 1.386 - inf->block_abs = now; 1.387 #if (EXTRA > EXTRA_OFF) 1.388 #if (EXTRA == EXTRA_BLOCK_WEIGHT) 1.389 if (extraq_on(d, EXTRA_PEN_Q)) extraq_del(d, EXTRA_PEN_Q); 1.390 @@ -462,6 +479,9 @@ static inline void desched_edf_dom (s_ti 1.391 if (extraq_on(d, EXTRA_UTIL_Q)) extraq_del(d, EXTRA_UTIL_Q); 1.392 #endif 1.393 } 1.394 + ASSERT(EQ(sedf_runnable(d), __task_on_queue(d))); 1.395 + ASSERT(IMPLY(extraq_on(d, EXTRA_UTIL_Q) || extraq_on(d, EXTRA_PEN_Q), 1.396 + sedf_runnable(d))); 1.397 } 1.398 1.399 /* Update all elements on the queues */ 1.400 @@ -503,42 +523,41 @@ struct list_head* waitq) { 1.401 curinf->deadl_abs += curinf->period; 1.402 /*and put them back into the queue*/ 1.403 __add_to_waitqueue_sort(curinf->exec_domain); 1.404 + continue; 1.405 } 1.406 - else { 1.407 - if (unlikely((curinf->deadl_abs < now) || 1.408 - (curinf->cputime > curinf->slice))) { 1.409 - /*we missed the deadline or the slice was 1.410 - already finished... might hapen because 1.411 - of dom_adj.*/ 1.412 - PRINT(4,"\tDomain %i.%i exceeded it's deadline/"\ 1.413 - "slice (%llu / %llu) now: %llu "\ 1.414 - "cputime: %llu\n", 1.415 - curinf->exec_domain->domain->id, 1.416 - curinf->exec_domain->eid, 1.417 - curinf->deadl_abs, curinf->slice, now, 1.418 - curinf->cputime); 1.419 - __del_from_queue(curinf->exec_domain); 1.420 - /*common case: we miss one period!*/ 1.421 - curinf->deadl_abs += curinf->period; 1.422 - 1.423 - /*if we are still behind: modulo arithmetic, 1.424 - force deadline to be in future and 1.425 - aligned to period borders!*/ 1.426 - if (unlikely(curinf->deadl_abs < now)) 1.427 - curinf->deadl_abs += 1.428 - DIV_UP(now - curinf->deadl_abs, 1.429 - curinf->period) * curinf->period; 1.430 - ASSERT(curinf->deadl_abs > now); 1.431 - /*give a fresh slice*/ 1.432 - curinf->cputime = 0; 1.433 - if (PERIOD_BEGIN(curinf) > now) 1.434 - __add_to_waitqueue_sort(curinf->exec_domain); 1.435 - else 1.436 - __add_to_runqueue_sort(curinf->exec_domain); 1.437 - } 1.438 + if (unlikely((curinf->deadl_abs < now) || 1.439 + (curinf->cputime > curinf->slice))) { 1.440 + /*we missed the deadline or the slice was 1.441 + already finished... might hapen because 1.442 + of dom_adj.*/ 1.443 + PRINT(4,"\tDomain %i.%i exceeded it's deadline/"\ 1.444 + "slice (%llu / %llu) now: %llu "\ 1.445 + "cputime: %llu\n", 1.446 + curinf->exec_domain->domain->id, 1.447 + curinf->exec_domain->eid, 1.448 + curinf->deadl_abs, curinf->slice, now, 1.449 + curinf->cputime); 1.450 + __del_from_queue(curinf->exec_domain); 1.451 + /*common case: we miss one period!*/ 1.452 + curinf->deadl_abs += curinf->period; 1.453 + 1.454 + /*if we are still behind: modulo arithmetic, 1.455 + force deadline to be in future and 1.456 + aligned to period borders!*/ 1.457 + if (unlikely(curinf->deadl_abs < now)) 1.458 + curinf->deadl_abs += 1.459 + DIV_UP(now - curinf->deadl_abs, 1.460 + curinf->period) * curinf->period; 1.461 + ASSERT(curinf->deadl_abs > now); 1.462 + /*give a fresh slice*/ 1.463 + curinf->cputime = 0; 1.464 + if (PERIOD_BEGIN(curinf) > now) 1.465 + __add_to_waitqueue_sort(curinf->exec_domain); 1.466 else 1.467 - break; 1.468 + __add_to_runqueue_sort(curinf->exec_domain); 1.469 } 1.470 + else 1.471 + break; 1.472 } 1.473 PRINT(3,"done updating the queues\n"); 1.474 } 1.475 @@ -554,12 +573,12 @@ static inline void desched_extra_dom(s_t 1.476 struct sedf_edom_info *inf = EDOM_INFO(d); 1.477 int i = extra_get_cur_q(inf); 1.478 1.479 - #if (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) 1.480 +#if (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) 1.481 unsigned long oldscore; 1.482 - #endif 1.483 - 1.484 +#endif 1.485 + ASSERT(extraq_on(d, i)); 1.486 /*unset all running flags*/ 1.487 - inf->extra &= ~(EXTRA_RUN_PEN | EXTRA_RUN_UTIL); 1.488 + inf->status &= ~(EXTRA_RUN_PEN | EXTRA_RUN_UTIL); 1.489 /*fresh slice for the next run*/ 1.490 inf->cputime = 0; 1.491 /*accumulate total extratime*/ 1.492 @@ -567,14 +586,14 @@ static inline void desched_extra_dom(s_t 1.493 /*remove extradomain from head of the queue*/ 1.494 extraq_del(d, i); 1.495 1.496 - #if (EXTRA == EXTRA_ROUNDR) 1.497 - if (domain_runnable(d)) 1.498 +#if (EXTRA == EXTRA_ROUNDR) 1.499 + if (sedf_runnable(d) && (inf->status & EXTRA_AWARE)) 1.500 /*add to the tail if it is runnable => round-robin*/ 1.501 extraq_add_tail(d, EXTRA_UTIL_Q); 1.502 - #elif (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) 1.503 +#elif (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) 1.504 /*update the score*/ 1.505 oldscore = inf->score[i]; 1.506 - #if (EXTRA == EXTRA_BLOCK_WEIGHT) 1.507 +#if (EXTRA == EXTRA_BLOCK_WEIGHT) 1.508 if (i == EXTRA_PEN_Q) { 1.509 /*domain was running in L0 extraq*/ 1.510 /*reduce block lost, probably more sophistication here!*/ 1.511 @@ -589,9 +608,8 @@ static inline void desched_extra_dom(s_t 1.512 /*we have (over-)compensated our block penalty*/ 1.513 inf->short_block_lost_tot = 0; 1.514 /*we don't want a place on the penalty queue anymore!*/ 1.515 - inf->extra &= ~EXTRA_WANT_PEN_Q; 1.516 - /*do not add us on this block extraq again!*/ 1.517 - return; 1.518 + inf->status &= ~EXTRA_WANT_PEN_Q; 1.519 + goto check_extra_queues; 1.520 } 1.521 /*we have to go again for another try in the block-extraq, 1.522 the score is not used incremantally here, as this is 1.523 @@ -600,33 +618,32 @@ static inline void desched_extra_dom(s_t 1.524 inf->short_block_lost_tot; 1.525 oldscore = 0; 1.526 } else 1.527 - #endif 1.528 +#endif 1.529 { 1.530 /*domain was running in L1 extraq => score is inverse of 1.531 utilization and is used somewhat incremental!*/ 1.532 -//TODO: Check for weights => use them for calculating the score! 1.533 - if (inf->slice) 1.534 + if (!inf->extraweight) 1.535 /*NB: use fixed point arithmetic with 10 bits*/ 1.536 inf->score[EXTRA_UTIL_Q] = (inf->period << 10) / 1.537 inf->slice; 1.538 else 1.539 - /*set best effort domains to the maximum value*/ 1.540 - inf->score[EXTRA_UTIL_Q] = 2^10; 1.541 + /*give a domain w/ exweight = 1 as much as a domain with 1.542 + util = 1/128*/ 1.543 + inf->score[EXTRA_UTIL_Q] = (1<<17) / inf->extraweight; 1.544 } 1.545 - if (domain_runnable(d)) 1.546 +check_extra_queues: 1.547 + /* Adding a runnable domain to the right queue and removing blocked ones*/ 1.548 + if (sedf_runnable(d)) { 1.549 /*add according to score: weighted round robin*/ 1.550 - extraq_add_sort_update(d, i, oldscore); 1.551 + if (inf->status & (EXTRA_AWARE | EXTRA_WANT_PEN_Q)) 1.552 + extraq_add_sort_update(d, i, oldscore); 1.553 + } 1.554 else { 1.555 - inf->block_abs = now; 1.556 - /*if (!__task_on_queue(d)) 1.557 - printf("Oops... We attempt to remove d %i.%i from the "\ 1.558 - "waitq, but it is not on :(\n", d->domain->id, 1.559 - d->eid);*/ 1.560 /*remove this blocked domain from the waitq!*/ 1.561 - __del_from_queue(d); 1.562 + __del_from_queue(d); 1.563 +#if (EXTRA == EXTRA_BLOCK_WEIGHT) 1.564 /*make sure that we remove a blocked domain from the other 1.565 - extraq aswell (this caused hours of debugging!)*/ 1.566 - #if (EXTRA == EXTRA_BLOCK_WEIGHT) 1.567 + extraq too*/ 1.568 if (i == EXTRA_PEN_Q) { 1.569 if (extraq_on(d, EXTRA_UTIL_Q)) 1.570 extraq_del(d, EXTRA_UTIL_Q); 1.571 @@ -635,25 +652,17 @@ static inline void desched_extra_dom(s_t 1.572 if (extraq_on(d, EXTRA_PEN_Q)) 1.573 extraq_del(d, EXTRA_PEN_Q); 1.574 } 1.575 - #endif 1.576 +#endif 1.577 } 1.578 - #endif 1.579 - /*if (!domain_runnable(d)) { 1.580 - if (extraq_on(d, EXTRA_UTIL_Q)) { 1.581 - PRINT(0,"domain %i.%i is blocked but still on L1 "\ 1.582 - "xq=> HALT\n",d->domain->id, d->eid); 1.583 - sedf_dump_cpu_state(0);(*((int*)0))++; 1.584 - } 1.585 - if (__task_on_queue(d)) { 1.586 - PRINT(0,"domain %i.%i is blocked but still on run/waitq"\ 1.587 - "=> HALT\n",d->domain->id, d->eid); 1.588 - sedf_dump_cpu_state(0);(*((int*)0))++; 1.589 - } 1.590 - }*/ 1.591 +#endif 1.592 + ASSERT(EQ(sedf_runnable(d), __task_on_queue(d))); 1.593 + ASSERT(IMPLY(extraq_on(d, EXTRA_UTIL_Q) || extraq_on(d, EXTRA_PEN_Q), 1.594 + sedf_runnable(d))); 1.595 } 1.596 #endif 1.597 1.598 -static inline struct task_slice sedf_do_extra_schedule (s_time_t now, s_time_t end_xt, struct list_head *extraq[], int cpu) { 1.599 +static inline struct task_slice sedf_do_extra_schedule (s_time_t now, 1.600 + s_time_t end_xt, struct list_head *extraq[], int cpu) { 1.601 struct task_slice ret; 1.602 struct sedf_edom_info *runinf; 1.603 1.604 @@ -666,7 +675,7 @@ static inline struct task_slice sedf_do_ 1.605 => let those run first!*/ 1.606 runinf = list_entry(extraq[EXTRA_PEN_Q]->next, 1.607 struct sedf_edom_info, extralist[EXTRA_PEN_Q]); 1.608 - runinf->extra |= EXTRA_RUN_PEN; 1.609 + runinf->status |= EXTRA_RUN_PEN; 1.610 ret.task = runinf->exec_domain; 1.611 ret.time = EXTRA_QUANTUM; 1.612 #ifdef SEDF_STATS 1.613 @@ -678,18 +687,22 @@ static inline struct task_slice sedf_do_ 1.614 /*use elements from the normal extraqueue*/ 1.615 runinf = list_entry(extraq[EXTRA_UTIL_Q]->next, 1.616 struct sedf_edom_info, extralist[EXTRA_UTIL_Q]); 1.617 - runinf->extra |= EXTRA_RUN_UTIL; 1.618 + runinf->status |= EXTRA_RUN_UTIL; 1.619 ret.task = runinf->exec_domain; 1.620 ret.time = EXTRA_QUANTUM; 1.621 } 1.622 else 1.623 goto return_idle; 1.624 1.625 + ASSERT(ret.time > 0); 1.626 + ASSERT(sedf_runnable(ret.task)); 1.627 return ret; 1.628 1.629 return_idle: 1.630 ret.task = IDLETASK(cpu); 1.631 ret.time = end_xt - now; 1.632 + ASSERT(ret.time > 0); 1.633 + ASSERT(sedf_runnable(ret.task)); 1.634 return ret; 1.635 } 1.636 /* Main scheduling function 1.637 @@ -713,32 +726,25 @@ static struct task_slice sedf_do_schedul 1.638 if (is_idle_task(current->domain)) 1.639 goto check_waitq; 1.640 1.641 + /* create local state of the status of the domain, in order to avoid 1.642 + inconsistent state during scheduling decisions, because data for 1.643 + domain_runnable is not protected by the scheduling lock!*/ 1.644 + if(!domain_runnable(current)) 1.645 + inf->status |= SEDF_ASLEEP; 1.646 + 1.647 + if (inf->status & SEDF_ASLEEP) 1.648 + inf->block_abs = now; 1.649 + 1.650 #if (EXTRA > EXTRA_OFF) 1.651 if (unlikely(extra_runs(inf))) { 1.652 - /*i=1;*/ 1.653 /*special treatment of domains running in extra time*/ 1.654 desched_extra_dom(now, current); 1.655 } 1.656 else 1.657 #endif 1.658 { 1.659 - /*i=2;*/ 1.660 desched_edf_dom(now, current); 1.661 } 1.662 - /*if (!domain_runnable(current)) { 1.663 - if (extraq_on(current,EXTRA_UTIL_Q)) { 1.664 - PRINT(0,"domain %i.%i is blocked but still on L1 xq"\ 1.665 - " branch %i=> HALT\n", current->domain->id, 1.666 - current->eid, i); 1.667 - sedf_dump_cpu_state(0);(*((int*)0))++; 1.668 - } 1.669 - if (__task_on_queue(current)) { 1.670 - PRINT(0,"domain %i.%i is blocked but still on run/waitq"\ 1.671 - " branch %i=> HALT\n",current->domain->id, 1.672 - d->eid,i); 1.673 - sedf_dump_cpu_state(0);(*((int*)0))++; 1.674 - } 1.675 - }*/ 1.676 check_waitq: 1.677 update_queues(now, runq, waitq); 1.678 1.679 @@ -761,7 +767,7 @@ check_waitq: 1.680 else { 1.681 ret.time = runinf->slice - runinf->cputime; 1.682 } 1.683 - ASSERT(ret.time > now); 1.684 + CHECK(ret.time > 0); 1.685 goto sched_done; 1.686 } 1.687 1.688 @@ -776,7 +782,7 @@ check_waitq: 1.689 ret.task = IDLETASK(cpu); 1.690 ret.time = PERIOD_BEGIN(waitinf) - now; 1.691 #endif 1.692 - ASSERT(ret.time > now); 1.693 + CHECK(ret.time > 0); 1.694 } 1.695 else { 1.696 /*this could probably never happen, but one never knows...*/ 1.697 @@ -795,11 +801,19 @@ sched_done: 1.698 ret.time = EXTRA_QUANTUM; 1.699 } 1.700 EDOM_INFO(ret.task)->sched_start_abs = now; 1.701 + CHECK(ret.time > 0); 1.702 + ASSERT(sedf_runnable(ret.task)); 1.703 return ret; 1.704 } 1.705 1.706 static void sedf_sleep(struct exec_domain *d) { 1.707 PRINT(2,"sedf_sleep was called, domain-id %i.%i\n",d->domain->id, d->eid); 1.708 + 1.709 + if (is_idle_task(d->domain)) 1.710 + return; 1.711 + 1.712 + EDOM_INFO(d)->status |= SEDF_ASLEEP; 1.713 + 1.714 if ( test_bit(EDF_RUNNING, &d->ed_flags) ) { 1.715 #ifdef ADV_SCHED_HISTO 1.716 adv_sched_hist_start(d->processor); 1.717 @@ -946,7 +960,7 @@ static inline void unblock_short_extra_s 1.718 /*remember that we want to be on the penalty q 1.719 so that we can continue when we (un-)block 1.720 in penalty-extratime*/ 1.721 - inf->extra |= EXTRA_WANT_PEN_Q; 1.722 + inf->status |= EXTRA_WANT_PEN_Q; 1.723 1.724 /*(re-)add domain to the penalty extraq*/ 1.725 extraq_add_sort_update(inf->exec_domain, 1.726 @@ -1072,9 +1086,9 @@ static inline int get_run_type(struct ex 1.727 struct sedf_edom_info* inf = EDOM_INFO(d); 1.728 if (is_idle_task(d->domain)) 1.729 return DOMAIN_IDLE; 1.730 - if (inf->extra & EXTRA_RUN_PEN) 1.731 + if (inf->status & EXTRA_RUN_PEN) 1.732 return DOMAIN_EXTRA_PEN; 1.733 - if (inf->extra & EXTRA_RUN_UTIL) 1.734 + if (inf->status & EXTRA_RUN_UTIL) 1.735 return DOMAIN_EXTRA_UTIL; 1.736 return DOMAIN_EDF; 1.737 } 1.738 @@ -1105,7 +1119,7 @@ static inline int should_switch(struct e 1.739 case DOMAIN_EXTRA_PEN: 1.740 /*check whether we also want 1.741 the L0 ex-q with lower score*/ 1.742 - if ((other_inf->extra & EXTRA_WANT_PEN_Q) 1.743 + if ((other_inf->status & EXTRA_WANT_PEN_Q) 1.744 && (other_inf->score[EXTRA_PEN_Q] < 1.745 cur_inf->score[EXTRA_PEN_Q])) 1.746 return 1; 1.747 @@ -1113,31 +1127,33 @@ static inline int should_switch(struct e 1.748 case DOMAIN_EXTRA_UTIL: 1.749 /*check whether we want the L0 extraq, don't 1.750 switch if both domains want L1 extraq */ 1.751 - if (other_inf->extra & EXTRA_WANT_PEN_Q) 1.752 + if (other_inf->status & EXTRA_WANT_PEN_Q) 1.753 return 1; 1.754 else return 0; 1.755 case DOMAIN_IDLE: 1.756 return 1; 1.757 } 1.758 + return 1; 1.759 } 1.760 void sedf_wake(struct exec_domain *d) { 1.761 s_time_t now = NOW(); 1.762 struct sedf_edom_info* inf = EDOM_INFO(d); 1.763 1.764 - PRINT(3,"sedf_wake was called, domain-id %i.%i\n",d->domain->id, d->eid); 1.765 + PRINT(3, "sedf_wake was called, domain-id %i.%i\n",d->domain->id, d->eid); 1.766 1.767 if (unlikely(is_idle_task(d->domain))) 1.768 return; 1.769 - 1.770 + 1.771 if ( unlikely(__task_on_queue(d)) ) { 1.772 PRINT(3,"\tdomain %i.%i is already in some queue\n", 1.773 d->domain->id, d->eid); 1.774 return; 1.775 } 1.776 - if ( unlikely(extraq_on(d,EXTRA_UTIL_Q) || extraq_on(d,EXTRA_PEN_Q)) ) { 1.777 - PRINT(3,"\tdomain %i.%i is already in the extraQ\n", 1.778 - d->domain->id, d->eid); 1.779 - } 1.780 + ASSERT(!sedf_runnable(d)); 1.781 + inf->status &= ~SEDF_ASLEEP; 1.782 + ASSERT(!extraq_on(d, EXTRA_UTIL_Q)); 1.783 + ASSERT(!extraq_on(d, EXTRA_PEN_Q)); 1.784 + 1.785 if (unlikely(inf->deadl_abs == 0)) 1.786 /*initial setup of the deadline*/ 1.787 inf->deadl_abs = now + inf->slice; 1.788 @@ -1150,9 +1166,9 @@ void sedf_wake(struct exec_domain *d) { 1.789 #endif 1.790 if (unlikely(now < PERIOD_BEGIN(inf))) { 1.791 PRINT(4,"extratime unblock\n"); 1.792 - /*this might happen, imagine unblocking in extra-time!*/ 1.793 + /* unblocking in extra-time! */ 1.794 #if (EXTRA == EXTRA_BLOCK_WEIGHT) 1.795 - if (inf->extra & EXTRA_WANT_PEN_Q) { 1.796 + if (inf->status & EXTRA_WANT_PEN_Q) { 1.797 /*we have a domain that wants compensation 1.798 for block penalty and did just block in 1.799 its compensation time. Give it another 1.800 @@ -1160,19 +1176,7 @@ void sedf_wake(struct exec_domain *d) { 1.801 extraq_add_sort_update(d, EXTRA_PEN_Q, 0); 1.802 } 1.803 #endif 1.804 - if (inf->extra & EXTRA_AWARE) 1.805 - #if (EXTRA == EXTRA_ROUNDR) 1.806 - extraq_add_tail(d,EXTRA_UTIL_Q); 1.807 - #elif (EXTRA == EXTRA_SLICE_WEIGHT \ 1.808 - || EXTRA == EXTRA_BLOCK_WEIGHT) 1.809 - /*put in on the weighted extraq, 1.810 - without updating any scores*/ 1.811 - extraq_add_sort_update(d, EXTRA_UTIL_Q, 0); 1.812 - #else 1.813 - ; 1.814 - #endif 1.815 - /*else*/ 1.816 - /*This is very very unlikely, ie. might even be an error?!*/ 1.817 + extraq_check_add_unblocked(d, 0); 1.818 } 1.819 else { 1.820 if (now < inf->deadl_abs) { 1.821 @@ -1191,16 +1195,7 @@ void sedf_wake(struct exec_domain *d) { 1.822 unblock_short_extra_support(inf, now); 1.823 #endif 1.824 1.825 - if (inf->extra & EXTRA_AWARE) 1.826 - #if (EXTRA == EXTRA_OFF) 1.827 - ; 1.828 - #elif (EXTRA == EXTRA_ROUNDR) 1.829 - /*Favour domains which got short unblocked*/ 1.830 - extraq_add_head(d, EXTRA_UTIL_Q); 1.831 - #elif (EXTRA == EXTRA_SLICE_WEIGHT \ 1.832 - || EXTRA == EXTRA_BLOCK_WEIGHT) 1.833 - extraq_add_sort_update(d, EXTRA_UTIL_Q, 0); 1.834 - #endif 1.835 + extraq_check_add_unblocked(d, 1); 1.836 } 1.837 else { 1.838 PRINT(4,"long unblocking\n"); 1.839 @@ -1221,25 +1216,21 @@ void sedf_wake(struct exec_domain *d) { 1.840 #elif (UNBLOCK == UNBLOCK_BURST) 1.841 unblock_long_burst(inf, now); 1.842 #endif 1.843 - 1.844 - if (inf->extra & EXTRA_AWARE) { 1.845 - #if (EXTRA == EXTRA_OFF) 1.846 - ; 1.847 - #elif (EXTRA == EXTRA_ROUNDR) 1.848 - extraq_add_head(d, EXTRA_UTIL_Q); 1.849 - #elif (EXTRA == EXTRA_SLICE_WEIGHT \ 1.850 - || EXTRA == EXTRA_BLOCK_WEIGHT) 1.851 - extraq_add_sort_update(d, EXTRA_UTIL_Q, 0); 1.852 - #endif 1.853 - } 1.854 - 1.855 + 1.856 + extraq_check_add_unblocked(d, 1); 1.857 } 1.858 } 1.859 PRINT(3,"woke up domain %i.%i (deadl= %llu period= %llu "\ 1.860 "now= %llu)\n", d->domain->id, d->eid, inf->deadl_abs, 1.861 inf->period, now); 1.862 - __add_to_waitqueue_sort(d); 1.863 - PRINT(3,"added to waitq\n"); 1.864 + if (PERIOD_BEGIN(inf) > now) { 1.865 + __add_to_waitqueue_sort(d); 1.866 + PRINT(3,"added to waitq\n"); 1.867 + } 1.868 + else { 1.869 + __add_to_runqueue_sort(d); 1.870 + PRINT(3,"added to runq\n"); 1.871 + } 1.872 1.873 #ifdef SEDF_STATS 1.874 /*do some statistics here...*/ 1.875 @@ -1250,12 +1241,8 @@ void sedf_wake(struct exec_domain *d) { 1.876 } 1.877 #endif 1.878 /*sanity check: make sure each extra-aware domain IS on the util-q!*/ 1.879 - /*if (inf->extra & EXTRA_AWARE) { 1.880 - if (!extraq_on(d, EXTRA_UTIL_Q)) 1.881 - printf("sedf_wake: domain %i.%i is extra-aware, "\ 1.882 - "but NOT on L1 extraq!\n",d->domain->id, d->eid); 1.883 - }*/ 1.884 - 1.885 + ASSERT(IMPLY(inf->status & EXTRA_AWARE, extraq_on(d, EXTRA_UTIL_Q))); 1.886 + ASSERT(__task_on_queue(d)); 1.887 /*check whether the awakened task needs to invoke the do_schedule 1.888 routine. Try to avoid unnecessary runs but: 1.889 Save approximation: Always switch to scheduler!*/ 1.890 @@ -1271,11 +1258,11 @@ void sedf_wake(struct exec_domain *d) { 1.891 static void sedf_dump_domain(struct exec_domain *d) { 1.892 printk("%i.%i has=%c ", d->domain->id, d->eid, 1.893 test_bit(EDF_RUNNING, &d->ed_flags) ? 'T':'F'); 1.894 - printk("p=%llu sl=%llu ddl=%llu w=%hu c=%llu sc=%i xtr(%s)=%llu", 1.895 + printk("p=%llu sl=%llu ddl=%llu w=%hu c=%llu sc=%i xtr(%s)=%llu ew=%hu", 1.896 EDOM_INFO(d)->period, EDOM_INFO(d)->slice, EDOM_INFO(d)->deadl_abs, 1.897 EDOM_INFO(d)->weight, d->cpu_time, EDOM_INFO(d)->score[EXTRA_UTIL_Q], 1.898 - (EDOM_INFO(d)->extra & EXTRA_AWARE) ? "yes" : "no", 1.899 - EDOM_INFO(d)->extra_time_tot); 1.900 + (EDOM_INFO(d)->status & EXTRA_AWARE) ? "yes" : "no", 1.901 + EDOM_INFO(d)->extra_time_tot, EDOM_INFO(d)->extraweight); 1.902 if (d->cpu_time !=0) 1.903 printf(" (%lu%)", (EDOM_INFO(d)->extra_time_tot * 100) 1.904 / d->cpu_time); 1.905 @@ -1408,7 +1395,7 @@ static inline int sedf_adjust_weights(st 1.906 /* set or fetch domain scheduling parameters */ 1.907 static int sedf_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) { 1.908 struct exec_domain *ed; 1.909 - 1.910 + 1.911 PRINT(2,"sedf_adjdom was called, domain-id %i new period %llu "\ 1.912 "new slice %llu\nlatency %llu extra:%s\n", 1.913 p->id, cmd->u.sedf.period, cmd->u.sedf.slice, 1.914 @@ -1418,10 +1405,21 @@ static int sedf_adjdom(struct domain *p, 1.915 /*check for sane parameters*/ 1.916 if (!cmd->u.sedf.period && !cmd->u.sedf.weight) 1.917 return -EINVAL; 1.918 - /*weight driven domains*/ 1.919 if (cmd->u.sedf.weight) { 1.920 - for_each_exec_domain(p, ed) 1.921 - EDOM_INFO(ed)->weight = cmd->u.sedf.weight; 1.922 + if ((cmd->u.sedf.extratime & EXTRA_AWARE) && 1.923 + (! cmd->u.sedf.period)) { 1.924 + /*weight driven domains with xtime ONLY!*/ 1.925 + for_each_exec_domain(p, ed) { 1.926 + EDOM_INFO(ed)->extraweight = cmd->u.sedf.weight; 1.927 + EDOM_INFO(ed)->weight = 0; 1.928 + EDOM_INFO(ed)->slice = 0; 1.929 + EDOM_INFO(ed)->period = WEIGHT_PERIOD; 1.930 + } 1.931 + } else { 1.932 + /*weight driven domains with real-time execution*/ 1.933 + for_each_exec_domain(p, ed) 1.934 + EDOM_INFO(ed)->weight = cmd->u.sedf.weight; 1.935 + } 1.936 } 1.937 else { 1.938 /*time driven domains*/ 1.939 @@ -1430,6 +1428,7 @@ static int sedf_adjdom(struct domain *p, 1.940 if(cmd->u.sedf.slice > cmd->u.sedf.period ) 1.941 return -EINVAL; 1.942 EDOM_INFO(ed)->weight = 0; 1.943 + EDOM_INFO(ed)->extraweight = 0; 1.944 EDOM_INFO(ed)->period_orig = 1.945 EDOM_INFO(ed)->period = cmd->u.sedf.period; 1.946 EDOM_INFO(ed)->slice_orig = 1.947 @@ -1440,7 +1439,7 @@ static int sedf_adjdom(struct domain *p, 1.948 return -EINVAL; 1.949 1.950 for_each_exec_domain(p, ed) { 1.951 - EDOM_INFO(ed)->extra = (EDOM_INFO(ed)->extra & 1.952 + EDOM_INFO(ed)->status = (EDOM_INFO(ed)->status & 1.953 ~EXTRA_AWARE) | (cmd->u.sedf.extratime & EXTRA_AWARE); 1.954 EDOM_INFO(ed)->latency = cmd->u.sedf.latency; 1.955 extraq_check(ed); 1.956 @@ -1450,7 +1449,7 @@ static int sedf_adjdom(struct domain *p, 1.957 { 1.958 cmd->u.sedf.period = EDOM_INFO(p->exec_domain[0])->period; 1.959 cmd->u.sedf.slice = EDOM_INFO(p->exec_domain[0])->slice; 1.960 - cmd->u.sedf.extratime = EDOM_INFO(p->exec_domain[0])->extra 1.961 + cmd->u.sedf.extratime = EDOM_INFO(p->exec_domain[0])->status 1.962 & EXTRA_AWARE; 1.963 cmd->u.sedf.latency = EDOM_INFO(p->exec_domain[0])->latency; 1.964 cmd->u.sedf.weight = EDOM_INFO(p->exec_domain[0])->weight;
2.1 --- a/xen/common/schedule.c Fri Apr 22 17:05:34 2005 +0000 2.2 +++ b/xen/common/schedule.c Mon May 02 15:49:43 2005 +0000 2.3 @@ -338,7 +338,19 @@ long sched_ctl(struct sched_ctl_cmd *cmd 2.4 long sched_adjdom(struct sched_adjdom_cmd *cmd) 2.5 { 2.6 struct domain *d; 2.7 + struct exec_domain *ed; 2.8 + int cpu; 2.9 +#if NR_CPUS <=32 2.10 + unsigned long have_lock; 2.11 + #else 2.12 + unsigned long long have_lock; 2.13 +#endif 2.14 + int succ; 2.15 2.16 + #define __set_cpu_bit(cpu, data) data |= ((typeof(data))1)<<cpu 2.17 + #define __get_cpu_bit(cpu, data) (data & ((typeof(data))1)<<cpu) 2.18 + #define __clear_cpu_bits(data) data = ((typeof(data))0) 2.19 + 2.20 if ( cmd->sched_id != ops.sched_id ) 2.21 return -EINVAL; 2.22 2.23 @@ -349,9 +361,38 @@ long sched_adjdom(struct sched_adjdom_cm 2.24 if ( d == NULL ) 2.25 return -ESRCH; 2.26 2.27 - spin_lock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock); 2.28 + /* acquire locks on all CPUs on which exec_domains of this domain run */ 2.29 + do { 2.30 + succ = 0; 2.31 + __clear_cpu_bits(have_lock); 2.32 + for_each_exec_domain(d, ed) { 2.33 + cpu = ed->processor; 2.34 + if (!__get_cpu_bit(cpu, have_lock)) { 2.35 + /* if we don't have a lock on this CPU: acquire it*/ 2.36 + if (!spin_trylock(&schedule_data[cpu].schedule_lock)) { 2.37 + /*we have this lock!*/ 2.38 + __set_cpu_bit(cpu, have_lock); 2.39 + succ = 1; 2.40 + } else { 2.41 + /*we didn,t get this lock -> free all other locks too!*/ 2.42 + for (cpu = 0; cpu < NR_CPUS; cpu++) 2.43 + if (__get_cpu_bit(cpu, have_lock)) 2.44 + spin_unlock(&schedule_data[cpu].schedule_lock); 2.45 + /* and start from the beginning! */ 2.46 + succ = 0; 2.47 + /* leave the "for_each_domain_loop" */ 2.48 + break; 2.49 + } 2.50 + } 2.51 + } 2.52 + } while (!succ); 2.53 + //spin_lock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock); 2.54 SCHED_OP(adjdom, d, cmd); 2.55 - spin_unlock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock); 2.56 + //spin_unlock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock); 2.57 + for (cpu = 0; cpu < NR_CPUS; cpu++) 2.58 + if (__get_cpu_bit(cpu, have_lock)) 2.59 + spin_unlock(&schedule_data[cpu].schedule_lock); 2.60 + __clear_cpu_bits(have_lock); 2.61 2.62 TRACE_1D(TRC_SCHED_ADJDOM, d->id); 2.63 put_domain(d);