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

[PATCH v3 016/114] module: use static ModuleEntry and per-type DSO lists



register_module_init malloc'd a ModuleEntry and a late DSO ran
from one shared list. Store each module_init in a static
ModuleEntry and keep a dso_list per init type. Concatenate a late
DSO onto the builtin list when that type is not done yet,
otherwise run it immediately.

Signed-off-by: Yonggang Luo <luoyonggang@xxxxxxxxx>
---
 include/qemu/module.h   |  22 ++++++--
 include/qemu/queue.h    |  10 ++++
 rust/util/src/module.rs |  16 ++++--
 util/module.c           | 109 ++++++++++++++++++++++------------------
 4 files changed, 98 insertions(+), 59 deletions(-)

diff --git a/include/qemu/module.h b/include/qemu/module.h
index 9885ac9afb3..34e05c75348 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -14,6 +14,7 @@
 #ifndef QEMU_MODULE_H
 #define QEMU_MODULE_H
 
+#include "qemu/queue.h"
 
 #define DSO_STAMP_FUN         glue(qemu_stamp, CONFIG_STAMP)
 #define DSO_STAMP_FUN_STR     stringify(DSO_STAMP_FUN)
@@ -26,16 +27,22 @@ void DSO_STAMP_FUN(void);
 void qemu_module_dummy(void);
 
 #define module_init(function, type)                                         \
+static ModuleEntry glue(qemu_module_entry_, function) = {                   \
+    .init = function,                                                       \
+};                                                                          \
 static void __attribute__((constructor)) do_qemu_init_ ## function(void)    \
 {                                                                           \
-    register_dso_module_init(function, type);                               \
+    register_dso_module_init(&glue(qemu_module_entry_, function), type);    \
 }
 #else
 /* This should not be used directly.  Use block_init etc. instead.  */
 #define module_init(function, type)                                         \
+static ModuleEntry glue(qemu_module_entry_, function) = {                   \
+    .init = function,                                                       \
+};                                                                          \
 static void __attribute__((constructor)) do_qemu_init_ ## function(void)    \
 {                                                                           \
-    register_module_init(function, type);                                   \
+    register_module_init(&glue(qemu_module_entry_, function), type);        \
 }
 #endif
 
@@ -51,6 +58,13 @@ typedef enum {
     MODULE_INIT_MAX
 } module_init_type;
 
+typedef void (ModuleInitFn)(void);
+
+typedef struct ModuleEntry {
+    ModuleInitFn *init;
+    QTAILQ_ENTRY(ModuleEntry) node;
+} ModuleEntry;
+
 #define block_init(function) module_init(function, MODULE_INIT_BLOCK)
 #define opts_init(function) module_init(function, MODULE_INIT_OPTS)
 #define type_init(function) module_init(function, MODULE_INIT_QOM)
