[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC PATCH V5 03/15] evtchn: alter internal object handling scheme



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 <wei.liu2@xxxxxxxxxx>
---
 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


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.