From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Liu Subject: [RFC PATCH V5 03/15] evtchn: alter internal object handling scheme Date: Tue, 19 Mar 2013 15:15:28 +0000 Message-ID: <1363706140-26989-4-git-send-email-wei.liu2@citrix.com> References: <1363706140-26989-1-git-send-email-wei.liu2@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1363706140-26989-1-git-send-email-wei.liu2@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: Wei Liu , david.vrabel@citrix.com, jbeulich@suse.com, ian.campbell@citrix.com List-Id: xen-devel@lists.xenproject.org Originally, evtchn objects are stored in buckets. Now we add another layer called group. Now struct domain holds an array to evtchn groups, then each group holds pointers to a bucket. With this change, we can handle more struct evtchn in a space-efficient way. Signed-off-by: Wei Liu --- xen/common/event_channel.c | 26 +++++++++++++++++++++++--- xen/include/xen/event.h | 12 ++++++++++-- xen/include/xen/sched.h | 12 +++++++++--- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 1b702d5..76de8ec 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -124,6 +124,7 @@ static int virq_is_global(uint32_t virq) static int get_free_port(struct domain *d) { struct evtchn *chn; + struct evtchn **grp; int port; int i, j; @@ -137,6 +138,15 @@ static int get_free_port(struct domain *d) if ( port == MAX_EVTCHNS(d) ) return -ENOSPC; + if ( unlikely(group_from_port(d, port) == NULL ) ) + { + grp = xzalloc_array(struct evtchn *, BUCKETS_PER_GROUP); + if ( unlikely(grp == NULL) ) + return -ENOMEM; + else + group_from_port(d, port) = grp; + } + chn = xzalloc_array(struct evtchn, EVTCHNS_PER_BUCKET); if ( unlikely(chn == NULL) ) return -ENOMEM; @@ -1191,7 +1201,7 @@ int evtchn_init(struct domain *d) void evtchn_destroy(struct domain *d) { - int i; + int i, j; /* After this barrier no new event-channel allocations can occur. */ BUG_ON(!d->is_dying); @@ -1206,9 +1216,19 @@ void evtchn_destroy(struct domain *d) /* Free all event-channel buckets. */ spin_lock(&d->event_lock); - for ( i = 0; i < NR_EVTCHN_BUCKETS; i++ ) + for ( i = 0; i < NR_EVTCHN_GROUPS; i++ ) { - xsm_free_security_evtchn(d->evtchn[i]); + if ( d->evtchn[i] == NULL ) + continue; + + for ( j = 0; j < BUCKETS_PER_GROUP; j++ ) + { + if ( d->evtchn[i][j] == NULL ) + continue; + xsm_free_security_evtchn(d->evtchn[i][j]); + xfree(d->evtchn[i][j]); + d->evtchn[i][j] = NULL; + } xfree(d->evtchn[i]); d->evtchn[i] = NULL; } diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index 65ac81a..ff9332a 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -69,11 +69,19 @@ int guest_enabled_event(struct vcpu *v, uint32_t virq); /* Notify remote end of a Xen-attached event channel.*/ void notify_via_xen_event_channel(struct domain *ld, int lport); -/* Internal event channel object accessors */ +/* + * Internal event channel object storage: + * Objects are organized in two level scheme: group and bucket + * A group consists of several buckets, a bucket is an array of struct evtchn + */ +#define group_from_port(d,p) \ + ((d)->evtchn[(p)/EVTCHNS_PER_GROUP]) +/* User should make sure group is not NULL */ #define bucket_from_port(d,p) \ - ((d)->evtchn[(p)/EVTCHNS_PER_BUCKET]) + ((group_from_port(d,p))[((p)%EVTCHNS_PER_GROUP)/EVTCHNS_PER_BUCKET]) #define port_is_valid(d,p) \ (((p) >= 0) && ((p) < MAX_EVTCHNS(d)) && \ + (group_from_port(d,p) != NULL) && \ (bucket_from_port(d,p) != NULL)) #define evtchn_from_port(d,p) \ (&(bucket_from_port(d,p))[(p)&(EVTCHNS_PER_BUCKET-1)]) diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index ae3cd07..7169ca0 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -51,8 +51,14 @@ extern struct domain *dom0; #define BITS_PER_EVTCHN_WORD(d) (has_32bit_shinfo(d) ? 32 : BITS_PER_XEN_ULONG) #endif #define MAX_EVTCHNS(d) (BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d)) -#define EVTCHNS_PER_BUCKET 128 -#define NR_EVTCHN_BUCKETS (NR_EVENT_CHANNELS / EVTCHNS_PER_BUCKET) +/* + * To make sure EVTCHNS_PER_BUCKET is at least 1 for 32 bit build, + * NR_EVTCHN_GROUPS * BUCKETES_PER_GROUP should be <= 1024. + */ +#define NR_EVTCHN_GROUPS 64 +#define BUCKETS_PER_GROUP 16 +#define EVTCHNS_PER_GROUP (NR_EVENT_CHANNELS / NR_EVTCHN_GROUPS) +#define EVTCHNS_PER_BUCKET (EVTCHNS_PER_GROUP / BUCKETS_PER_GROUP) struct evtchn { @@ -260,7 +266,7 @@ struct domain spinlock_t rangesets_lock; /* Event channel information. */ - struct evtchn *evtchn[NR_EVTCHN_BUCKETS]; + struct evtchn **evtchn[NR_EVTCHN_GROUPS]; spinlock_t event_lock; struct grant_table *grant_table; -- 1.7.10.4