[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.