ia64/xen-unstable

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}
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);