[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Clean up domain shutdown and modification of vcpu
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 3eeabf448f91642f9148120564f86062b4dbb0de # Parent 01a854cd884838ef00e9a6d7c87539d594a8f33a Clean up domain shutdown and modification of vcpu processor affinity. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> diff -r 01a854cd8848 -r 3eeabf448f91 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Fri Jan 6 15:24:46 2006 +++ b/xen/arch/ia64/xen/domain.c Fri Jan 6 15:47:25 2006 @@ -1070,15 +1070,6 @@ vcpu_pend_interrupt(dom0->vcpu[0],irq); } -void vcpu_migrate_cpu(struct vcpu *v, int newcpu) -{ - if ( v->processor == newcpu ) - return; - - set_bit(_VCPUF_cpu_migrated, &v->vcpu_flags); - v->processor = newcpu; -} - void sync_vcpu_execstate(struct vcpu *v) { ia64_save_fpu(v->arch._thread.fph); diff -r 01a854cd8848 -r 3eeabf448f91 xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Fri Jan 6 15:24:46 2006 +++ b/xen/arch/ia64/xen/xensetup.c Fri Jan 6 15:47:25 2006 @@ -382,7 +382,7 @@ panic("Could not set up DOM0 guest OS\n"); /* PIN domain0 on CPU 0. */ - dom0->vcpu[0]->cpumask = cpumask_of_cpu(0); + dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0); #ifdef CLONE_DOMAIN0 { diff -r 01a854cd8848 -r 3eeabf448f91 xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c Fri Jan 6 15:24:46 2006 +++ b/xen/arch/x86/dom0_ops.c Fri Jan 6 15:47:25 2006 @@ -36,13 +36,13 @@ static void write_msr_for(void *unused) { - if ( ((1 << current->processor) & msr_cpu_mask) ) + if ( ((1 << smp_processor_id()) & msr_cpu_mask) ) (void)wrmsr_user(msr_addr, msr_lo, msr_hi); } static void read_msr_for(void *unused) { - if ( ((1 << current->processor) & msr_cpu_mask) ) + if ( ((1 << smp_processor_id()) & msr_cpu_mask) ) (void)rdmsr_user(msr_addr, msr_lo, msr_hi); } diff -r 01a854cd8848 -r 3eeabf448f91 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Jan 6 15:24:46 2006 +++ b/xen/arch/x86/domain.c Fri Jan 6 15:47:25 2006 @@ -326,21 +326,6 @@ return 0; } -void vcpu_migrate_cpu(struct vcpu *v, int newcpu) -{ - if ( v->processor == newcpu ) - return; - - set_bit(_VCPUF_cpu_migrated, &v->vcpu_flags); - v->processor = newcpu; - - if ( VMX_DOMAIN(v) ) - { - __vmpclear(virt_to_phys(v->arch.arch_vmx.vmcs)); - v->arch.schedule_tail = arch_vmx_do_relaunch; - } -} - /* This is called by arch_final_setup_guest and do_boot_vcpu */ int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c) diff -r 01a854cd8848 -r 3eeabf448f91 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Fri Jan 6 15:24:46 2006 +++ b/xen/arch/x86/mm.c Fri Jan 6 15:47:25 2006 @@ -2497,7 +2497,7 @@ l1_pgentry_t val = l1e_from_intpte(val64); struct vcpu *v = current; struct domain *d = v->domain; - unsigned int cpu = v->processor; + unsigned int cpu = smp_processor_id(); unsigned long vmask, bmap_ptr; cpumask_t pmask; int rc = 0; diff -r 01a854cd8848 -r 3eeabf448f91 xen/arch/x86/vmx.c --- a/xen/arch/x86/vmx.c Fri Jan 6 15:24:46 2006 +++ b/xen/arch/x86/vmx.c Fri Jan 6 15:47:25 2006 @@ -53,7 +53,7 @@ integer_param("vmx_debug", opt_vmx_debug_level); static unsigned long trace_values[NR_CPUS][4]; -#define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value +#define TRACE_VMEXIT(index,value) trace_values[smp_processor_id()][index]=value static int vmx_switch_on; @@ -1950,9 +1950,12 @@ asmlinkage void trace_vmentry (void) { - TRACE_5D(TRC_VMENTRY,trace_values[current->processor][0], - trace_values[current->processor][1],trace_values[current->processor][2], - trace_values[current->processor][3],trace_values[current->processor][4]); + TRACE_5D(TRC_VMENTRY, + trace_values[smp_processor_id()][0], + trace_values[smp_processor_id()][1], + trace_values[smp_processor_id()][2], + trace_values[smp_processor_id()][3], + trace_values[smp_processor_id()][4]); TRACE_VMEXIT(0,9); TRACE_VMEXIT(1,9); TRACE_VMEXIT(2,9); diff -r 01a854cd8848 -r 3eeabf448f91 xen/arch/x86/vmx_vmcs.c --- a/xen/arch/x86/vmx_vmcs.c Fri Jan 6 15:24:46 2006 +++ b/xen/arch/x86/vmx_vmcs.c Fri Jan 6 15:47:25 2006 @@ -355,6 +355,8 @@ __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom()); v->arch.schedule_tail = arch_vmx_do_resume; + v->arch.arch_vmx.launch_cpu = smp_processor_id(); + /* init guest tsc to start from 0 */ rdtscll(host_tsc); v->arch.arch_vmx.tsc_offset = 0 - host_tsc; @@ -637,11 +639,21 @@ void arch_vmx_do_resume(struct vcpu *v) { - u64 vmcs_phys_ptr = (u64) virt_to_phys(v->arch.arch_vmx.vmcs); - - load_vmcs(&v->arch.arch_vmx, vmcs_phys_ptr); - vmx_do_resume(v); - reset_stack_and_jump(vmx_asm_do_resume); + if ( v->arch.arch_vmx.launch_cpu == smp_processor_id() ) + { + load_vmcs(&v->arch.arch_vmx, virt_to_phys(v->arch.arch_vmx.vmcs)); + vmx_do_resume(v); + reset_stack_and_jump(vmx_asm_do_resume); + } + else + { + __vmpclear(virt_to_phys(v->arch.arch_vmx.vmcs)); + load_vmcs(&v->arch.arch_vmx, virt_to_phys(v->arch.arch_vmx.vmcs)); + vmx_do_resume(v); + vmx_set_host_env(v); + v->arch.arch_vmx.launch_cpu = smp_processor_id(); + reset_stack_and_jump(vmx_asm_do_relaunch); + } } void arch_vmx_do_launch(struct vcpu *v) @@ -661,18 +673,6 @@ } vmx_do_launch(v); reset_stack_and_jump(vmx_asm_do_launch); -} - -void arch_vmx_do_relaunch(struct vcpu *v) -{ - u64 vmcs_phys_ptr = (u64) virt_to_phys(v->arch.arch_vmx.vmcs); - - load_vmcs(&v->arch.arch_vmx, vmcs_phys_ptr); - vmx_do_resume(v); - vmx_set_host_env(v); - v->arch.schedule_tail = arch_vmx_do_resume; - - reset_stack_and_jump(vmx_asm_do_relaunch); } #endif /* CONFIG_VMX */ diff -r 01a854cd8848 -r 3eeabf448f91 xen/common/dom0_ops.c --- a/xen/common/dom0_ops.c Fri Jan 6 15:24:46 2006 +++ b/xen/common/dom0_ops.c Fri Jan 6 15:47:25 2006 @@ -289,6 +289,7 @@ domid_t dom = op->u.setvcpuaffinity.domain; struct domain *d = find_domain_by_id(dom); struct vcpu *v; + cpumask_t new_affinity; if ( d == NULL ) { @@ -319,14 +320,13 @@ break; } - memcpy(cpus_addr(v->cpu_affinity), + new_affinity = v->cpu_affinity; + memcpy(cpus_addr(new_affinity), &op->u.setvcpuaffinity.cpumap, min((int)BITS_TO_LONGS(NR_CPUS), (int)sizeof(op->u.setvcpuaffinity.cpumap))); - vcpu_pause(v); - vcpu_migrate_cpu(v, first_cpu(v->cpu_affinity)); - vcpu_unpause(v); + ret = vcpu_set_affinity(v, &new_affinity); put_domain(d); } diff -r 01a854cd8848 -r 3eeabf448f91 xen/common/domain.c --- a/xen/common/domain.c Fri Jan 6 15:24:46 2006 +++ b/xen/common/domain.c Fri Jan 6 15:47:25 2006 @@ -173,8 +173,8 @@ BUG_ON(d == NULL); BUG_ON(d == current->domain); - BUG_ON(!test_bit(_DOMF_shuttingdown, &d->domain_flags)); - BUG_ON(test_bit(_DOMF_shutdown, &d->domain_flags)); + + LOCK_BIGLOCK(d); /* Make sure that every vcpu is descheduled before we finalise. */ for_each_vcpu ( d, v ) @@ -183,10 +183,13 @@ sync_pagetable_state(d); - set_bit(_DOMF_shutdown, &d->domain_flags); - clear_bit(_DOMF_shuttingdown, &d->domain_flags); - - send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC); + /* Don't set DOMF_shutdown until execution contexts are sync'ed. */ + if ( !test_and_set_bit(_DOMF_shutdown, &d->domain_flags) ) + send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC); + + UNLOCK_BIGLOCK(d); + + put_domain(d); } static __init int domain_shutdown_finaliser_init(void) @@ -222,16 +225,17 @@ /* Mark the domain as shutting down. */ d->shutdown_code = reason; - if ( !test_and_set_bit(_DOMF_shuttingdown, &d->domain_flags) ) - { - /* This vcpu won the race to finalise the shutdown. */ - domain_shuttingdown[smp_processor_id()] = d; - raise_softirq(DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ); - } /* Put every vcpu to sleep, but don't wait (avoids inter-vcpu deadlock). */ for_each_vcpu ( d, v ) + { + atomic_inc(&v->pausecnt); vcpu_sleep_nosync(v); + } + + get_knownalive_domain(d); + domain_shuttingdown[smp_processor_id()] = d; + raise_softirq(DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ); } diff -r 01a854cd8848 -r 3eeabf448f91 xen/common/sched_bvt.c --- a/xen/common/sched_bvt.c Fri Jan 6 15:24:46 2006 +++ b/xen/common/sched_bvt.c Fri Jan 6 15:47:25 2006 @@ -31,7 +31,8 @@ struct list_head run_list; /* runqueue list pointers */ u32 avt; /* actual virtual time */ u32 evt; /* effective virtual time */ - struct vcpu *vcpu; + int migrated; /* migrated to a new CPU */ + struct vcpu *vcpu; struct bvt_dom_info *inf; }; @@ -250,9 +251,11 @@ /* Set the BVT parameters. AVT should always be updated if CPU migration ocurred.*/ - if ( einf->avt < CPU_SVT(cpu) || - unlikely(test_bit(_VCPUF_cpu_migrated, &v->vcpu_flags)) ) + if ( (einf->avt < CPU_SVT(cpu)) || einf->migrated ) + { einf->avt = CPU_SVT(cpu); + einf->migrated = 0; + } /* Deal with warping here. */ einf->evt = calc_evt(v, einf->avt); @@ -279,6 +282,22 @@ else if ( __task_on_runqueue(v) ) __del_from_runqueue(v); } + + +static int bvt_set_affinity(struct vcpu *v, cpumask_t *affinity) +{ + if ( v == current ) + return cpu_isset(v->processor, *affinity) ? 0 : -EBUSY; + + vcpu_pause(v); + v->cpu_affinity = *affinity; + v->processor = first_cpu(v->cpu_affinity); + EBVT_INFO(v)->migrated = 1; + vcpu_unpause(v); + + return 0; +} + /** * bvt_free_task - free BVT private structures for a task @@ -557,6 +576,7 @@ .dump_cpu_state = bvt_dump_cpu_state, .sleep = bvt_sleep, .wake = bvt_wake, + .set_affinity = bvt_set_affinity }; /* diff -r 01a854cd8848 -r 3eeabf448f91 xen/common/sched_sedf.c --- a/xen/common/sched_sedf.c Fri Jan 6 15:24:46 2006 +++ b/xen/common/sched_sedf.c Fri Jan 6 15:47:25 2006 @@ -325,21 +325,29 @@ list_insert_sort(RUNQ(d->processor), LIST(d), runq_comp); } + /* Allocates memory for per domain private scheduling data*/ -static int sedf_alloc_task(struct vcpu *d) { - PRINT(2,"sedf_alloc_task was called, domain-id %i.%i\n",d->domain->domain_id, - d->vcpu_id); - if (d->domain->sched_priv == NULL) { - if ((d->domain->sched_priv = - xmalloc(struct sedf_dom_info)) == NULL ) +static int sedf_alloc_task(struct vcpu *d) +{ + PRINT(2, "sedf_alloc_task was called, domain-id %i.%i\n", + d->domain->domain_id, d->vcpu_id); + + if ( d->domain->sched_priv == NULL ) + { + d->domain->sched_priv = xmalloc(struct sedf_dom_info); + if ( d->domain->sched_priv == NULL ) return -1; memset(d->domain->sched_priv, 0, sizeof(struct sedf_dom_info)); } - if ((d->sched_priv = xmalloc(struct sedf_vcpu_info)) == NULL ) + + if ( (d->sched_priv = xmalloc(struct sedf_vcpu_info)) == NULL ) return -1; + memset(d->sched_priv, 0, sizeof(struct sedf_vcpu_info)); + return 0; } + /* Setup the sedf_dom_info */ static void sedf_add_task(struct vcpu *d) @@ -363,14 +371,17 @@ INIT_LIST_HEAD(EXTRAQ(d->processor,EXTRA_UTIL_Q)); } - if (d->domain->domain_id==0) { + if ( d->domain->domain_id == 0 ) + { /*set dom0 to something useful to boot the machine*/ inf->period = MILLISECS(20); inf->slice = MILLISECS(15); inf->latency = 0; inf->deadl_abs = 0; inf->status = EXTRA_AWARE | SEDF_ASLEEP; - } else { + } + else + { /*other domains run in best effort mode*/ inf->period = WEIGHT_PERIOD; inf->slice = 0; @@ -379,14 +390,18 @@ inf->status = EXTRA_AWARE | SEDF_ASLEEP; inf->extraweight = 1; } + inf->period_orig = inf->period; inf->slice_orig = inf->slice; INIT_LIST_HEAD(&(inf->list)); INIT_LIST_HEAD(&(inf->extralist[EXTRA_PEN_Q])); INIT_LIST_HEAD(&(inf->extralist[EXTRA_UTIL_Q])); - if (!is_idle_domain(d->domain)) { + if ( !is_idle_domain(d->domain) ) + { extraq_check(d); - } else { + } + else + { EDOM_INFO(d)->deadl_abs = 0; EDOM_INFO(d)->status &= ~SEDF_ASLEEP; } @@ -396,19 +411,28 @@ static void sedf_free_task(struct domain *d) { int i; + PRINT(2,"sedf_free_task was called, domain-id %i\n",d->domain_id); + ASSERT(d->sched_priv != NULL); xfree(d->sched_priv); - for (i = 0; i < MAX_VIRT_CPUS; i++) - if ( d->vcpu[i] ) { + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + { + if ( d->vcpu[i] ) + { ASSERT(d->vcpu[i]->sched_priv != NULL); xfree(d->vcpu[i]->sched_priv); } -} - -/* handles the rescheduling, bookkeeping of domains running in their realtime-time :)*/ -static inline void desched_edf_dom (s_time_t now, struct vcpu* d) { + } +} + +/* + * Handles the rescheduling & bookkeeping of domains running in their + * guaranteed timeslice. + */ +static void desched_edf_dom(s_time_t now, struct vcpu* d) +{ struct sedf_vcpu_info* inf = EDOM_INFO(d); /*current domain is running in real time mode*/ @@ -418,27 +442,30 @@ /*scheduling decisions, which don't remove the running domain from the runq*/ - if ((inf->cputime < inf->slice) && sedf_runnable(d)) + if ( (inf->cputime < inf->slice) && sedf_runnable(d) ) return; __del_from_queue(d); /*manage bookkeeping (i.e. calculate next deadline, memorize overun-time of slice) of finished domains*/ - if (inf->cputime >= inf->slice) { + if ( inf->cputime >= inf->slice ) + { inf->cputime -= inf->slice; - if (inf->period < inf->period_orig) { + if ( inf->period < inf->period_orig ) + { /*this domain runs in latency scaling or burst mode*/ #if (UNBLOCK == UNBLOCK_BURST) /*if we are runnig in burst scaling wait for two periods before scaling periods up again*/ - if (now - inf->unblock_abs >= 2 * inf->period) + if ( (now - inf->unblock_abs) >= (2 * inf->period) ) #endif { inf->period *= 2; inf->slice *= 2; - if ((inf->period > inf->period_orig) || - (inf->slice > inf->slice_orig)) { + if ( (inf->period > inf->period_orig) || + (inf->slice > inf->slice_orig) ) + { /*reset slice & period*/ inf->period = inf->period_orig; inf->slice = inf->slice_orig; @@ -450,36 +477,46 @@ } /*add a runnable domain to the waitqueue*/ - if (sedf_runnable(d)) + if ( sedf_runnable(d) ) + { __add_to_waitqueue_sort(d); - else { + } + else + { /*we have a blocked realtime task -> remove it from exqs too*/ #if (EXTRA > EXTRA_OFF) #if (EXTRA == EXTRA_BLOCK_WEIGHT) - if (extraq_on(d, EXTRA_PEN_Q)) extraq_del(d, EXTRA_PEN_Q); -#endif - if (extraq_on(d, EXTRA_UTIL_Q)) extraq_del(d, EXTRA_UTIL_Q); -#endif - } + if ( extraq_on(d, EXTRA_PEN_Q) ) + extraq_del(d, EXTRA_PEN_Q); +#endif + if ( extraq_on(d, EXTRA_UTIL_Q) ) + extraq_del(d, EXTRA_UTIL_Q); +#endif + } + ASSERT(EQ(sedf_runnable(d), __task_on_queue(d))); ASSERT(IMPLY(extraq_on(d, EXTRA_UTIL_Q) || extraq_on(d, EXTRA_PEN_Q), sedf_runnable(d))); } + /* Update all elements on the queues */ -static inline void update_queues(s_time_t now, struct list_head* runq, - struct list_head* waitq) { - struct list_head *cur,*tmp; +static void update_queues( + s_time_t now, struct list_head *runq, struct list_head *waitq) +{ + struct list_head *cur, *tmp; struct sedf_vcpu_info *curinf; PRINT(3,"Updating waitq..\n"); + /*check for the first elements of the waitqueue, whether their next period has already started*/ list_for_each_safe(cur, tmp, waitq) { curinf = list_entry(cur, struct sedf_vcpu_info, list); PRINT(4,"\tLooking @ dom %i.%i\n", curinf->vcpu->domain->domain_id, curinf->vcpu->vcpu_id); - if (PERIOD_BEGIN(curinf) <= now) { + if ( PERIOD_BEGIN(curinf) <= now ) + { __del_from_queue(curinf->vcpu); __add_to_runqueue_sort(curinf->vcpu); } @@ -488,13 +525,16 @@ } PRINT(3,"Updating runq..\n"); + /*process the runq, find domains that are on the runqueue which shouldn't be there*/ list_for_each_safe(cur, tmp, runq) { curinf = list_entry(cur,struct sedf_vcpu_info,list); PRINT(4,"\tLooking @ dom %i.%i\n", curinf->vcpu->domain->domain_id, curinf->vcpu->vcpu_id); - if (unlikely(curinf->slice == 0)) { + + if ( unlikely(curinf->slice == 0) ) + { /*ignore domains with empty slice*/ PRINT(4,"\tUpdating zero-slice domain %i.%i\n", curinf->vcpu->domain->domain_id, @@ -504,7 +544,8 @@ /*move them to their next period*/ curinf->deadl_abs += curinf->period; /*ensure that the start of the next period is in the future*/ - if (unlikely(PERIOD_BEGIN(curinf) < now)) { + if ( unlikely(PERIOD_BEGIN(curinf) < now) ) + { curinf->deadl_abs += (DIV_UP(now - PERIOD_BEGIN(curinf), curinf->period)) * curinf->period; @@ -513,8 +554,10 @@ __add_to_waitqueue_sort(curinf->vcpu); continue; } - if (unlikely((curinf->deadl_abs < now) || - (curinf->cputime > curinf->slice))) { + + if ( unlikely((curinf->deadl_abs < now) || + (curinf->cputime > curinf->slice)) ) + { /*we missed the deadline or the slice was already finished... might hapen because of dom_adj.*/ @@ -550,6 +593,7 @@ PRINT(3,"done updating the queues\n"); } + #if (EXTRA > EXTRA_OFF) /* removes a domain from the head of the according extraQ and requeues it at a specified position: @@ -557,9 +601,10 @@ weighted ext.: insert in sorted list by score if the domain is blocked / has regained its short-block-loss time it is not put on any queue */ -static inline void desched_extra_dom(s_time_t now, struct vcpu* d) { +static void desched_extra_dom(s_time_t now, struct vcpu* d) +{ struct sedf_vcpu_info *inf = EDOM_INFO(d); - int i = extra_get_cur_q(inf); + int i = extra_get_cur_q(inf); #if (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) unsigned long oldscore; @@ -575,14 +620,15 @@ extraq_del(d, i); #if (EXTRA == EXTRA_ROUNDR) - if (sedf_runnable(d) && (inf->status & EXTRA_AWARE)) + if ( sedf_runnable(d) && (inf->status & EXTRA_AWARE) ) /*add to the tail if it is runnable => round-robin*/ extraq_add_tail(d, EXTRA_UTIL_Q); #elif (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) /*update the score*/ - oldscore = inf->score[i]; + oldscore = inf->score[i]; #if (EXTRA == EXTRA_BLOCK_WEIGHT) - if (i == EXTRA_PEN_Q) { + if ( i == EXTRA_PEN_Q ) + { /*domain was running in L0 extraq*/ /*reduce block lost, probably more sophistication here!*/ /*inf->short_block_lost_tot -= EXTRA_QUANTUM;*/ @@ -605,12 +651,13 @@ inf->score[EXTRA_PEN_Q] = (inf->period << 10) / inf->short_block_lost_tot; oldscore = 0; - } else + } + else #endif { /*domain was running in L1 extraq => score is inverse of utilization and is used somewhat incremental!*/ - if (!inf->extraweight) + if ( !inf->extraweight ) /*NB: use fixed point arithmetic with 10 bits*/ inf->score[EXTRA_UTIL_Q] = (inf->period << 10) / inf->slice; @@ -619,24 +666,32 @@ full (ie 100%) utilization is equivalent to 128 extraweight*/ inf->score[EXTRA_UTIL_Q] = (1<<17) / inf->extraweight; } + check_extra_queues: /* Adding a runnable domain to the right queue and removing blocked ones*/ - if (sedf_runnable(d)) { + if ( sedf_runnable(d) ) + { /*add according to score: weighted round robin*/ if (((inf->status & EXTRA_AWARE) && (i == EXTRA_UTIL_Q)) || ((inf->status & EXTRA_WANT_PEN_Q) && (i == EXTRA_PEN_Q))) extraq_add_sort_update(d, i, oldscore); } - else { + else + { /*remove this blocked domain from the waitq!*/ __del_from_queue(d); #if (EXTRA == EXTRA_BLOCK_WEIGHT) /*make sure that we remove a blocked domain from the other extraq too*/ - if (i == EXTRA_PEN_Q) { - if (extraq_on(d, EXTRA_UTIL_Q)) extraq_del(d, EXTRA_UTIL_Q); - } else { - if (extraq_on(d, EXTRA_PEN_Q)) extraq_del(d, EXTRA_PEN_Q); + if ( i == EXTRA_PEN_Q ) + { + if ( extraq_on(d, EXTRA_UTIL_Q) ) + extraq_del(d, EXTRA_UTIL_Q); + } + else + { + if ( extraq_on(d, EXTRA_PEN_Q) ) + extraq_del(d, EXTRA_PEN_Q); } #endif } @@ -647,16 +702,21 @@ } #endif -static inline struct task_slice sedf_do_extra_schedule (s_time_t now, - s_time_t end_xt, struct list_head *extraq[], int cpu) { + +static struct task_slice sedf_do_extra_schedule( + s_time_t now, s_time_t end_xt, struct list_head *extraq[], int cpu) +{ struct task_slice ret; struct sedf_vcpu_info *runinf; ASSERT(end_xt > now); + /* Enough time left to use for extratime? */ - if (end_xt - now < EXTRA_QUANTUM) + if ( end_xt - now < EXTRA_QUANTUM ) goto return_idle; + #if (EXTRA == EXTRA_BLOCK_WEIGHT) - if (!list_empty(extraq[EXTRA_PEN_Q])) { + if ( !list_empty(extraq[EXTRA_PEN_Q]) ) + { /*we still have elements on the level 0 extraq => let those run first!*/ runinf = list_entry(extraq[EXTRA_PEN_Q]->next, @@ -667,9 +727,12 @@ #ifdef SEDF_STATS runinf->pen_extra_slices++; #endif - } else -#endif - if (!list_empty(extraq[EXTRA_UTIL_Q])) { + } + else +#endif + { + if ( !list_empty(extraq[EXTRA_UTIL_Q]) ) + { /*use elements from the normal extraqueue*/ runinf = list_entry(extraq[EXTRA_UTIL_Q]->next, struct sedf_vcpu_info, @@ -680,6 +743,7 @@ } else goto return_idle; + } ASSERT(ret.time > 0); ASSERT(sedf_runnable(ret.task)); @@ -692,6 +756,8 @@ ASSERT(sedf_runnable(ret.task)); return ret; } + + /* Main scheduling function Reasons for calling this function are: -timeslice for the current period used up @@ -699,7 +765,7 @@ -and various others ;) in general: determine which domain to run next*/ static struct task_slice sedf_do_schedule(s_time_t now) { - int cpu = current->processor; + int cpu = smp_processor_id(); struct list_head *runq = RUNQ(cpu); struct list_head *waitq = WAITQ(cpu); #if (EXTRA > EXTRA_OFF) @@ -717,14 +783,15 @@ /* create local state of the status of the domain, in order to avoid inconsistent state during scheduling decisions, because data for domain_runnable is not protected by the scheduling lock!*/ - if(!domain_runnable(current)) + if ( !domain_runnable(current) ) inf->status |= SEDF_ASLEEP; - if (inf->status & SEDF_ASLEEP) + if ( inf->status & SEDF_ASLEEP ) inf->block_abs = now; #if (EXTRA > EXTRA_OFF) - if (unlikely(extra_runs(inf))) { + if ( unlikely(extra_runs(inf)) ) + { /*special treatment of domains running in extra time*/ desched_extra_dom(now, current); } @@ -739,10 +806,12 @@ /*now simply pick the first domain from the runqueue, which has the earliest deadline, because the list is sorted*/ - if (!list_empty(runq)) { + if ( !list_empty(runq) ) + { runinf = list_entry(runq->next,struct sedf_vcpu_info,list); ret.task = runinf->vcpu; - if (!list_empty(waitq)) { + if ( !list_empty(waitq) ) + { waitinf = list_entry(waitq->next, struct sedf_vcpu_info,list); /*rerun scheduler, when scheduled domain reaches it's @@ -751,14 +820,16 @@ ret.time = MIN(now + runinf->slice - runinf->cputime, PERIOD_BEGIN(waitinf)) - now; } - else { + else + { ret.time = runinf->slice - runinf->cputime; } CHECK(ret.time > 0); goto sched_done; } - if (!list_empty(waitq)) { + if ( !list_empty(waitq) ) + { waitinf = list_entry(waitq->next,struct sedf_vcpu_info, list); /*we could not find any suitable domain => look for domains that are aware of extratime*/ @@ -771,7 +842,8 @@ #endif CHECK(ret.time > 0); } - else { + else + { /*this could probably never happen, but one never knows...*/ /*it can... imagine a second CPU, which is pure scifi ATM, but one never knows ;)*/ @@ -782,11 +854,13 @@ sched_done: /*TODO: Do something USEFUL when this happens and find out, why it still can happen!!!*/ - if (ret.time<0) { + if ( ret.time < 0) + { printk("Ouch! We are seriously BEHIND schedule! %"PRIi64"\n", ret.time); ret.time = EXTRA_QUANTUM; } + EDOM_INFO(ret.task)->sched_start_abs = now; CHECK(ret.time > 0); ASSERT(sedf_runnable(ret.task)); @@ -794,30 +868,36 @@ return ret; } -static void sedf_sleep(struct vcpu *d) { - PRINT(2,"sedf_sleep was called, domain-id %i.%i\n",d->domain->domain_id, d->vcpu_id); - - if (is_idle_domain(d->domain)) + +static void sedf_sleep(struct vcpu *d) +{ + PRINT(2,"sedf_sleep was called, domain-id %i.%i\n", + d->domain->domain_id, d->vcpu_id); + + if ( is_idle_domain(d->domain) ) return; EDOM_INFO(d)->status |= SEDF_ASLEEP; - if ( test_bit(_VCPUF_running, &d->vcpu_flags) ) { + if ( test_bit(_VCPUF_running, &d->vcpu_flags) ) + { cpu_raise_softirq(d->processor, SCHEDULE_SOFTIRQ); } - else { + else + { if ( __task_on_queue(d) ) __del_from_queue(d); #if (EXTRA > EXTRA_OFF) - if (extraq_on(d, EXTRA_UTIL_Q)) + if ( extraq_on(d, EXTRA_UTIL_Q) ) extraq_del(d, EXTRA_UTIL_Q); #endif #if (EXTRA == EXTRA_BLOCK_WEIGHT) - if (extraq_on(d, EXTRA_PEN_Q)) + if ( extraq_on(d, EXTRA_PEN_Q) ) extraq_del(d, EXTRA_PEN_Q); #endif } } + /* This function wakes up a domain, i.e. moves them into the waitqueue * things to mention are: admission control is taking place nowhere at @@ -890,17 +970,21 @@ * -either behaviour can lead to missed deadlines in other domains as * opposed to approaches 1,2a,2b */ -static inline void unblock_short_vcons -(struct sedf_vcpu_info* inf, s_time_t now) { +#if (UNBLOCK <= UNBLOCK_SHORT_RESUME) +static void unblock_short_vcons(struct sedf_vcpu_info* inf, s_time_t now) +{ inf->deadl_abs += inf->period; inf->cputime = 0; } - -static inline void unblock_short_cons(struct sedf_vcpu_info* inf, s_time_t now) +#endif + +#if (UNBLOCK == UNBLOCK_SHORT_RESUME) +static void unblock_short_cons(struct sedf_vcpu_info* inf, s_time_t now) { /*treat blocked time as consumed by the domain*/ inf->cputime += now - inf->block_abs; - if (inf->cputime + EXTRA_QUANTUM > inf->slice) { + if ( (inf->cputime + EXTRA_QUANTUM) > inf->slice ) + { /*we don't have a reasonable amount of time in our slice left :( => start in next period!*/ unblock_short_vcons(inf, now); @@ -910,8 +994,11 @@ inf->short_cont++; #endif } -static inline void unblock_short_extra_support (struct sedf_vcpu_info* inf, - s_time_t now) { +#endif + +static void unblock_short_extra_support( + struct sedf_vcpu_info* inf, s_time_t now) +{ /*this unblocking scheme tries to support the domain, by assigning it a priority in extratime distribution according to the loss of time in this slice due to blocking*/ @@ -919,26 +1006,29 @@ /*no more realtime execution in this period!*/ inf->deadl_abs += inf->period; - if (likely(inf->block_abs)) { + if ( likely(inf->block_abs) ) + { //treat blocked time as consumed by the domain*/ /*inf->cputime += now - inf->block_abs;*/ /*penalty is time the domain would have had if it continued to run */ pen = (inf->slice - inf->cputime); - if (pen < 0) pen = 0; + if ( pen < 0 ) + pen = 0; /*accumulate all penalties over the periods*/ /*inf->short_block_lost_tot += pen;*/ /*set penalty to the current value*/ inf->short_block_lost_tot = pen; /*not sure which one is better.. but seems to work well...*/ - if (inf->short_block_lost_tot) { + if ( inf->short_block_lost_tot ) + { inf->score[0] = (inf->period << 10) / inf->short_block_lost_tot; #ifdef SEDF_STATS inf->pen_extra_blocks++; #endif - if (extraq_on(inf->vcpu, EXTRA_PEN_Q)) + if ( extraq_on(inf->vcpu, EXTRA_PEN_Q) ) /*remove domain for possible resorting!*/ extraq_del(inf->vcpu, EXTRA_PEN_Q); else @@ -951,36 +1041,53 @@ extraq_add_sort_update(inf->vcpu, EXTRA_PEN_Q, 0); } } + /*give it a fresh slice in the next period!*/ inf->cputime = 0; } -static inline void unblock_long_vcons(struct sedf_vcpu_info* inf, s_time_t now) + + +#if (UNBLOCK == UNBLOCK_ISOCHRONOUS_EDF) +static void unblock_long_vcons(struct sedf_vcpu_info* inf, s_time_t now) { /* align to next future period */ inf->deadl_abs += (DIV_UP(now - inf->deadl_abs, inf->period) +1) * inf->period; inf->cputime = 0; } - -static inline void unblock_long_cons_a (struct sedf_vcpu_info* inf, - s_time_t now) { +#endif + + +#if 0 +static void unblock_long_cons_a (struct sedf_vcpu_info* inf, s_time_t now) +{ /*treat the time the domain was blocked in the - CURRENT period as consumed by the domain*/ + CURRENT period as consumed by the domain*/ inf->cputime = (now - inf->deadl_abs) % inf->period; - if (inf->cputime + EXTRA_QUANTUM > inf->slice) { + if ( (inf->cputime + EXTRA_QUANTUM) > inf->slice ) + { /*we don't have a reasonable amount of time in our slice left :( => start in next period!*/ unblock_long_vcons(inf, now); } } -static inline void unblock_long_cons_b(struct sedf_vcpu_info* inf,s_time_t now) { +#endif + + +static void unblock_long_cons_b(struct sedf_vcpu_info* inf,s_time_t now) +{ /*Conservative 2b*/ /*Treat the unblocking time as a start of a new period */ inf->deadl_abs = now + inf->period; inf->cputime = 0; } -static inline void unblock_long_cons_c(struct sedf_vcpu_info* inf,s_time_t now) { - if (likely(inf->latency)) { + + +#if (UNBLOCK == UNBLOCK_ATROPOS) +static void unblock_long_cons_c(struct sedf_vcpu_info* inf,s_time_t now) +{ + if ( likely(inf->latency) ) + { /*scale the slice and period accordingly to the latency hint*/ /*reduce period temporarily to the latency hint*/ inf->period = inf->latency; @@ -993,18 +1100,24 @@ inf->deadl_abs = now + inf->period; inf->cputime = 0; } - else { + else + { /*we don't have a latency hint.. use some other technique*/ unblock_long_cons_b(inf, now); } } +#endif + + +#if (UNBLOCK == UNBLOCK_BURST) /*a new idea of dealing with short blocks: burst period scaling*/ -static inline void unblock_short_burst(struct sedf_vcpu_info* inf, s_time_t now) +static void unblock_short_burst(struct sedf_vcpu_info* inf, s_time_t now) { /*treat blocked time as consumed by the domain*/ inf->cputime += now - inf->block_abs; - if (inf->cputime + EXTRA_QUANTUM <= inf->slice) { + if ( (inf->cputime + EXTRA_QUANTUM) <= inf->slice ) + { /*if we can still use some time in the current slice then use it!*/ #ifdef SEDF_STATS @@ -1012,10 +1125,12 @@ inf->short_cont++; #endif } - else { + else + { /*we don't have a reasonable amount of time in our slice left => switch to burst mode*/ - if (likely(inf->unblock_abs)) { + if ( likely(inf->unblock_abs) ) + { /*set the period-length to the current blocking interval, possible enhancements: average over last blocking intervals, user-specified minimum,...*/ @@ -1030,17 +1145,23 @@ /*set new (shorter) deadline*/ inf->deadl_abs += inf->period; } - else { + else + { /*in case we haven't unblocked before start in next period!*/ inf->cputime=0; inf->deadl_abs += inf->period; } } + inf->unblock_abs = now; } -static inline void unblock_long_burst(struct sedf_vcpu_info* inf, s_time_t now) { - if (unlikely(inf->latency && (inf->period > inf->latency))) { + + +static void unblock_long_burst(struct sedf_vcpu_info* inf, s_time_t now) +{ + if ( unlikely(inf->latency && (inf->period > inf->latency)) ) + { /*scale the slice and period accordingly to the latency hint*/ inf->period = inf->latency; /*check for overflows on multiplication*/ @@ -1052,21 +1173,26 @@ inf->deadl_abs = now + inf->period; inf->cputime = 0; } - else { + else + { /*we don't have a latency hint.. or we are currently in "burst mode": use some other technique NB: this should be in fact the normal way of operation, when we are in sync with the device!*/ unblock_long_cons_b(inf, now); } + inf->unblock_abs = now; } +#endif /* UNBLOCK == UNBLOCK_BURST */ + #define DOMAIN_EDF 1 #define DOMAIN_EXTRA_PEN 2 #define DOMAIN_EXTRA_UTIL 3 #define DOMAIN_IDLE 4 -static inline int get_run_type(struct vcpu* d) { +static inline int get_run_type(struct vcpu* d) +{ struct sedf_vcpu_info* inf = EDOM_INFO(d); if (is_idle_domain(d->domain)) return DOMAIN_IDLE; @@ -1076,6 +1202,8 @@ return DOMAIN_EXTRA_UTIL; return DOMAIN_EDF; } + + /*Compares two domains in the relation of whether the one is allowed to interrupt the others execution. It returns true (!=0) if a switch to the other domain is good. @@ -1085,8 +1213,10 @@ In the same class priorities are assigned as following: EDF: early deadline > late deadline L0 extra-time: lower score > higher score*/ -static inline int should_switch(struct vcpu* cur, - struct vcpu* other, s_time_t now) { +static inline int should_switch(struct vcpu *cur, + struct vcpu *other, + s_time_t now) +{ struct sedf_vcpu_info *cur_inf, *other_inf; cur_inf = EDOM_INFO(cur); other_inf = EDOM_INFO(other); @@ -1119,41 +1249,51 @@ } return 1; } -void sedf_wake(struct vcpu *d) { + +void sedf_wake(struct vcpu *d) +{ s_time_t now = NOW(); struct sedf_vcpu_info* inf = EDOM_INFO(d); PRINT(3, "sedf_wake was called, domain-id %i.%i\n",d->domain->domain_id, d->vcpu_id); - if (unlikely(is_idle_domain(d->domain))) + if ( unlikely(is_idle_domain(d->domain)) ) return; - if ( unlikely(__task_on_queue(d)) ) { + if ( unlikely(__task_on_queue(d)) ) + { PRINT(3,"\tdomain %i.%i is already in some queue\n", d->domain->domain_id, d->vcpu_id); return; } + ASSERT(!sedf_runnable(d)); inf->status &= ~SEDF_ASLEEP; ASSERT(!extraq_on(d, EXTRA_UTIL_Q)); ASSERT(!extraq_on(d, EXTRA_PEN_Q)); - if (unlikely(inf->deadl_abs == 0)) + if ( unlikely(inf->deadl_abs == 0) ) + { /*initial setup of the deadline*/ inf->deadl_abs = now + inf->slice; + } - PRINT(3,"waking up domain %i.%i (deadl= %"PRIu64" period= %"PRIu64" "\ - "now= %"PRIu64")\n", d->domain->domain_id, d->vcpu_id, inf->deadl_abs, - inf->period, now); + PRINT(3, "waking up domain %i.%i (deadl= %"PRIu64" period= %"PRIu64 + "now= %"PRIu64")\n", + d->domain->domain_id, d->vcpu_id, inf->deadl_abs, inf->period, now); + #ifdef SEDF_STATS inf->block_tot++; #endif - if (unlikely(now < PERIOD_BEGIN(inf))) { + + if ( unlikely(now < PERIOD_BEGIN(inf)) ) + { PRINT(4,"extratime unblock\n"); /* unblocking in extra-time! */ #if (EXTRA == EXTRA_BLOCK_WEIGHT) - if (inf->status & EXTRA_WANT_PEN_Q) { + if ( inf->status & EXTRA_WANT_PEN_Q ) + { /*we have a domain that wants compensation for block penalty and did just block in its compensation time. Give it another @@ -1163,8 +1303,10 @@ #endif extraq_check_add_unblocked(d, 0); } - else { - if (now < inf->deadl_abs) { + else + { + if ( now < inf->deadl_abs ) + { PRINT(4,"short unblocking\n"); /*short blocking*/ #ifdef SEDF_STATS @@ -1182,7 +1324,8 @@ extraq_check_add_unblocked(d, 1); } - else { + else + { PRINT(4,"long unblocking\n"); /*long unblocking*/ #ifdef SEDF_STATS @@ -1197,7 +1340,6 @@ unblock_long_cons_c(inf, now); #elif (UNBLOCK == UNBLOCK_SHORT_RESUME) unblock_long_cons_b(inf, now); - /*unblock_short_cons_c(inf, now);*/ #elif (UNBLOCK == UNBLOCK_BURST) unblock_long_burst(inf, now); #endif @@ -1205,26 +1347,33 @@ extraq_check_add_unblocked(d, 1); } } - PRINT(3,"woke up domain %i.%i (deadl= %"PRIu64" period= %"PRIu64" "\ - "now= %"PRIu64")\n", d->domain->domain_id, d->vcpu_id, inf->deadl_abs, + + PRINT(3, "woke up domain %i.%i (deadl= %"PRIu64" period= %"PRIu64 + "now= %"PRIu64")\n", + d->domain->domain_id, d->vcpu_id, inf->deadl_abs, inf->period, now); - if (PERIOD_BEGIN(inf) > now) { + + if ( PERIOD_BEGIN(inf) > now ) + { __add_to_waitqueue_sort(d); PRINT(3,"added to waitq\n"); } - else { + else + { __add_to_runqueue_sort(d); PRINT(3,"added to runq\n"); } #ifdef SEDF_STATS /*do some statistics here...*/ - if (inf->block_abs != 0) { + if ( inf->block_abs != 0 ) + { inf->block_time_tot += now - inf->block_abs; inf->penalty_time_tot += PERIOD_BEGIN(inf) + inf->cputime - inf->block_abs; } #endif + /*sanity check: make sure each extra-aware domain IS on the util-q!*/ ASSERT(IMPLY(inf->status & EXTRA_AWARE, extraq_on(d, EXTRA_UTIL_Q))); ASSERT(__task_on_queue(d)); @@ -1234,27 +1383,48 @@ ASSERT(d->processor >= 0); ASSERT(d->processor < NR_CPUS); ASSERT(schedule_data[d->processor].curr); - if (should_switch(schedule_data[d->processor].curr, d, now)) + + if ( should_switch(schedule_data[d->processor].curr, d, now) ) cpu_raise_softirq(d->processor, SCHEDULE_SOFTIRQ); } -/*Print a lot of use-{full, less} information about a domains in the system*/ -static void sedf_dump_domain(struct vcpu *d) { + +static int sedf_set_affinity(struct vcpu *v, cpumask_t *affinity) +{ + if ( v == current ) + return cpu_isset(v->processor, *affinity) ? 0 : -EBUSY; + + vcpu_pause(v); + v->cpu_affinity = *affinity; + v->processor = first_cpu(v->cpu_affinity); + vcpu_unpause(v); + + return 0; +} + + +/* Print a lot of useful information about a domains in the system */ +static void sedf_dump_domain(struct vcpu *d) +{ printk("%i.%i has=%c ", d->domain->domain_id, d->vcpu_id, test_bit(_VCPUF_running, &d->vcpu_flags) ? 'T':'F'); - printk("p=%"PRIu64" sl=%"PRIu64" ddl=%"PRIu64" w=%hu c=%"PRIu64" sc=%i xtr(%s)=%"PRIu64" ew=%hu", + printk("p=%"PRIu64" sl=%"PRIu64" ddl=%"PRIu64" w=%hu c=%"PRIu64 + " sc=%i xtr(%s)=%"PRIu64" ew=%hu", EDOM_INFO(d)->period, EDOM_INFO(d)->slice, EDOM_INFO(d)->deadl_abs, - EDOM_INFO(d)->weight, d->cpu_time, EDOM_INFO(d)->score[EXTRA_UTIL_Q], + EDOM_INFO(d)->weight, d->cpu_time, + EDOM_INFO(d)->score[EXTRA_UTIL_Q], (EDOM_INFO(d)->status & EXTRA_AWARE) ? "yes" : "no", EDOM_INFO(d)->extra_time_tot, EDOM_INFO(d)->extraweight); - if (d->cpu_time !=0) + + if ( d->cpu_time != 0 ) printf(" (%"PRIu64"%%)", (EDOM_INFO(d)->extra_time_tot * 100) / d->cpu_time); + #ifdef SEDF_STATS - if (EDOM_INFO(d)->block_time_tot!=0) + if ( EDOM_INFO(d)->block_time_tot != 0 ) printf(" pen=%"PRIu64"%%", (EDOM_INFO(d)->penalty_time_tot * 100) / EDOM_INFO(d)->block_time_tot); - if (EDOM_INFO(d)->block_tot!=0) + if ( EDOM_INFO(d)->block_tot != 0 ) printf("\n blks=%u sh=%u (%u%%) (shc=%u (%u%%) shex=%i "\ "shexsl=%i) l=%u (%u%%) avg: b=%"PRIu64" p=%"PRIu64"", EDOM_INFO(d)->block_tot, EDOM_INFO(d)->short_block_tot, @@ -1271,7 +1441,8 @@ printf("\n"); } -/*dumps all domains on hte specified cpu*/ + +/* dumps all domains on hte specified cpu */ static void sedf_dump_cpu_state(int i) { struct list_head *list, *queue, *tmp; @@ -1284,7 +1455,8 @@ queue = RUNQ(i); printk("RUNQ rq %lx n: %lx, p: %lx\n", (unsigned long)queue, (unsigned long) queue->next, (unsigned long) queue->prev); - list_for_each_safe ( list, tmp, queue ) { + list_for_each_safe ( list, tmp, queue ) + { printk("%3d: ",loop++); d_inf = list_entry(list, struct sedf_vcpu_info, list); sedf_dump_domain(d_inf->vcpu); @@ -1293,7 +1465,8 @@ queue = WAITQ(i); loop = 0; printk("\nWAITQ rq %lx n: %lx, p: %lx\n", (unsigned long)queue, (unsigned long) queue->next, (unsigned long) queue->prev); - list_for_each_safe ( list, tmp, queue ) { + list_for_each_safe ( list, tmp, queue ) + { printk("%3d: ",loop++); d_inf = list_entry(list, struct sedf_vcpu_info, list); sedf_dump_domain(d_inf->vcpu); @@ -1303,7 +1476,8 @@ printk("\nEXTRAQ (penalty) rq %lx n: %lx, p: %lx\n", (unsigned long)queue, (unsigned long) queue->next, (unsigned long) queue->prev); - list_for_each_safe ( list, tmp, queue ) { + list_for_each_safe ( list, tmp, queue ) + { d_inf = list_entry(list, struct sedf_vcpu_info, extralist[EXTRA_PEN_Q]); printk("%3d: ",loop++); @@ -1314,7 +1488,8 @@ printk("\nEXTRAQ (utilization) rq %lx n: %lx, p: %lx\n", (unsigned long)queue, (unsigned long) queue->next, (unsigned long) queue->prev); - list_for_each_safe ( list, tmp, queue ) { + list_for_each_safe ( list, tmp, queue ) + { d_inf = list_entry(list, struct sedf_vcpu_info, extralist[EXTRA_UTIL_Q]); printk("%3d: ",loop++); @@ -1323,69 +1498,93 @@ loop = 0; printk("\nnot on Q\n"); - for_each_domain(d) + + for_each_domain ( d ) + { for_each_vcpu(d, ed) - { - if (!__task_on_queue(ed) && (ed->processor == i)) { - printk("%3d: ",loop++); - sedf_dump_domain(ed); - } - } -} -/*Adjusts periods and slices of the domains accordingly to their weights*/ -static inline int sedf_adjust_weights(struct sched_adjdom_cmd *cmd) { + { + if ( !__task_on_queue(ed) && (ed->processor == i) ) + { + printk("%3d: ",loop++); + sedf_dump_domain(ed); + } + } + } +} + + +/* Adjusts periods and slices of the domains accordingly to their weights. */ +static int sedf_adjust_weights(struct sched_adjdom_cmd *cmd) +{ struct vcpu *p; struct domain *d; int sumw[NR_CPUS]; s_time_t sumt[NR_CPUS]; int cpu; - for (cpu=0; cpu < NR_CPUS; cpu++) { + for ( cpu = 0; cpu < NR_CPUS; cpu++ ) + { sumw[cpu] = 0; sumt[cpu] = 0; } - /*sum up all weights*/ - for_each_domain(d) - for_each_vcpu(d, p) { - if (EDOM_INFO(p)->weight) - sumw[p->processor] += EDOM_INFO(p)->weight; - else { - /*don't modify domains who don't have a weight, but sum - up the time they need, projected to a WEIGHT_PERIOD, - so that this time is not given to the weight-driven - domains*/ - /*check for overflows*/ - ASSERT((WEIGHT_PERIOD < ULONG_MAX) - && (EDOM_INFO(p)->slice_orig < ULONG_MAX)); - sumt[p->processor] += - (WEIGHT_PERIOD * EDOM_INFO(p)->slice_orig) / - EDOM_INFO(p)->period_orig; - } - } - /*adjust all slices (and periods) to the new weight*/ - for_each_domain(d) - for_each_vcpu(d, p) { - if (EDOM_INFO(p)->weight) { - EDOM_INFO(p)->period_orig = - EDOM_INFO(p)->period = WEIGHT_PERIOD; - EDOM_INFO(p)->slice_orig = - EDOM_INFO(p)->slice = - (EDOM_INFO(p)->weight * - (WEIGHT_PERIOD - WEIGHT_SAFETY - sumt[p->processor])) / - sumw[p->processor]; - } - } + + /* sum up all weights */ + for_each_domain( d ) + { + for_each_vcpu( d, p ) + { + if ( EDOM_INFO(p)->weight ) + { + sumw[p->processor] += EDOM_INFO(p)->weight; + } + else + { + /*don't modify domains who don't have a weight, but sum + up the time they need, projected to a WEIGHT_PERIOD, + so that this time is not given to the weight-driven + domains*/ + /*check for overflows*/ + ASSERT((WEIGHT_PERIOD < ULONG_MAX) + && (EDOM_INFO(p)->slice_orig < ULONG_MAX)); + sumt[p->processor] += + (WEIGHT_PERIOD * EDOM_INFO(p)->slice_orig) / + EDOM_INFO(p)->period_orig; + } + } + } + + /* adjust all slices (and periods) to the new weight */ + for_each_domain( d ) + { + for_each_vcpu ( d, p ) + { + if ( EDOM_INFO(p)->weight ) + { + EDOM_INFO(p)->period_orig = + EDOM_INFO(p)->period = WEIGHT_PERIOD; + EDOM_INFO(p)->slice_orig = + EDOM_INFO(p)->slice = + (EDOM_INFO(p)->weight * + (WEIGHT_PERIOD - WEIGHT_SAFETY - sumt[p->processor])) / + sumw[p->processor]; + } + } + } + return 0; } + /* set or fetch domain scheduling parameters */ -static int sedf_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) { +static int sedf_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) +{ struct vcpu *v; PRINT(2,"sedf_adjdom was called, domain-id %i new period %"PRIu64" "\ "new slice %"PRIu64"\nlatency %"PRIu64" extra:%s\n", p->domain_id, cmd->u.sedf.period, cmd->u.sedf.slice, cmd->u.sedf.latency, (cmd->u.sedf.extratime)?"yes":"no"); + if ( cmd->direction == SCHED_INFO_PUT ) { /*check for sane parameters*/ @@ -1458,6 +1657,7 @@ .sleep = sedf_sleep, .wake = sedf_wake, .adjdom = sedf_adjdom, + .set_affinity = sedf_set_affinity }; /* diff -r 01a854cd8848 -r 3eeabf448f91 xen/common/schedule.c --- a/xen/common/schedule.c Fri Jan 6 15:24:46 2006 +++ b/xen/common/schedule.c Fri Jan 6 15:47:25 2006 @@ -202,10 +202,17 @@ SCHED_OP(wake, v); v->wokenup = NOW(); } - clear_bit(_VCPUF_cpu_migrated, &v->vcpu_flags); spin_unlock_irqrestore(&schedule_data[v->processor].schedule_lock, flags); TRACE_2D(TRC_SCHED_WAKE, v->domain->domain_id, v->vcpu_id); +} + +int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity) +{ + if ( cpus_empty(*affinity) ) + return -EINVAL; + + return SCHED_OP(set_affinity, v, affinity); } /* Block the currently-executing domain until a pertinent event occurs. */ diff -r 01a854cd8848 -r 3eeabf448f91 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Fri Jan 6 15:24:46 2006 +++ b/xen/include/asm-x86/mm.h Fri Jan 6 15:47:25 2006 @@ -336,11 +336,13 @@ int revalidate_l1(struct domain *, l1_pgentry_t *, l1_pgentry_t *); void cleanup_writable_pagetable(struct domain *d); -#define sync_pagetable_state(d) \ - do { \ - LOCK_BIGLOCK(d); \ - cleanup_writable_pagetable(d); \ - UNLOCK_BIGLOCK(d); \ +#define sync_pagetable_state(d) \ + do { \ + LOCK_BIGLOCK(d); \ + /* Avoid racing with ptwr_destroy(). */ \ + if ( !test_bit(_DOMF_dying, &(d)->domain_flags) ) \ + cleanup_writable_pagetable(d); \ + UNLOCK_BIGLOCK(d); \ } while ( 0 ) int audit_adjust_pgtables(struct domain *d, int dir, int noisy); diff -r 01a854cd8848 -r 3eeabf448f91 xen/include/asm-x86/shadow.h --- a/xen/include/asm-x86/shadow.h Fri Jan 6 15:24:46 2006 +++ b/xen/include/asm-x86/shadow.h Fri Jan 6 15:47:25 2006 @@ -341,10 +341,10 @@ #if SHADOW_VERBOSE_DEBUG #define SH_LOG(_f, _a...) \ printk("DOM%uP%u: SH_LOG(%d): " _f "\n", \ - current->domain->domain_id , current->processor, __LINE__ , ## _a ) + current->domain->domain_id , smp_processor_id(), __LINE__ , ## _a ) #define SH_VLOG(_f, _a...) \ printk("DOM%uP%u: SH_VLOG(%d): " _f "\n", \ - current->domain->domain_id, current->processor, __LINE__ , ## _a ) + current->domain->domain_id, smp_processor_id(), __LINE__ , ## _a ) #else #define SH_LOG(_f, _a...) ((void)0) #define SH_VLOG(_f, _a...) ((void)0) @@ -353,7 +353,7 @@ #if SHADOW_VVERBOSE_DEBUG #define SH_VVLOG(_f, _a...) \ printk("DOM%uP%u: SH_VVLOG(%d): " _f "\n", \ - current->domain->domain_id, current->processor, __LINE__ , ## _a ) + current->domain->domain_id, smp_processor_id(), __LINE__ , ## _a ) #else #define SH_VVLOG(_f, _a...) ((void)0) #endif @@ -361,7 +361,7 @@ #if SHADOW_VVVERBOSE_DEBUG #define SH_VVVLOG(_f, _a...) \ printk("DOM%uP%u: SH_VVVLOG(%d): " _f "\n", \ - current->domain->domain_id, current->processor, __LINE__ , ## _a ) + current->domain->domain_id, smp_processor_id(), __LINE__ , ## _a ) #else #define SH_VVVLOG(_f, _a...) ((void)0) #endif @@ -369,7 +369,7 @@ #if FULLSHADOW_DEBUG #define FSH_LOG(_f, _a...) \ printk("DOM%uP%u: FSH_LOG(%d): " _f "\n", \ - current->domain->domain_id, current->processor, __LINE__ , ## _a ) + current->domain->domain_id, smp_processor_id(), __LINE__ , ## _a ) #else #define FSH_LOG(_f, _a...) ((void)0) #endif diff -r 01a854cd8848 -r 3eeabf448f91 xen/include/asm-x86/vmx.h --- a/xen/include/asm-x86/vmx.h Fri Jan 6 15:24:46 2006 +++ b/xen/include/asm-x86/vmx.h Fri Jan 6 15:47:25 2006 @@ -38,7 +38,6 @@ extern void arch_vmx_do_launch(struct vcpu *); extern void arch_vmx_do_resume(struct vcpu *); -extern void arch_vmx_do_relaunch(struct vcpu *); extern unsigned int cpu_rev; diff -r 01a854cd8848 -r 3eeabf448f91 xen/include/asm-x86/vmx_vmcs.h --- a/xen/include/asm-x86/vmx_vmcs.h Fri Jan 6 15:24:46 2006 +++ b/xen/include/asm-x86/vmx_vmcs.h Fri Jan 6 15:47:25 2006 @@ -86,7 +86,8 @@ #define PC_DEBUG_PORT 0x80 struct arch_vmx_struct { - struct vmcs_struct *vmcs; /* VMCS pointer in virtual */ + struct vmcs_struct *vmcs; /* VMCS pointer in virtual. */ + unsigned int launch_cpu; /* VMCS is valid on this CPU. */ unsigned long flags; /* VMCS flags */ unsigned long cpu_cr0; /* copy of guest CR0 */ unsigned long cpu_shadow_cr0; /* copy of guest read shadow CR0 */ diff -r 01a854cd8848 -r 3eeabf448f91 xen/include/xen/domain.h --- a/xen/include/xen/domain.h Fri Jan 6 15:24:46 2006 +++ b/xen/include/xen/domain.h Fri Jan 6 15:47:25 2006 @@ -18,8 +18,6 @@ extern int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c); -extern void vcpu_migrate_cpu(struct vcpu *v, int newcpu); - extern void free_perdomain_pt(struct domain *d); extern void domain_relinquish_resources(struct domain *d); diff -r 01a854cd8848 -r 3eeabf448f91 xen/include/xen/sched-if.h --- a/xen/include/xen/sched-if.h Fri Jan 6 15:24:46 2006 +++ b/xen/include/xen/sched-if.h Fri Jan 6 15:47:25 2006 @@ -39,6 +39,7 @@ void (*rem_task) (struct vcpu *); void (*sleep) (struct vcpu *); void (*wake) (struct vcpu *); + int (*set_affinity) (struct vcpu *, cpumask_t *); struct task_slice (*do_schedule) (s_time_t); int (*control) (struct sched_ctl_cmd *); int (*adjdom) (struct domain *, diff -r 01a854cd8848 -r 3eeabf448f91 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Fri Jan 6 15:24:46 2006 +++ b/xen/include/xen/sched.h Fri Jan 6 15:47:25 2006 @@ -362,14 +362,11 @@ /* Currently running on a CPU? */ #define _VCPUF_running 3 #define VCPUF_running (1UL<<_VCPUF_running) - /* Domain migrated between CPUs. */ -#define _VCPUF_cpu_migrated 4 -#define VCPUF_cpu_migrated (1UL<<_VCPUF_cpu_migrated) /* Initialization completed. */ -#define _VCPUF_initialised 5 +#define _VCPUF_initialised 4 #define VCPUF_initialised (1UL<<_VCPUF_initialised) /* VCPU is not-runnable */ -#define _VCPUF_down 6 +#define _VCPUF_down 5 #define VCPUF_down (1UL<<_VCPUF_down) /* @@ -384,17 +381,14 @@ /* Guest shut itself down for some reason. */ #define _DOMF_shutdown 2 #define DOMF_shutdown (1UL<<_DOMF_shutdown) - /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */ -#define _DOMF_shuttingdown 3 -#define DOMF_shuttingdown (1UL<<_DOMF_shuttingdown) /* Death rattle. */ -#define _DOMF_dying 4 +#define _DOMF_dying 3 #define DOMF_dying (1UL<<_DOMF_dying) /* Domain is paused by controller software. */ -#define _DOMF_ctrl_pause 5 +#define _DOMF_ctrl_pause 4 #define DOMF_ctrl_pause (1UL<<_DOMF_ctrl_pause) /* Domain is being debugged by controller software. */ -#define _DOMF_debugging 6 +#define _DOMF_debugging 5 #define DOMF_debugging (1UL<<_DOMF_debugging) @@ -402,8 +396,7 @@ { return ( (atomic_read(&v->pausecnt) == 0) && !(v->vcpu_flags & (VCPUF_blocked|VCPUF_down)) && - !(v->domain->domain_flags & - (DOMF_shutdown|DOMF_shuttingdown|DOMF_ctrl_pause)) ); + !(v->domain->domain_flags & (DOMF_shutdown|DOMF_ctrl_pause)) ); } void vcpu_pause(struct vcpu *v); @@ -414,6 +407,8 @@ void domain_unpause_by_systemcontroller(struct domain *d); void cpu_init(void); +int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity); + static inline void vcpu_unblock(struct vcpu *v) { if ( test_and_clear_bit(_VCPUF_blocked, &v->vcpu_flags) ) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |