# HG changeset patch # User kaf24@freefall.cl.cam.ac.uk # Date 1096969990 0 # Node ID fe2f4bbcf8698fb9ef967c9495ed73340e843c53 # Parent a28d3cf3832ca6429af0b6fc24d86fd90f3fc782 bitkeeper revision 1.1159.99.4 (41626f06VquclgVVpIeHy9z2K3jW-A) Rationalise scheduler locking. A bit more conservative now, but much simpler! I only applied this to the basic BVT scheduler -- the others are still unsafe and have been removed from the basic build. diff -r a28d3cf3832c -r fe2f4bbcf869 xen/common/Makefile --- a/xen/common/Makefile Mon Oct 04 14:55:47 2004 +0000 +++ b/xen/common/Makefile Tue Oct 05 09:53:10 2004 +0000 @@ -19,6 +19,14 @@ ifneq ($(trace),y) OBJS := $(subst trace.o,,$(OBJS)) endif +ifneq ($(broken_schedulers),y) +OBJS := $(subst sched_atropos.o,,$(OBJS)) +OBJS := $(subst sched_fair_bvt.o,,$(OBJS)) +OBJS := $(subst sched_rrobin.o,,$(OBJS)) +else +CFLAGS += -DBROKEN_SCHEDULERS +endif + default: $(OBJS) $(LD) $(LDFLAGS) -r -o common.o $(OBJS) diff -r a28d3cf3832c -r fe2f4bbcf869 xen/common/domain.c --- a/xen/common/domain.c Mon Oct 04 14:55:47 2004 +0000 +++ b/xen/common/domain.c Tue Oct 05 09:53:10 2004 +0000 @@ -39,7 +39,6 @@ struct domain *do_createdomain(domid_t d d->domain = dom_id; d->processor = cpu; d->create_time = NOW(); - spin_lock_init(&d->sleep_lock); memcpy(&d->thread, &idle0_task.thread, sizeof(d->thread)); diff -r a28d3cf3832c -r fe2f4bbcf869 xen/common/sched_bvt.c --- a/xen/common/sched_bvt.c Mon Oct 04 14:55:47 2004 +0000 +++ b/xen/common/sched_bvt.c Tue Oct 05 09:53:10 2004 +0000 @@ -37,7 +37,7 @@ struct bvt_dom_info u32 evt; /* effective virtual time */ int warpback; /* warp? */ int warp; /* warp set and within the warp - limits*/ + limits*/ s32 warp_value; /* virtual time warp */ s_time_t warpl; /* warp limit */ struct ac_timer warp_timer; /* deals with warpl */ @@ -47,12 +47,10 @@ struct bvt_dom_info struct bvt_cpu_info { - spinlock_t run_lock; /* protects runqueue */ - struct list_head runqueue; /* runqueue for given processor */ - unsigned long svt; /* XXX check this is unsigned long! */ + struct list_head runqueue; + unsigned long svt; }; - #define BVT_INFO(p) ((struct bvt_dom_info *)(p)->sched_priv) #define CPU_INFO(cpu) ((struct bvt_cpu_info *)(schedule_data[cpu]).sched_priv) #define RUNLIST(p) ((struct list_head *)&(BVT_INFO(p)->run_list)) @@ -64,13 +62,8 @@ struct bvt_cpu_info #define TIME_SLOP (s32)MICROSECS(50) /* allow time to slip a bit */ static s32 ctx_allow = (s32)MILLISECS(5); /* context switch allowance */ -/* SLAB cache for struct bvt_dom_info objects */ static xmem_cache_t *dom_info_cache; -/* - * Wrappers for run-queue management. Must be called with the run_lock - * held. - */ static inline void __add_to_runqueue_head(struct domain *d) { list_add(RUNLIST(d), RUNQUEUE(d->processor)); @@ -98,43 +91,42 @@ static inline int __task_on_runqueue(str static void warp_timer_fn(unsigned long pointer) { struct bvt_dom_info *inf = (struct bvt_dom_info *)pointer; - unsigned long flags; + unsigned int cpu = inf->domain->processor; - spin_lock_irqsave(&CPU_INFO(inf->domain->processor)->run_lock, flags); + spin_lock_irq(&schedule_data[cpu].schedule_lock); + inf->warp = 0; + /* unwarp equal to zero => stop warping */ - if(inf->warpu == 0) + if ( inf->warpu == 0 ) { inf->warpback = 0; - goto reschedule; + cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); } /* set unwarp timer */ inf->unwarp_timer.expires = NOW() + inf->warpu; add_ac_timer(&inf->unwarp_timer); - spin_unlock_irqrestore(&CPU_INFO(inf->domain->processor)->run_lock, flags); -reschedule: - cpu_raise_softirq(inf->domain->processor, SCHEDULE_SOFTIRQ); + spin_unlock_irq(&schedule_data[cpu].schedule_lock); } static void unwarp_timer_fn(unsigned long pointer) { - struct bvt_dom_info *inf = (struct bvt_dom_info *)pointer; - unsigned long flags; + struct bvt_dom_info *inf = (struct bvt_dom_info *)pointer; + unsigned int cpu = inf->domain->processor; - spin_lock_irqsave(&CPU_INFO(inf->domain->processor)->run_lock, flags); - if(inf->warpback) + spin_lock_irq(&schedule_data[cpu].schedule_lock); + + if ( inf->warpback ) { inf->warp = 1; - cpu_raise_softirq(inf->domain->processor, SCHEDULE_SOFTIRQ); + cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); } - - spin_unlock_irqrestore(&CPU_INFO(inf->domain->processor)->run_lock, flags); + + spin_unlock_irq(&schedule_data[cpu].schedule_lock); } - - static inline u32 calc_avt(struct domain *d, s_time_t now) { u32 ranfor, mcus; @@ -146,15 +138,14 @@ static inline u32 calc_avt(struct domain return inf->avt + mcus * inf->mcu_advance; } - /* * Calculate the effective virtual time for a domain. Take into account * warping limits */ static inline u32 calc_evt(struct domain *d, u32 avt) { - struct bvt_dom_info *inf = BVT_INFO(d); - /* TODO The warp routines need to be rewritten GM */ + struct bvt_dom_info *inf = BVT_INFO(d); + /* TODO The warp routines need to be rewritten GM */ if ( inf->warp ) return avt - inf->warp_value; @@ -168,26 +159,25 @@ static inline u32 calc_evt(struct domain * * Returns non-zero on failure. */ -int bvt_alloc_task(struct domain *p) +int bvt_alloc_task(struct domain *d) { - p->sched_priv = xmem_cache_alloc(dom_info_cache); - if ( p->sched_priv == NULL ) + if ( (d->sched_priv = xmem_cache_alloc(dom_info_cache)) == NULL ) return -1; - + memset(d->sched_priv, 0, sizeof(struct bvt_dom_info)); return 0; } /* * Add and remove a domain */ -void bvt_add_task(struct domain *p) +void bvt_add_task(struct domain *d) { - struct bvt_dom_info *inf = BVT_INFO(p); + struct bvt_dom_info *inf = BVT_INFO(d); ASSERT(inf != NULL); - ASSERT(p != NULL); + ASSERT(d != NULL); inf->mcu_advance = MCU_ADVANCE; - inf->domain = p; + inf->domain = d; inf->warpback = 0; /* Set some default values here. */ inf->warp = 0; @@ -196,135 +186,95 @@ void bvt_add_task(struct domain *p) inf->warpu = MILLISECS(1000); /* initialise the timers */ init_ac_timer(&inf->warp_timer); - inf->warp_timer.cpu = p->processor; + inf->warp_timer.cpu = d->processor; inf->warp_timer.data = (unsigned long)inf; inf->warp_timer.function = &warp_timer_fn; init_ac_timer(&inf->unwarp_timer); - inf->unwarp_timer.cpu = p->processor; + inf->unwarp_timer.cpu = d->processor; inf->unwarp_timer.data = (unsigned long)inf; inf->unwarp_timer.function = &unwarp_timer_fn; - if ( p->domain == IDLE_DOMAIN_ID ) + if ( d->domain == IDLE_DOMAIN_ID ) { inf->avt = inf->evt = ~0U; } else { /* Set avt and evt to system virtual time. */ - inf->avt = CPU_SVT(p->processor); - inf->evt = CPU_SVT(p->processor); - } - - return; + inf->avt = CPU_SVT(d->processor); + inf->evt = CPU_SVT(d->processor); + } } int bvt_init_idle_task(struct domain *p) { - unsigned long flags; - - if(bvt_alloc_task(p) < 0) return -1; + if ( bvt_alloc_task(p) < 0 ) + return -1; bvt_add_task(p); - spin_lock_irqsave(&CPU_INFO(p->processor)->run_lock, flags); - set_bit(DF_RUNNING, &p->flags); if ( !__task_on_runqueue(p) ) __add_to_runqueue_head(p); - spin_unlock_irqrestore(&CPU_INFO(p->processor)->run_lock, flags); - return 0; } void bvt_wake(struct domain *d) { - unsigned long flags; struct bvt_dom_info *inf = BVT_INFO(d); struct domain *curr; s_time_t now, r_time; int cpu = d->processor; u32 curr_evt; - /* The runqueue accesses must be protected */ - spin_lock_irqsave(&CPU_INFO(cpu)->run_lock, flags); - - /* If on the runqueue already then someone has done the wakeup work. */ if ( unlikely(__task_on_runqueue(d)) ) - { - spin_unlock_irqrestore(&CPU_INFO(cpu)->run_lock, flags); return; - } __add_to_runqueue_head(d); now = NOW(); /* Set the BVT parameters. AVT should always be updated - if CPU migration ocurred.*/ + if CPU migration ocurred.*/ if ( inf->avt < CPU_SVT(cpu) || - unlikely(test_bit(DF_MIGRATED, &d->flags)) ) + unlikely(test_bit(DF_MIGRATED, &d->flags)) ) inf->avt = CPU_SVT(cpu); /* Deal with warping here. */ inf->evt = calc_evt(d, inf->avt); - spin_unlock_irqrestore(&CPU_INFO(cpu)->run_lock, flags); - - /* Access to schedule_data protected by schedule_lock */ - spin_lock_irqsave(&schedule_data[cpu].schedule_lock, flags); curr = schedule_data[cpu].curr; curr_evt = calc_evt(curr, calc_avt(curr, now)); /* Calculate the time the current domain would run assuming the second smallest evt is of the newly woken domain */ r_time = curr->lastschd + - ((inf->evt - curr_evt) / BVT_INFO(curr)->mcu_advance) + - ctx_allow; + ((inf->evt - curr_evt) / BVT_INFO(curr)->mcu_advance) + + ctx_allow; if ( is_idle_task(curr) || (inf->evt <= curr_evt) ) cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); else if ( schedule_data[cpu].s_timer.expires > r_time ) mod_ac_timer(&schedule_data[cpu].s_timer, r_time); - - spin_unlock_irqrestore(&schedule_data[cpu].schedule_lock, flags); } static void bvt_sleep(struct domain *d) { - unsigned long flags; - if ( test_bit(DF_RUNNING, &d->flags) ) cpu_raise_softirq(d->processor, SCHEDULE_SOFTIRQ); - else - { - /* The runqueue accesses must be protected */ - spin_lock_irqsave(&CPU_INFO(d->processor)->run_lock, flags); - - - if ( __task_on_runqueue(d) ) - __del_from_runqueue(d); - - spin_unlock_irqrestore(&CPU_INFO(d->processor)->run_lock, flags); - } + else if ( __task_on_runqueue(d) ) + __del_from_runqueue(d); } /** * bvt_free_task - free BVT private structures for a task - * @p: task + * @d: task */ -void bvt_free_task(struct domain *p) +void bvt_free_task(struct domain *d) { - ASSERT( p->sched_priv != NULL ); - xmem_cache_free( dom_info_cache, p->sched_priv ); -} - - -/* - * Block the currently-executing domain until a pertinent event occurs. - */ -static void bvt_do_block(struct domain *p) -{ + ASSERT(d->sched_priv != NULL); + xmem_cache_free(dom_info_cache, d->sched_priv); } /* Control the scheduler. */ @@ -333,24 +283,19 @@ int bvt_ctl(struct sched_ctl_cmd *cmd) struct bvt_ctl *params = &cmd->u.bvt; if ( cmd->direction == SCHED_INFO_PUT ) - { ctx_allow = params->ctx_allow; - } else - { params->ctx_allow = ctx_allow; - } return 0; } /* Adjust scheduling parameter for a given domain. */ -int bvt_adjdom(struct domain *p, - struct sched_adjdom_cmd *cmd) +int bvt_adjdom( + struct domain *d, struct sched_adjdom_cmd *cmd) { struct bvt_adjdom *params = &cmd->u.bvt; - unsigned long flags; - + if ( cmd->direction == SCHED_INFO_PUT ) { u32 mcu_adv = params->mcu_adv; @@ -359,27 +304,17 @@ int bvt_adjdom(struct domain *p, s_time_t warpl = params->warpl; s_time_t warpu = params->warpu; - struct bvt_dom_info *inf = BVT_INFO(p); + struct bvt_dom_info *inf = BVT_INFO(d); DPRINTK("Get domain %u bvt mcu_adv=%u, warpback=%d, warpvalue=%d, " "warpl=%lld, warpu=%lld\n", - p->domain, inf->mcu_advance, inf->warpback, inf->warp_value, + d->domain, inf->mcu_advance, inf->warpback, inf->warp_value, inf->warpl, inf->warpu); /* Sanity -- this can avoid divide-by-zero. */ - if ( mcu_adv == 0 ) - { - printk("Mcu advance must not be set to 0 (domain %d)\n",p->domain); + if ( (mcu_adv == 0) || (warpl < 0) || (warpu < 0) ) return -EINVAL; - } - else if ( warpl < 0 || warpu < 0) - { - printk("Warp limits must be >= 0 (domain %d)\n", p->domain); - return -EINVAL; - } - - - spin_lock_irqsave(&CPU_INFO(p->processor)->run_lock, flags); + inf->mcu_advance = mcu_adv; inf->warpback = warpback; /* The warp should be the same as warpback */ @@ -391,27 +326,23 @@ int bvt_adjdom(struct domain *p, /* If the unwarp timer set up it needs to be removed */ rem_ac_timer(&inf->unwarp_timer); /* If we stop warping the warp timer needs to be removed */ - if(!warpback) + if ( !warpback ) rem_ac_timer(&inf->warp_timer); DPRINTK("Get domain %u bvt mcu_adv=%u, warpback=%d, warpvalue=%d, " "warpl=%lld, warpu=%lld\n", - p->domain, inf->mcu_advance, inf->warpback, inf->warp_value, + d->domain, inf->mcu_advance, inf->warpback, inf->warp_value, inf->warpl, inf->warpu); - spin_unlock_irqrestore(&CPU_INFO(p->processor)->run_lock, flags); } else if ( cmd->direction == SCHED_INFO_GET ) { - struct bvt_dom_info *inf = BVT_INFO(p); - - spin_lock_irqsave(&CPU_INFO(p->processor)->run_lock, flags); + struct bvt_dom_info *inf = BVT_INFO(d); params->mcu_adv = inf->mcu_advance; params->warpvalue = inf->warp_value; params->warpback = inf->warpback; params->warpl = inf->warpl; params->warpu = inf->warpu; - spin_unlock_irqrestore(&CPU_INFO(p->processor)->run_lock, flags); } return 0; @@ -427,23 +358,19 @@ int bvt_adjdom(struct domain *p, */ static task_slice_t bvt_do_schedule(s_time_t now) { - unsigned long flags; - struct domain *prev = current, *next = NULL, *next_prime, *p; + struct domain *prev = current, *next = NULL, *next_prime, *p; struct list_head *tmp; int cpu = prev->processor; s32 r_time; /* time for new dom to run */ u32 next_evt, next_prime_evt, min_avt; - struct bvt_dom_info *prev_inf = BVT_INFO(prev), - *p_inf = NULL, - *next_inf = NULL, - *next_prime_inf = NULL; + struct bvt_dom_info *prev_inf = BVT_INFO(prev); + struct bvt_dom_info *p_inf = NULL; + struct bvt_dom_info *next_inf = NULL; + struct bvt_dom_info *next_prime_inf = NULL; task_slice_t ret; - ASSERT(prev->sched_priv != NULL); ASSERT(prev_inf != NULL); - spin_lock_irqsave(&CPU_INFO(cpu)->run_lock, flags); - ASSERT(__task_on_runqueue(prev)); if ( likely(!is_idle_task(prev)) ) @@ -511,8 +438,6 @@ static task_slice_t bvt_do_schedule(s_ti add_ac_timer(&next_inf->warp_timer); } - spin_unlock_irqrestore(&CPU_INFO(cpu)->run_lock, flags); - /* Extract the domain pointers from the dom infos */ next = next_inf->domain; next_prime = next_prime_inf->domain; @@ -524,9 +449,9 @@ static task_slice_t bvt_do_schedule(s_ti /* check for virtual time overrun on this cpu */ if ( CPU_SVT(cpu) >= 0xf0000000 ) { - u_long t_flags; - - write_lock_irqsave(&tasklist_lock, t_flags); + ASSERT(!local_irq_is_enabled()); + + write_lock(&tasklist_lock); for_each_domain ( p ) { @@ -538,7 +463,7 @@ static task_slice_t bvt_do_schedule(s_ti } } - write_unlock_irqrestore(&tasklist_lock, t_flags); + write_unlock(&tasklist_lock); CPU_SVT(cpu) -= 0xe0000000; } @@ -591,43 +516,29 @@ static void bvt_dump_settings(void) static void bvt_dump_cpu_state(int i) { - unsigned long flags; struct list_head *list, *queue; int loop = 0; struct bvt_dom_info *d_inf; struct domain *d; - spin_lock_irqsave(&CPU_INFO(i)->run_lock, flags); printk("svt=0x%08lX ", CPU_SVT(i)); queue = RUNQUEUE(i); printk("QUEUE rq %lx n: %lx, p: %lx\n", (unsigned long)queue, - (unsigned long) queue->next, (unsigned long) queue->prev); + (unsigned long) queue->next, (unsigned long) queue->prev); list_for_each ( list, queue ) { d_inf = list_entry(list, struct bvt_dom_info, run_list); d = d_inf->domain; printk("%3d: %u has=%c ", loop++, d->domain, - test_bit(DF_RUNNING, &d->flags) ? 'T':'F'); + test_bit(DF_RUNNING, &d->flags) ? 'T':'F'); bvt_dump_runq_el(d); printk("c=0x%X%08X\n", (u32)(d->cpu_time>>32), (u32)d->cpu_time); printk(" l: %lx n: %lx p: %lx\n", - (unsigned long)list, (unsigned long)list->next, - (unsigned long)list->prev); + (unsigned long)list, (unsigned long)list->next, + (unsigned long)list->prev); } - spin_unlock_irqrestore(&CPU_INFO(i)->run_lock, flags); -} - -/* We use cache to create the bvt_dom_infos - this functions makes sure that the run_list - is initialised properly. - Call to __task_on_runqueue needs to return false */ -static void cache_constructor(void *arg1, xmem_cache_t *arg2, unsigned long arg3) -{ - struct bvt_dom_info *dom_inf = (struct bvt_dom_info*)arg1; - dom_inf->run_list.next = NULL; - dom_inf->run_list.prev = NULL; } /* Initialise the data structures. */ @@ -646,15 +557,12 @@ int bvt_init_scheduler() } INIT_LIST_HEAD(RUNQUEUE(i)); - spin_lock_init(&CPU_INFO(i)->run_lock); CPU_SVT(i) = 0; /* XXX do I really need to do this? */ } - dom_info_cache = xmem_cache_create("BVT dom info", - sizeof(struct bvt_dom_info), - 0, 0, cache_constructor, NULL); - + dom_info_cache = xmem_cache_create( + "BVT dom info", sizeof(struct bvt_dom_info), 0, 0, NULL, NULL); if ( dom_info_cache == NULL ) { printk("BVT: Failed to allocate domain info SLAB cache"); @@ -664,8 +572,6 @@ int bvt_init_scheduler() return 0; } - - struct scheduler sched_bvt_def = { .name = "Borrowed Virtual Time", .opt_name = "bvt", @@ -676,7 +582,6 @@ struct scheduler sched_bvt_def = { .alloc_task = bvt_alloc_task, .add_task = bvt_add_task, .free_task = bvt_free_task, - .do_block = bvt_do_block, .do_schedule = bvt_do_schedule, .control = bvt_ctl, .adjdom = bvt_adjdom, @@ -685,4 +590,3 @@ struct scheduler sched_bvt_def = { .sleep = bvt_sleep, .wake = bvt_wake, }; - diff -r a28d3cf3832c -r fe2f4bbcf869 xen/common/schedule.c --- a/xen/common/schedule.c Mon Oct 04 14:55:47 2004 +0000 +++ b/xen/common/schedule.c Tue Oct 05 09:53:10 2004 +0000 @@ -67,16 +67,19 @@ static void fallback_timer_fn(unsigned l /* This is global for now so that private implementations can reach it */ schedule_data_t schedule_data[NR_CPUS]; -/* - * TODO: It would be nice if the schedulers array could get populated - * automagically without having to hack the code in here. - */ -extern struct scheduler sched_bvt_def, sched_fbvt_def, sched_rrobin_def, sched_atropos_def; -static struct scheduler *schedulers[] = { &sched_bvt_def, - &sched_fbvt_def, - &sched_rrobin_def, - &sched_atropos_def, - NULL}; +extern struct scheduler sched_bvt_def; +extern struct scheduler sched_fbvt_def; +extern struct scheduler sched_rrobin_def; +extern struct scheduler sched_atropos_def; +static struct scheduler *schedulers[] = { + &sched_bvt_def, +#ifdef BROKEN_SCHEDULERS + &sched_fbvt_def, + &sched_rrobin_def, + &sched_atropos_def, +#endif + NULL +}; /* Operations for the current scheduler. */ static struct scheduler ops; @@ -155,21 +158,20 @@ void sched_rem_domain(struct domain *d) void init_idle_task(void) { - struct domain *d = current; - - if ( SCHED_OP(init_idle_task, d) < 0) - panic("Failed to initialise idle task for processor %d",d->processor); + if ( SCHED_OP(init_idle_task, current) < 0 ) + BUG(); } void domain_sleep(struct domain *d) { unsigned long flags; - /* sleep and wake protected by domain's sleep_lock */ - spin_lock_irqsave(&d->sleep_lock, flags); + spin_lock_irqsave(&schedule_data[d->processor].schedule_lock, flags); + if ( likely(!domain_runnable(d)) ) SCHED_OP(sleep, d); - spin_unlock_irqrestore(&d->sleep_lock, flags); + + spin_unlock_irqrestore(&schedule_data[d->processor].schedule_lock, flags); /* Synchronous. */ while ( test_bit(DF_RUNNING, &d->flags) && !domain_runnable(d) ) @@ -181,10 +183,10 @@ void domain_sleep(struct domain *d) void domain_wake(struct domain *d) { - unsigned long flags; + unsigned long flags; - spin_lock_irqsave(&d->sleep_lock, flags); - + spin_lock_irqsave(&schedule_data[d->processor].schedule_lock, flags); + if ( likely(domain_runnable(d)) ) { TRACE_2D(TRC_SCHED_WAKE, d->domain, d); @@ -196,7 +198,7 @@ void domain_wake(struct domain *d) clear_bit(DF_MIGRATED, &d->flags); - spin_unlock_irqrestore(&d->sleep_lock, flags); + spin_unlock_irqrestore(&schedule_data[d->processor].schedule_lock, flags); } /* Block the currently-executing domain until a pertinent event occurs. */ @@ -218,7 +220,6 @@ static long do_yield(void) return 0; } - /* * Demultiplex scheduler-related hypercalls. */ @@ -292,24 +293,25 @@ long sched_ctl(struct sched_ctl_cmd *cmd /* Adjust scheduling parameter for a given domain. */ long sched_adjdom(struct sched_adjdom_cmd *cmd) { - struct domain *p; - + struct domain *d; + if ( cmd->sched_id != ops.sched_id ) return -EINVAL; if ( cmd->direction != SCHED_INFO_PUT && cmd->direction != SCHED_INFO_GET ) return -EINVAL; - p = find_domain_by_id(cmd->domain); - - if( p == NULL ) + d = find_domain_by_id(cmd->domain); + if ( d == NULL ) return -ESRCH; - TRACE_1D(TRC_SCHED_ADJDOM, p->domain); + TRACE_1D(TRC_SCHED_ADJDOM, d->domain); - SCHED_OP(adjdom, p, cmd); + spin_lock_irq(&schedule_data[d->processor].schedule_lock); + SCHED_OP(adjdom, d, cmd); + spin_unlock_irq(&schedule_data[d->processor].schedule_lock); - put_domain(p); + put_domain(d); return 0; } @@ -335,7 +337,6 @@ void __enter_scheduler(void) rem_ac_timer(&schedule_data[cpu].s_timer); ASSERT(!in_irq()); - // TODO - move to specific scheduler ASSERT(__task_on_runqueue(prev)); if ( test_bit(DF_BLOCKED, &prev->flags) ) { @@ -362,6 +363,9 @@ void __enter_scheduler(void) schedule_data[cpu].s_timer.expires = now + r_time; add_ac_timer(&schedule_data[cpu].s_timer); + /* Must be protected by the schedule_lock! */ + set_bit(DF_RUNNING, &next->flags); + spin_unlock_irq(&schedule_data[cpu].schedule_lock); /* Ensure that the domain has an up-to-date time base. */ @@ -405,7 +409,6 @@ void __enter_scheduler(void) * without warning). */ clear_bit(DF_RUNNING, &prev->flags); - set_bit(DF_RUNNING, &next->flags); /* Mark a timer event for the newly-scheduled domain. */ if ( !is_idle_task(next) ) @@ -549,15 +552,23 @@ void dump_runq(u_char key, void *dev_id, { s_time_t now = NOW(); int i; + unsigned long flags; + + local_irq_save(flags); printk("Scheduler: %s (%s)\n", ops.name, ops.opt_name); SCHED_OP(dump_settings); printk("NOW=0x%08X%08X\n", (u32)(now>>32), (u32)now); + for ( i = 0; i < smp_num_cpus; i++ ) { + spin_lock(&schedule_data[i].schedule_lock); printk("CPU[%02d] ", i); SCHED_OP(dump_cpu_state,i); + spin_unlock(&schedule_data[i].schedule_lock); } + + local_irq_restore(flags); } #if defined(WAKE_HISTO) || defined(BLOCKTIME_HISTO) diff -r a28d3cf3832c -r fe2f4bbcf869 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Mon Oct 04 14:55:47 2004 +0000 +++ b/xen/include/xen/sched.h Tue Oct 05 09:53:10 2004 +0000 @@ -97,7 +97,6 @@ struct domain /* Scheduling. */ int shutdown_code; /* code value from OS (if DF_SHUTDOWN). */ - spinlock_t sleep_lock; /* wake/sleep lock */ s_time_t lastschd; /* time this domain was last scheduled */ s_time_t lastdeschd; /* time this domain was last descheduled */ s_time_t cpu_time; /* total CPU time received till now */