|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] xenalyze: add a basic plugin infrastructure
Allow xenalyze to be include (at build time) plugins that can do
per-record actions and a summary. These plugins can be in C or C++.
The plugins entry points are in struct plugin and pointers to all the
plugins linked in xenalyze are placed in a "plugin" section so
plugin_init() can find them all.
A new command line option (-p, --plugin=PLUGIN) is added to enable one
or more plugins.
A sample plugin (skeleton) is included (mostly because at least one
plugin must be present for the build to work).
Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
---
Makefile | 10 +++---
analyze.h | 55 ++++++++++++++++++++++++++++++++++
plugin.cc | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++
plugin.h | 48 +++++++++++++++++++++++++++++
plugin.hh | 42 ++++++++++++++++++++++++++
plugins/skeleton.cc | 31 +++++++++++++++++++
xenalyze.c | 72 +++++++++++++-------------------------------
7 files changed, 287 insertions(+), 55 deletions(-)
diff -r f4feecb06e49 Makefile
--- a/Makefile Tue Apr 24 18:37:35 2012 +0100
+++ b/Makefile Wed Apr 25 10:42:54 2012 +0100
@@ -1,6 +1,6 @@
CC = gcc
-CFLAGS += -g -O2
+CFLAGS += -g -O2 -I.
CFLAGS += -fno-strict-aliasing
CFLAGS += -std=gnu99
CFLAGS += -Wall -Wstrict-prototypes
@@ -11,9 +11,11 @@ CFLAGS += -D_LARGEFILE_SOURCE -D_LARGEF
CFLAGS += -mno-tls-direct-seg-refs
CFLAGS += -Werror
+CXXFLAGS := -g -O2 -I. -Wall -Werror -std=c++0x
+
BIN = xenalyze dump-raw
-HDRS = trace.h analyze.h mread.h
+HDRS = trace.h analyze.h mread.h plugin.h plugin.hh
all: $(BIN)
@@ -24,5 +26,5 @@ clean:
%: %.c $(HDRS) Makefile
$(CC) $(CFLAGS) -o $@ $<
-xenalyze: xenalyze.o mread.o
- $(CC) $(CFLAGS) -o $@ $^
+xenalyze: xenalyze.o mread.o plugin.o plugins/skeleton.o
+ $(CXX) $(CFLAGS) -o $@ $^
diff -r f4feecb06e49 analyze.h
--- a/analyze.h Tue Apr 24 18:37:35 2012 +0100
+++ b/analyze.h Wed Apr 25 10:42:54 2012 +0100
@@ -1,5 +1,8 @@
#ifndef __ANALYZE_H
# define __ANALYZE_H
+
+#include <stdint.h>
+
#define TRC_GEN_MAIN 0
#define TRC_SCHED_MAIN 1
#define TRC_DOM0OP_MAIN 2
@@ -47,4 +50,56 @@ enum {
};
#define TRC_HVM_OP_DESTROY_PROC (TRC_HVM_HANDLER + 0x100)
+
+typedef unsigned long long tsc_t;
+
+/* -- on-disk trace buffer definitions -- */
+struct trace_record {
+ union {
+ struct {
+ unsigned event:28,
+ extra_words:3,
+ cycle_flag:1;
+ union {
+ struct {
+ uint32_t tsc_lo, tsc_hi;
+ uint32_t data[7];
+ } tsc;
+ struct {
+ uint32_t data[7];
+ } notsc;
+ } u;
+ };
+ uint32_t raw[8];
+ };
+};
+
+/* -- General info about a current record -- */
+struct time_struct {
+ unsigned long long time;
+ unsigned int s, ns;
+};
+
+#define DUMP_HEADER_MAX 256
+
+struct record_info {
+ int cpu;
+ tsc_t tsc;
+ union {
+ unsigned event;
+ struct {
+ unsigned minor:12,
+ sub:4,
+ main:12,
+ unused:4;
+ } evt;
+ };
+ int extra_words;
+ int size;
+ uint32_t *d;
+ char dump_header[DUMP_HEADER_MAX];
+ struct time_struct t;
+ struct trace_record rec;
+};
+
#endif
diff -r f4feecb06e49 plugin.cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin.cc Wed Apr 25 10:42:54 2012 +0100
@@ -0,0 +1,84 @@
+/*
+ * Xenalyze plugin infrastructure.
+ *
+ * Copyright (C) 2012, Citrix Systems R&D Ltd, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <list>
+
+#include "plugin.hh"
+
+typedef std::list<struct plugin *> plugin_list;
+
+static plugin_list available;
+static plugin_list enabled;
+
+bool plugin_enable(const char *name)
+{
+ for (auto p = available.begin(); p != available.end(); p++) {
+ struct plugin *plugin = *p;
+ if (strcmp(plugin->name, name) == 0) {
+ enabled.push_back(plugin);
+ if (plugin->enable) {
+ plugin->enable(plugin);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void plugin_process(const struct record_info *ri)
+{
+ for (auto p = enabled.begin(); p != enabled.end(); p++) {
+ struct plugin *plugin = *p;
+ if (plugin->process) {
+ plugin->process(plugin, ri);
+ }
+ }
+}
+
+void plugin_summary(void)
+{
+ for (auto p = enabled.begin(); p != enabled.end(); p++) {
+ struct plugin *plugin = *p;
+ if (plugin->summary) {
+ printf("Summary for %s plugin:\n", plugin->name);
+ plugin->summary(plugin);
+ }
+ }
+}
+
+static void plugin_add(struct plugin *plugin)
+{
+ available.push_back(plugin);
+}
+
+void plugin_init(void)
+{
+ extern struct plugin *__start_plugin;
+ extern struct plugin *__stop_plugin;
+ struct plugin **p;
+
+ for (p = &__start_plugin; p < &__stop_plugin; p++) {
+ plugin_add(*p);
+ }
+}
+
+void plugin_process_wrapper(struct plugin *plugin, const struct record_info
*ri)
+{
+ xenalyze_plugin *p = static_cast<xenalyze_plugin*>(plugin->data);
+ p->process(ri);
+}
+
+void plugin_summary_wrapper(struct plugin *plugin)
+{
+ xenalyze_plugin *p = static_cast<xenalyze_plugin*>(plugin->data);
+ p->summary();
+ delete p;
+}
diff -r f4feecb06e49 plugin.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin.h Wed Apr 25 10:42:54 2012 +0100
@@ -0,0 +1,48 @@
+/*
+ * Xenalyze plugin C API.
+ *
+ * Copyright (C) 2012, Citrix Systems R&D Ltd, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#ifndef PLUGIN_H
+#define PLUGIN_H
+
+#include <stdbool.h>
+
+#include "analyze.h"
+#include "helpers.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct plugin;
+
+typedef void (*plugin_enable_f)(struct plugin *plugin);
+typedef void (*plugin_process_f)(struct plugin *plugin, const struct
record_info *ri);
+typedef void (*plugin_summary_f)(struct plugin *plugin);
+
+struct plugin {
+ const char *name;
+ plugin_enable_f enable;
+ plugin_process_f process;
+ plugin_summary_f summary;
+ void *data;
+};
+
+#define DEFINE_PLUGIN(p) \
+ struct plugin *__plugin_ ## p __attribute__((section("plugin"))) = &p
+
+void plugin_init(void);
+bool plugin_enable(const char *name);
+void plugin_process(const struct record_info *ri);
+void plugin_summary(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* #ifndef PLUGIN_H */
diff -r f4feecb06e49 plugin.hh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin.hh Wed Apr 25 10:42:54 2012 +0100
@@ -0,0 +1,42 @@
+/*
+ * Xenalyze plugin C++ API.
+ *
+ * Copyright (C) 2012, Citrix Systems R&D Ltd, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#ifndef PLUGIN_HH
+#define PLUGIN_HH
+
+#include "plugin.h"
+
+class xenalyze_plugin {
+public:
+ virtual ~xenalyze_plugin() {}
+
+ virtual void process(const struct record_info *ri) = 0;
+ virtual void summary() = 0;
+};
+
+#define DEFINE_CXX_PLUGIN(name, cls) \
+ static void __plugin_ ## cls ## _enable(struct plugin *plugin) \
+ { \
+ plugin->data = new cls(); \
+ } \
+ \
+ static struct plugin __plugin ## cls = { \
+ name, \
+ __plugin_ ## cls ## _enable, \
+ plugin_process_wrapper, \
+ plugin_summary_wrapper, \
+ }; \
+ DEFINE_PLUGIN(__plugin ## cls)
+
+extern "C" {
+void plugin_process_wrapper(struct plugin *plugin, const struct record_info
*ri);
+void plugin_summary_wrapper(struct plugin *plugin);
+}
+
+#endif /* #ifndef PLUGIN_HH */
diff -r f4feecb06e49 plugins/skeleton.cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/skeleton.cc Wed Apr 25 10:42:54 2012 +0100
@@ -0,0 +1,31 @@
+/*
+ * Skeleton xenalyze plugin.
+ *
+ * Copyright (C) 2012, Citrix Systems R&D Ltd, UK
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include "plugin.hh"
+
+class skeleton_plugin : xenalyze_plugin {
+public:
+ skeleton_plugin() {}
+ ~skeleton_plugin() {}
+
+ void process(const struct record_info *ri);
+ void summary(void);
+};
+
+void skeleton_plugin::process(const struct record_info *ri)
+{
+ /* Put per-trace record stuff here. */
+}
+
+void skeleton_plugin::summary(void)
+{
+ /* Print a summary of the results (if applicable). */
+}
+
+DEFINE_CXX_PLUGIN("skeleton", skeleton_plugin);
diff -r f4feecb06e49 xenalyze.c
--- a/xenalyze.c Tue Apr 24 18:37:35 2012 +0100
+++ b/xenalyze.c Wed Apr 25 10:42:54 2012 +0100
@@ -32,6 +32,7 @@
#include "trace.h"
#include "analyze.h"
#include "mread.h"
+#include "plugin.h"
#include <errno.h>
#include <strings.h>
#include <string.h>
@@ -40,8 +41,6 @@
struct mread_ctrl;
-typedef unsigned long long tsc_t;
-
#define DEFAULT_CPU_HZ 2400000000LL
#define ADDR_SPACE_BITS 48
#define DEFAULT_SAMPLE_SIZE 10240
@@ -260,57 +259,8 @@ struct {
.interval = { .msec = DEFAULT_INTERVAL_LENGTH },
};
-/* -- on-disk trace buffer definitions -- */
-struct trace_record {
- union {
- struct {
- unsigned event:28,
- extra_words:3,
- cycle_flag:1;
- union {
- struct {
- uint32_t tsc_lo, tsc_hi;
- uint32_t data[7];
- } tsc;
- struct {
- uint32_t data[7];
- } notsc;
- } u;
- };
- uint32_t raw[8];
- };
-};
-
FILE *warn = NULL;
-/* -- General info about a current record -- */
-struct time_struct {
- unsigned long long time;
- unsigned int s, ns;
-};
-
-#define DUMP_HEADER_MAX 256
-
-struct record_info {
- int cpu;
- tsc_t tsc;
- union {
- unsigned event;
- struct {
- unsigned minor:12,
- sub:4,
- main:12,
- unused:4;
- } evt;
- };
- int extra_words;
- int size;
- uint32_t *d;
- char dump_header[DUMP_HEADER_MAX];
- struct time_struct t;
- struct trace_record rec;
-};
-
/* -- Summary data -- */
struct cycle_framework {
tsc_t first_tsc, last_tsc, total_cycles;
@@ -8901,6 +8851,8 @@ void process_record(struct pcpu_info *p)
default:
process_generic(ri);
}
+
+ plugin_process(ri);
}
UPDATE_VOLUME(p, toplevel[toplevel], ri->size);
@@ -9484,6 +9436,7 @@ enum {
OPT_DUMP_ALL='a',
OPT_INTERVAL_LENGTH='i',
OPT_SUMMARY='s',
+ OPT_PLUGIN='p',
};
enum {
@@ -9954,6 +9907,15 @@ error_t cmd_parser(int key, char *arg, s
opt.tsc_loop_fatal = 1;
break;
+ case OPT_PLUGIN:
+ if (plugin_enable(arg)) {
+ G.output_defined = 1;
+ } else {
+ fprintf(stderr, "ERROR: No such plugin `%s'.\n", arg);
+ exit(1);
+ }
+ break;
+
case ARGP_KEY_ARG:
{
/* FIXME - strcpy */
@@ -10246,6 +10208,10 @@ const struct argp_option cmd_opts[] = {
.arg = "errlevel",
.doc = "Sets tolerance for errors found in the file. Default is 3; max
is 6.", },
+ { .name = "plugin",
+ .key = OPT_PLUGIN,
+ .arg = "PLUGIN",
+ .doc = "Enable a decoder or summary plugin.", },
{ 0 },
};
@@ -10265,6 +10231,8 @@ int main(int argc, char *argv[]) {
/* Start with warn at stderr. */
warn = stderr;
+ plugin_init();
+
argp_parse(&parser_def, argc, argv, 0, NULL, NULL);
if (G.trace_file == NULL)
@@ -10301,6 +10269,8 @@ int main(int argc, char *argv[]) {
if(opt.summary)
summary();
+ plugin_summary();
+
if(opt.report_pcpu)
report_pcpu();
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |