summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2009-05-14 19:29:53 +0100
committerPaul Brook <paul@codesourcery.com>2009-05-14 19:29:53 +0100
commit0bfe3ca51ebddbf2cc099fa34f359bd1ac4f65e6 (patch)
tree55e9fe69186e0c403be34ed30bbcb60416ec617f
parent70ec5dc0afa5cb4cc0c1fafc844c01973fcde8c3 (diff)
downloadqemu-0bfe3ca51ebddbf2cc099fa34f359bd1ac4f65e6.tar.gz
qemu-0bfe3ca51ebddbf2cc099fa34f359bd1ac4f65e6.tar.bz2
qemu-0bfe3ca51ebddbf2cc099fa34f359bd1ac4f65e6.zip
Constructor support
Allow devices/drivers to register themselves via constructors. Destructors are not needed (can be registered from a constructor) and "priority" has been renamed and changed to an enum for clarity. Signed-off-by: Paul Brook <paul@codesourcery.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r--Makefile2
-rw-r--r--Makefile.target25
-rw-r--r--module.c91
-rw-r--r--module.h35
-rw-r--r--qemu-common.h2
-rw-r--r--rules.mak7
6 files changed, 145 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index e996a997d2..046c74369a 100644
--- a/Makefile
+++ b/Makefile
@@ -63,7 +63,7 @@ recurse-all: $(SUBDIR_RULES)
#######################################################################
# BLOCK_OBJS is code used by both qemu system emulation and qemu-img
-BLOCK_OBJS=cutils.o cache-utils.o qemu-malloc.o
+BLOCK_OBJS=cutils.o cache-utils.o qemu-malloc.o module.o
BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
BLOCK_OBJS+=block-qcow2.o block-parallels.o block-nbd.o
diff --git a/Makefile.target b/Makefile.target
index f682560518..30b159dc1b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -340,14 +340,13 @@ ifeq ($(TARGET_ARCH), m68k)
OBJS+= m68k-sim.o m68k-semi.o
endif
-OBJS+= libqemu.a
-
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in cpu-exec.c.
signal.o: CFLAGS += $(HELPER_CFLAGS)
-$(QEMU_PROG): $(OBJS) ../libqemu_user.a
- $(LINK)
+$(QEMU_PROG): ARLIBS=../libqemu_user.a libqemu.a
+$(QEMU_PROG): $(OBJS) ../libqemu_user.a libqemu.a
+ $(call LINK,$(OBJS))
ifeq ($(ARCH),alpha)
# Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of
# the address space (31 bit so sign extending doesn't matter)
@@ -372,14 +371,13 @@ LIBS+=-lmx
OBJS= main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o \
gdbstub.o gdbstub-xml.o
-OBJS+= libqemu.a
-
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in cpu-exec.c.
signal.o: CFLAGS += $(HELPER_CFLAGS)
-$(QEMU_PROG): $(OBJS)
- $(LINK)
+$(QEMU_PROG): ARLIBS=libqemu.a
+$(QEMU_PROG): $(OBJS) libqemu.a
+ $(call LINK,$(OBJS))
endif #CONFIG_DARWIN_USER
@@ -473,14 +471,13 @@ OBJS= main.o bsdload.o elfload.o mmap.o path.o signal.o strace.o syscall.o \
gdbstub.o gdbstub-xml.o
OBJS+= uaccess.o
-OBJS+= libqemu.a
-
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in cpu-exec.c.
signal.o: CFLAGS += $(HELPER_CFLAGS)
-$(QEMU_PROG): $(OBJS) ../libqemu_user.a
- $(LINK)
+$(QEMU_PROG): ARLIBS=libqemu.a ../libqemu_user.a
+$(QEMU_PROG): $(OBJS) libqemu.a ../libqemu_user.a
+ $(call LINK,$(OBJS))
endif #CONFIG_BSD_USER
@@ -716,9 +713,9 @@ endif
vl.o: qemu-options.h
$(QEMU_PROG): LIBS += $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) $(VDE_LIBS)
-
+$(QEMU_PROG): ARLIBS=../libqemu_common.a libqemu.a
$(QEMU_PROG): $(OBJS) ../libqemu_common.a libqemu.a
- $(LINK)
+ $(call LINK,$(OBJS))
endif # !CONFIG_USER_ONLY
diff --git a/module.c b/module.c
new file mode 100644
index 0000000000..113eeefc6e
--- /dev/null
+++ b/module.c
@@ -0,0 +1,91 @@
+/*
+ * QEMU Module Infrastructure
+ *
+ * Copyright IBM, Corp. 2009
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "sys-queue.h"
+#include "module.h"
+
+typedef struct ModuleEntry
+{
+ module_init_type type;
+ void (*init)(void);
+ TAILQ_ENTRY(ModuleEntry) node;
+} ModuleEntry;
+
+typedef struct ModuleTypeList
+{
+ module_init_type type;
+ TAILQ_HEAD(, ModuleEntry) entry_list;
+ TAILQ_ENTRY(ModuleTypeList) node;
+} ModuleTypeList;
+
+static TAILQ_HEAD(, ModuleTypeList) init_type_list;
+
+static ModuleTypeList *find_type_or_alloc(module_init_type type, int alloc)
+{
+ ModuleTypeList *n;
+
+ TAILQ_FOREACH(n, &init_type_list, node) {
+ if (type >= n->type)
+ break;
+ }
+
+ if (!n || n->type != type) {
+ ModuleTypeList *o;
+
+ if (!alloc)
+ return NULL;
+
+ o = qemu_mallocz(sizeof(*o));
+ o->type = type;
+ TAILQ_INIT(&o->entry_list);
+
+ if (n) {
+ TAILQ_INSERT_AFTER(&init_type_list, n, o, node);
+ } else {
+ TAILQ_INSERT_HEAD(&init_type_list, o, node);
+ }
+
+ n = o;
+ }
+
+ return n;
+}
+
+void register_module_init(void (*fn)(void), module_init_type type)
+{
+ ModuleEntry *e;
+ ModuleTypeList *l;
+
+ e = qemu_mallocz(sizeof(*e));
+ e->init = fn;
+
+ l = find_type_or_alloc(type, 1);
+
+ TAILQ_INSERT_TAIL(&l->entry_list, e, node);
+}
+
+void module_call_init(module_init_type type)
+{
+ ModuleTypeList *l;
+ ModuleEntry *e;
+
+ l = find_type_or_alloc(type, 0);
+ if (!l) {
+ return;
+ }
+
+ TAILQ_FOREACH(e, &l->entry_list, node) {
+ e->init();
+ }
+}
diff --git a/module.h b/module.h
new file mode 100644
index 0000000000..cd368b1a91
--- /dev/null
+++ b/module.h
@@ -0,0 +1,35 @@
+/*
+ * QEMU Module Infrastructure
+ *
+ * Copyright IBM, Corp. 2009
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_MODULE_H
+#define QEMU_MODULE_H
+
+/* This should not be used directly. Use block_init etc. instead. */
+#define module_init(function, type) \
+static void __attribute__((constructor)) do_qemu_init_ ## function(void) { \
+ register_module_init(function, type); \
+}
+
+typedef enum {
+ MODULE_INIT_BLOCK,
+ MODULE_INIT_DEVICE
+} module_init_type;
+
+#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
+#define device_init(function) module_init(function, MODULE_INIT_DEVICE)
+
+void register_module_init(void (*fn)(void), module_init_type type);
+
+void module_call_init(module_init_type type);
+
+#endif
diff --git a/qemu-common.h b/qemu-common.h
index ee4a672694..5f7f275d0f 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -221,6 +221,8 @@ void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count);
struct Monitor;
typedef struct Monitor Monitor;
+#include "module.h"
+
#endif /* dyngen-exec.h hack */
#endif
diff --git a/rules.mak b/rules.mak
index a75a93bdcd..8471d4007b 100644
--- a/rules.mak
+++ b/rules.mak
@@ -8,10 +8,13 @@
%.o: %.m
$(call quiet-command,$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
-LINK = $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)," LINK $(TARGET_DIR)$@")
+WAS=-Wl,--whole-archive
+WAE=-Wl,--no-whole-archive
+
+LINK = $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(1) $(LIBS) $(WAS) $(ARLIBS) $(WAE)," LINK $(TARGET_DIR)$@")
%$(EXESUF): %.o
- $(LINK)
+ $(call LINK,$^)
%.a:
$(call quiet-command,rm -f $@ && $(AR) rcs $@ $^," AR $(TARGET_DIR)$@")