All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Vrabel <david.vrabel@citrix.com>
To: "xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Cc: George Dunlap <george.dunlap@citrix.com>
Subject: [PATCH] xenalyze: add a basic plugin infrastructure
Date: Wed, 25 Apr 2012 11:02:48 +0100	[thread overview]
Message-ID: <4F97CBC8.6010507@citrix.com> (raw)

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@citrix.com>
---
 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();

                 reply	other threads:[~2012-04-25 10:02 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F97CBC8.6010507@citrix.com \
    --to=david.vrabel@citrix.com \
    --cc=george.dunlap@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.