[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] x86/mm: Improve ring management for memory events. Do not lose guest events
> Hi, > > This looks fine to me; this time I'd like Olaf to review and test it > before I commit it. :) > > A few comments inline below -- mostly nits about style. Great, will address them -- once Olaf gives us a green light. Andres > > At 13:28 -0500 on 11 Jan (1326288504), Andres Lagar-Cavilla wrote: >> Signed-off-by: Adin Scannell <adin@xxxxxxxxxxx> >> Signed-off-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx> > > Housekeeping: please keep Olaf's Signed-off-by: line to cover the parts > of this patch that he's certifying. > >> diff -r d3342b370b6f -r a85e7d46401b xen/arch/x86/hvm/hvm.c >> --- a/xen/arch/x86/hvm/hvm.c >> +++ b/xen/arch/x86/hvm/hvm.c >> @@ -4188,25 +4188,31 @@ static int hvm_memory_event_traps(long p >> unsigned long value, unsigned long >> old, >> bool_t gla_valid, unsigned long gla) >> { >> + int rc; >> struct vcpu* v = current; >> struct domain *d = v->domain; >> mem_event_request_t req; >> - int rc; >> > > Please try to avoid this kind of unrelated shuffling (and I saw some > whitespace changes later on as well). It's not a big deal, but it makes > reviewing a bit easier and avoids unnecessarily clashing with other > patches. > >> diff -r d3342b370b6f -r a85e7d46401b xen/arch/x86/mm/mem_event.c >> --- a/xen/arch/x86/mm/mem_event.c >> +++ b/xen/arch/x86/mm/mem_event.c > >> + >> +/* >> + * mem_event_wake_requesters() will wakeup vcpus waiting for room in >> the > > DYM mem_event_wake_blocked() ? > >> + * ring. These vCPUs were paused on their way out after placing an >> event, >> + * but need to be resumed where the ring is capable of processing at >> least >> + * one event from them. >> + */ >> +static void mem_event_wake_blocked(struct domain *d, struct >> mem_event_domain *med) >> +{ >> + struct vcpu *v; >> + int online = d->max_vcpus; >> + int avail_req = mem_event_ring_available(med); >> + >> + if( avail_req <= 0 || med->blocked == 0 ) > > s/if(/if (/ > >> + return; >> + >> + /* >> + * We ensure that we only have vCPUs online if there are enough >> free slots >> + * for their memory events to be processed. This will ensure that >> no >> + * memory events are lost (due to the fact that certain types of >> events >> + * cannot be replayed, we need to ensure that there is space in the >> ring >> + * for when they are hit). >> + * See comment below in mem_event_put_request(). >> + */ >> + for_each_vcpu ( d, v ) >> + if ( test_bit(med->pause_flag, &v->pause_flags) ) >> + online--; >> + >> + ASSERT(online == (d->max_vcpus - med->blocked)); > > Maybe better to do the cheap calculation as the default and the more > expensive one for the ASSERT? > >> + /* We remember which vcpu last woke up to avoid scanning always >> linearly >> + * from zero and starving higher-numbered vcpus under high load */ >> + if ( d->vcpu ) >> + { >> + int i, j, k; >> + >> + for (i = med->last_vcpu_wake_up + 1, j = 0; j < d->max_vcpus; >> i++, j++) >> + { >> + k = i % d->max_vcpus; >> + v = d->vcpu[k]; >> + if ( !v ) >> + continue; >> + >> + if ( !(med->blocked) || online >= avail_req ) >> + break; >> + >> + if ( test_and_clear_bit(med->pause_flag, &v->pause_flags) ) >> + { >> + vcpu_unpause(v); >> + online++; >> + med->blocked--; >> + med->last_vcpu_wake_up = k; >> + } >> + } >> + } >> +} >> + >> +/* >> + * In the event that a vCPU attempted to place an event in the ring and >> + * was unable to do so, it is queued on a wait queue. These are woken >> as >> + * needed, and take precedence over the blocked vCPUs. >> + */ >> +static void mem_event_wake_queued(struct domain *d, struct >> mem_event_domain *med) >> +{ >> + int avail_req = mem_event_ring_available(med); >> + >> + if ( avail_req > 0 ) >> + wake_up_nr(&med->wq, avail_req); >> +} >> + >> +/* >> + * mem_event_wake_waiters() will wakeup all vcpus waiting for the ring >> to > > DYM mem_event_wake() ? > >> + * become available. If we have queued vCPUs, they get top priority. >> We >> + * are guaranteed that they will go through code paths that will >> eventually >> + * call mem_event_wake() again, ensuring that any blocked vCPUs will >> get >> + * unpaused once all the queued vCPUs have made it through. >> + */ >> +void mem_event_wake(struct domain *d, struct mem_event_domain *med) >> +{ >> + if (!list_empty(&med->wq.list)) >> + mem_event_wake_queued(d, med); >> + else >> + mem_event_wake_blocked(d, med); >> +} >> + >> +static int mem_event_disable(struct domain *d, struct mem_event_domain >> *med) >> +{ >> + if( med->ring_page ) > > s/if(/if (/g :) > >> + { >> + struct vcpu *v; >> + >> + mem_event_ring_lock(med); >> + >> + if (!list_empty(&med->wq.list)) > > if ( ... ) > >> + { >> + mem_event_ring_unlock(med); >> + return -EBUSY; >> + } >> + >> + unmap_domain_page(med->ring_page); >> + med->ring_page = NULL; >> + >> + unmap_domain_page(med->shared_page); >> + med->shared_page = NULL; >> + >> + /* Wake up everybody */ >> + wake_up_all(&med->wq); >> + >> + /* Unblock all vCPUs */ >> + for_each_vcpu ( d, v ) >> + { >> + if ( test_and_clear_bit(med->pause_flag, &v->pause_flags) ) >> + { >> + vcpu_unpause(v); >> + med->blocked--; >> + } >> + } >> + >> + mem_event_ring_unlock(med); >> + } >> >> return 0; >> } >> >> -void mem_event_put_request(struct domain *d, struct mem_event_domain >> *med, mem_event_request_t *req) >> +static inline void mem_event_release_slot(struct domain *d, >> + struct mem_event_domain *med) >> +{ >> + /* Update the accounting */ >> + if ( current->domain == d ) >> + med->target_producers--; >> + else >> + med->foreign_producers--; >> + >> + /* Kick any waiters */ >> + mem_event_wake(d, med); >> +} >> + >> +/* >> + * mem_event_mark_and_pause() tags vcpu and put it to sleep. >> + * The vcpu will resume execution in mem_event_wake_waiters(). >> + */ >> +void mem_event_mark_and_pause(struct vcpu *v, struct mem_event_domain >> *med) >> +{ >> + if ( !test_and_set_bit(med->pause_flag, &v->pause_flags) ) >> + { >> + vcpu_pause_nosync(v); >> + med->blocked++; >> + } >> +} >> + >> +/* >> + * This must be preceeded by a call to claim_slot(), and is guaranteed >> to > > preceded > > Cheers, > > Tim. > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |