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

[UNIKRAFT PATCH 2/2] plat/linuxu: do not allocate IRQ handler entries dynamically



This commit applies the same strategy as previously done for the KVM
platform. We pre-allocate IRQ handlers statically. Their number can be
configured via a new config variable LINUXU_MAX_IRQ_HANDLER_ENTRIES.

Signed-off-by: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
---
 plat/linuxu/Config.uk |  4 +++
 plat/linuxu/irq.c     | 67 ++++++++++++++++++++++++++++++---------------------
 2 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/plat/linuxu/Config.uk b/plat/linuxu/Config.uk
index d8c86d8..0394f91 100644
--- a/plat/linuxu/Config.uk
+++ b/plat/linuxu/Config.uk
@@ -17,4 +17,8 @@ if (PLAT_LINUXU)
                changed by using linuxu.heap_size as a command line argument. 
For more
                information refer to "Command line arguments in Unikraft" 
sections in 
                the developers guide
+
+       config LINUXU_MAX_IRQ_HANDLER_ENTRIES
+       int "Maximum number of IRQ handlers per event"
+       default 8
 endif
diff --git a/plat/linuxu/irq.c b/plat/linuxu/irq.c
index 961dcf9..c1de4d1 100644
--- a/plat/linuxu/irq.c
+++ b/plat/linuxu/irq.c
@@ -32,8 +32,7 @@
  * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
  */
 #include <string.h>
-#include <uk/alloc.h>
-#include <uk/list.h>
+#include <errno.h>
 #include <uk/plat/lcpu.h>
 #include <uk/plat/irq.h>
 #include <uk/assert.h>
@@ -41,24 +40,34 @@
 #include <linuxu/signal.h>
 
 #define IRQS_NUM    16
+#define HANDLER_RESERVED ((void *) 0x1)
 
 /* IRQ handlers declarations */
 struct irq_handler {
+       /* func() special values:
+        *   NULL: free,
+        *   HANDLER_RESERVED: reserved
+        */
        irq_handler_func_t func;
        void *arg;
 
        struct uk_sigaction oldaction;
-
-       UK_SLIST_ENTRY(struct irq_handler) entries;
 };
 
-UK_SLIST_HEAD(irq_handler_head, struct irq_handler);
-static struct irq_handler_head irq_handlers[IRQS_NUM];
+static struct irq_handler irq_handlers[IRQS_NUM]
+                               [CONFIG_LINUXU_MAX_IRQ_HANDLER_ENTRIES];
 
-static struct uk_alloc *allocator;
 static k_sigset_t handled_signals_set;
 static unsigned long irq_enabled;
 
+static inline struct irq_handler *allocate_handler(unsigned long irq)
+{
+       for (int i = 0; i < CONFIG_LINUXU_MAX_IRQ_HANDLER_ENTRIES; i++)
+               if (irq_handlers[irq][i].func == NULL)
+                       return &irq_handlers[irq][i];
+       return NULL;
+}
+
 void ukplat_lcpu_enable_irq(void)
 {
        int rc;
@@ -123,10 +132,16 @@ asm("__restorer:mov r7, #0x77\nsvc 0x0");
 static void _irq_handle(int irq)
 {
        struct irq_handler *h;
+       int i;
 
        UK_ASSERT(irq >= 0 && irq < IRQS_NUM);
 
-       UK_SLIST_FOREACH(h, &irq_handlers[irq], entries) {
+       for (i = 0; i < CONFIG_LINUXU_MAX_IRQ_HANDLER_ENTRIES; i++) {
+               if (irq_handlers[irq][i].func == NULL)
+                       break;
+               else if (irq_handlers[irq][i].func == HANDLER_RESERVED)
+                       continue; /* reserved entry */
+               h = &irq_handlers[irq][i];
                if (h->func(h->arg) == 1)
                        return;
        }
@@ -151,11 +166,15 @@ int ukplat_irq_register(unsigned long irq, 
irq_handler_func_t func, void *arg)
                return -EINVAL;
 
        /* New handler */
-       h = uk_malloc(allocator, sizeof(struct irq_handler));
-       if (!h)
-               return -ENOMEM;
-       h->func = func;
-       h->arg = arg;
+       flags = ukplat_lcpu_save_irqf();
+       h = allocate_handler(irq);
+       if (!h) {
+               ukplat_lcpu_restore_irqf(flags);
+               return -EINVAL;
+       }
+
+       h->func = HANDLER_RESERVED; /* reserve */
+       ukplat_lcpu_restore_irqf(flags);
 
        /* Register signal action */
        memset(&action, 0, sizeof(action));
@@ -164,12 +183,14 @@ int ukplat_irq_register(unsigned long irq, 
irq_handler_func_t func, void *arg)
        action.k_sa_restorer = __restorer;
 
        rc = sys_sigaction((int) irq, &action, &h->oldaction);
-       if (rc != 0)
+       if (rc != 0) {
+               h->func = NULL; /* give back */
                goto err;
+       }
 
-       flags = ukplat_lcpu_save_irqf();
-       UK_SLIST_INSERT_HEAD(&irq_handlers[irq], h, entries);
-       ukplat_lcpu_restore_irqf(flags);
+       /* Enable the handler */
+       h->func = func;
+       h->arg = arg;
 
        /* Unblock the signal */
        k_sigemptyset(&set);
@@ -185,22 +206,12 @@ int ukplat_irq_register(unsigned long irq, 
irq_handler_func_t func, void *arg)
        return 0;
 
 err:
-       uk_free(allocator, h);
        return -rc;
 }
 
-int ukplat_irq_init(struct uk_alloc *a)
+int ukplat_irq_init(struct uk_alloc *a __unused)
 {
        UK_ASSERT(!irq_enabled);
-       UK_ASSERT(!allocator);
-
-       allocator = a;
-
-       /* Clear list head */
-       for (int i = 0; i < IRQS_NUM; i++)
-               UK_SLIST_INIT(&irq_handlers[i]);
-
        k_sigemptyset(&handled_signals_set);
-
        return 0;
 }
-- 
2.7.4




 


Rackspace

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