From 0bfe3ca51ebddbf2cc099fa34f359bd1ac4f65e6 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Thu, 14 May 2009 19:29:53 +0100 Subject: [PATCH] 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 Signed-off-by: Anthony Liguori --- Makefile | 2 +- Makefile.target | 25 ++++++-------- module.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ module.h | 35 +++++++++++++++++++ qemu-common.h | 2 ++ rules.mak | 7 ++-- 6 files changed, 145 insertions(+), 17 deletions(-) create mode 100644 module.c create mode 100644 module.h 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 + * + * 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 + * + * 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)$@")