From 1be5590f3a4fc33650acba8d208717bdea253fc1 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 17 Sep 2012 10:03:29 +0200 Subject: [PATCH] kvm tools: add init/exit automatic calls This adds a method to call init/exit functions similar to the kernel's init functions. Signed-off-by: Sasha Levin Signed-off-by: Pekka Enberg --- tools/kvm/include/kvm/util-init.h | 51 +++++++++++++++++++++++ tools/kvm/util/init.c | 69 +++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 tools/kvm/include/kvm/util-init.h create mode 100644 tools/kvm/util/init.c diff --git a/tools/kvm/include/kvm/util-init.h b/tools/kvm/include/kvm/util-init.h new file mode 100644 index 000000000000..13d4f04df678 --- /dev/null +++ b/tools/kvm/include/kvm/util-init.h @@ -0,0 +1,51 @@ +#ifndef KVM__UTIL_INIT_H +#define KVM__UTIL_INIT_H + +struct kvm; + +struct init_item { + struct hlist_node n; + const char *fn_name; + int (*init)(struct kvm *); +}; + +int init_list__init(struct kvm *kvm); +int init_list__exit(struct kvm *kvm); + +int init_list_add(struct init_item *t, int (*init)(struct kvm *), + int priority, const char *name); +int exit_list_add(struct init_item *t, int (*init)(struct kvm *), + int priority, const char *name); + +#define __init_list_add(cb, l) \ +static void __attribute__ ((constructor)) __init__##cb(void) \ +{ \ + static char name[] = #cb; \ + static struct init_item t; \ + init_list_add(&t, cb, l, name); \ +} + +#define __exit_list_add(cb, l) \ +static void __attribute__ ((constructor)) __init__##cb(void) \ +{ \ + static char name[] = #cb; \ + static struct init_item t; \ + exit_list_add(&t, cb, l, name); \ +} + +#define core_init(cb) __init_list_add(cb, 0) +#define base_init(cb) __init_list_add(cb, 2) +#define dev_base_init(cb) __init_list_add(cb, 4) +#define dev_init(cb) __init_list_add(cb, 5) +#define virtio_dev_init(cb) __init_list_add(cb, 6) +#define firmware_init(cb) __init_list_add(cb, 7) +#define late_init(cb) __init_list_add(cb, 9) + +#define core_exit(cb) __exit_list_add(cb, 0) +#define base_exit(cb) __exit_list_add(cb, 2) +#define dev_base_exit(cb) __exit_list_add(cb, 4) +#define dev_exit(cb) __exit_list_add(cb, 5) +#define virtio_dev_exit(cb) __exit_list_add(cb, 6) +#define firmware_exit(cb) __exit_list_add(cb, 7) +#define late_exit(cb) __exit_list_add(cb, 9) +#endif diff --git a/tools/kvm/util/init.c b/tools/kvm/util/init.c new file mode 100644 index 000000000000..33a595268021 --- /dev/null +++ b/tools/kvm/util/init.c @@ -0,0 +1,69 @@ +#include +#include + +#include "kvm/kvm.h" +#include "kvm/util-init.h" + +#define PRIORITY_LISTS 10 + +static struct hlist_head init_lists[PRIORITY_LISTS]; +static struct hlist_head exit_lists[PRIORITY_LISTS]; + +int init_list_add(struct init_item *t, int (*init)(struct kvm *), + int priority, const char *name) +{ + t->init = init; + t->fn_name = name; + hlist_add_head(&t->n, &init_lists[priority]); + + return 0; +} + +int exit_list_add(struct init_item *t, int (*init)(struct kvm *), + int priority, const char *name) +{ + t->init = init; + t->fn_name = name; + hlist_add_head(&t->n, &exit_lists[priority]); + + return 0; +} + +int init_list__init(struct kvm *kvm) +{ + unsigned int i; + int r = 0; + struct hlist_node *n; + struct init_item *t; + + for (i = 0; i < ARRAY_SIZE(init_lists); i++) + hlist_for_each_entry(t, n, &init_lists[i], n) { + r = t->init(kvm); + if (r < 0) { + pr_warning("Failed init: %s\n", t->fn_name); + goto fail; + } + } + +fail: + return r; +} + +int init_list__exit(struct kvm *kvm) +{ + int i; + int r = 0; + struct hlist_node *n; + struct init_item *t; + + for (i = ARRAY_SIZE(exit_lists) - 1; i >= 0; i--) + hlist_for_each_entry(t, n, &exit_lists[i], n) { + r = t->init(kvm); + if (r < 0) { + pr_warning("%s failed.\n", t->fn_name); + goto fail; + } + } +fail: + return r; +} -- 2.39.5