@@ -64,8 +78,8 @@ typedef enum {
 #define block_module_load(lib, errp) module_load("block-", lib, errp)
 #define ui_module_load(lib, errp) module_load("ui-", lib, errp)
 
-void register_module_init(void (*fn)(void), module_init_type type);
-void register_dso_module_init(void (*fn)(void), module_init_type type);
+void register_module_init(ModuleEntry *e, module_init_type type);
+void register_dso_module_init(ModuleEntry *e, module_init_type type);
 
 void module_call_init(module_init_type type);
 
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index e029e7bf669..06ebe8b1dfc 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -470,6 +470,16 @@ union {                                                    
             \
         (left)->field.tqe_circ.tql_prev->tql_next = (right)->field.tqe_next; \
     } while (/*CONSTCOND*/0)
 
+#define QTAILQ_CONCAT(head1, head2, field) do {                         \
+        if (!QTAILQ_EMPTY(head2)) {                                     \
+            (head1)->tqh_circ.tql_prev->tql_next = (head2)->tqh_first;  \
+            (head2)->tqh_first->field.tqe_circ.tql_prev =               \
+                (head1)->tqh_circ.tql_prev;                             \
+            (head1)->tqh_circ.tql_prev = (head2)->tqh_circ.tql_prev;    \
+            QTAILQ_INIT(head2);                                         \
+        }                                                               \
+} while (/*CONSTCOND*/0)
+
 #define QTAILQ_FOREACH(var, head, field)                                \
         for ((var) = ((head)->tqh_first);                               \
                 (var);                                                  \
diff --git a/rust/util/src/module.rs b/rust/util/src/module.rs
index 06c45fc142b..45d8b67d6dc 100644
--- a/rust/util/src/module.rs
+++ b/rust/util/src/module.rs
@@ -8,6 +8,16 @@
 macro_rules! module_init {
     ($type:ident => $body:block) => {
         const _: () = {
+            extern "C" fn init_fn() {
+                $body
+            }
+
+            static mut ENTRY: $crate::bindings::ModuleEntry =
+                $crate::bindings::ModuleEntry {
+                    init: Some(init_fn),
+                    ..unsafe { ::core::mem::zeroed() }
+                };
+
             #[used]
             #[cfg_attr(
                 not(any(target_vendor = "apple", target_os = "windows")),
@@ -16,14 +26,10 @@ macro_rules! module_init {
             #[cfg_attr(target_vendor = "apple", link_section = 
"__DATA,__mod_init_func")]
             #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
             pub static LOAD_MODULE: extern "C" fn() = {
-                extern "C" fn init_fn() {
-                    $body
-                }
-
                 extern "C" fn ctor_fn() {
                     unsafe {
                         $crate::bindings::register_module_init(
-                            Some(init_fn),
+                            ::core::ptr::addr_of_mut!(ENTRY),
                             $crate::bindings::module_init_type::$type,
                         );
                     }
diff --git a/util/module.c b/util/module.c
index 8f8e6994f11..6c5980542f6 100644
--- a/util/module.c
+++ b/util/module.c
@@ -27,19 +27,26 @@
 #endif
 #include "trace.h"
 
-typedef struct ModuleEntry
+typedef QTAILQ_HEAD(, ModuleEntry) ModuleEntryList;
+
+typedef struct ModuleInit
 {
-    void (*init)(void);
-    QTAILQ_ENTRY(ModuleEntry) node;
     module_init_type type;
-} ModuleEntry;
+    ModuleEntryList list;
+    ModuleEntryList dso_list;
+    bool done;
+} ModuleInit;
 
-typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
+static ModuleInit module_inits[MODULE_INIT_MAX];
 
-static ModuleTypeList init_type_list[MODULE_INIT_MAX];
-static bool modules_init_done[MODULE_INIT_MAX];
+static void empty_dso_lists(void)
+{
+    int i;
 
-static ModuleTypeList dso_init_list;
+    for (i = 0; i < MODULE_INIT_MAX; i++) {
+        QTAILQ_INIT(&module_inits[i].dso_list);
+    }
+}
 
 static void init_lists(void)
 {
@@ -51,65 +58,56 @@ static void init_lists(void)
     }
 
     for (i = 0; i < MODULE_INIT_MAX; i++) {
-        QTAILQ_INIT(&init_type_list[i]);
+        module_inits[i].type = i;
+        QTAILQ_INIT(&module_inits[i].list);
     }
-
-    QTAILQ_INIT(&dso_init_list);
+    empty_dso_lists();
 
     inited = 1;
 }
 
-
-static ModuleTypeList *find_type(module_init_type type)
+static ModuleInit *find_type(module_init_type type)
 {
     init_lists();
 
-    return &init_type_list[type];
+    return &module_inits[type];
 }
 
-void register_module_init(void (*fn)(void), module_init_type type)
+static void module_init_add(ModuleEntryList *list, ModuleEntry *e)
 {
-    ModuleEntry *e;
-    ModuleTypeList *l;
-
-    e = g_malloc0(sizeof(*e));
-    e->init = fn;
-    e->type = type;
+    QTAILQ_INSERT_TAIL(list, e, node);
+}
 
-    l = find_type(type);
+void register_module_init(ModuleEntry *e, module_init_type type)
+{
+    module_init_add(&find_type(type)->list, e);
+}
 
-    QTAILQ_INSERT_TAIL(l, e, node);
+void register_dso_module_init(ModuleEntry *e, module_init_type type)
+{
+    module_init_add(&find_type(type)->dso_list, e);
 }
 
-void register_dso_module_init(void (*fn)(void), module_init_type type)
+static void module_init_run(ModuleInit *m, ModuleEntryList *list)
 {
     ModuleEntry *e;
 
-    init_lists();
-
-    e = g_malloc0(sizeof(*e));
-    e->init = fn;
-    e->type = type;
-
-    QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
+    (void)m;
+    QTAILQ_FOREACH(e, list, node) {
+        e->init();
+    }
 }
 
 void module_call_init(module_init_type type)
 {
-    ModuleTypeList *l;
-    ModuleEntry *e;
+    ModuleInit *m = find_type(type);
 
-    if (modules_init_done[type]) {
+    if (m->done) {
         return;
     }
 
-    l = find_type(type);
-
-    QTAILQ_FOREACH(e, l, node) {
-        e->init();
-    }
-
-    modules_init_done[type] = true;
+    module_init_run(m, &m->list);
+    m->done = true;
 }
 
 #ifdef CONFIG_MODULES
@@ -159,10 +157,13 @@ static bool module_load_dso(const char *fname, bool 
export_symbols,
 {
     GModule *g_module;
     void (*sym)(void);
-    ModuleEntry *e, *next;
+    int i;
     int flags;
 
-    assert(QTAILQ_EMPTY(&dso_init_list));
+    init_lists();
+    for (i = 0; i < MODULE_INIT_MAX; i++) {
+        assert(QTAILQ_EMPTY(&module_inits[i].dso_list));
+    }
 
     flags = 0;
     if (!export_symbols) {
@@ -183,19 +184,27 @@ static bool module_load_dso(const char *fname, bool 
export_symbols,
             error_append_hint(errp,
                 "Only modules from the same build can be loaded.\n");
         }
+        empty_dso_lists();
         g_module_close(g_module);
         return false;
     }
 
-    QTAILQ_FOREACH(e, &dso_init_list, node) {
-        e->init();
-        register_module_init(e->init, e->type);
+    for (i = 0; i < MODULE_INIT_MAX; i++) {
+        ModuleInit *m = &module_inits[i];
+
+        if (QTAILQ_EMPTY(&m->dso_list)) {
+            continue;
+        }
+
+        if (!m->done) {
+            QTAILQ_CONCAT(&m->list, &m->dso_list, node);
+            continue;
+        }
+
+        module_init_run(m, &m->dso_list);
     }
     trace_module_load_module(fname);
-    QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
-        QTAILQ_REMOVE(&dso_init_list, e, node);
-        g_free(e);
-    }
+    empty_dso_lists();
     return true;
 }
 
-- 
2.52.0.windows.1




 


Rackspace

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