|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |