From patchwork Sun Apr 21 19:12:26 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Llu=C3=ADs_Vilanova?= X-Patchwork-Id: 238255 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 7A2172C0117 for ; Mon, 22 Apr 2013 05:50:10 +1000 (EST) Received: from localhost ([::1]:52782 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UTzk5-0005Aj-Sb for incoming@patchwork.ozlabs.org; Sun, 21 Apr 2013 15:16:05 -0400 Received: from eggs.gnu.org ([208.118.235.92]:34983) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UTzgb-0008Av-7C for qemu-devel@nongnu.org; Sun, 21 Apr 2013 15:12:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UTzgZ-0001nX-Eo for qemu-devel@nongnu.org; Sun, 21 Apr 2013 15:12:29 -0400 Received: from roura.ac.upc.es ([147.83.33.10]:33195) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UTzgZ-0001nJ-0f for qemu-devel@nongnu.org; Sun, 21 Apr 2013 15:12:27 -0400 Received: from gw.ac.upc.edu (gw.ac.upc.es [147.83.30.3]) by roura.ac.upc.es (8.13.8/8.13.8) with ESMTP id r3LJCQNc001813 for ; Sun, 21 Apr 2013 21:12:26 +0200 Received: from localhost (unknown [84.88.51.85]) by gw.ac.upc.edu (Postfix) with ESMTP id 491966B01A4 for ; Sun, 21 Apr 2013 21:12:26 +0200 (CEST) From: =?utf-8?b?TGx1w61z?= Vilanova To: qemu-devel@nongnu.org Date: Sun, 21 Apr 2013 21:12:26 +0200 Message-Id: <20130421191225.8947.89296.stgit@fimbulvetr.bsc.es> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <20130421191129.8947.77964.stgit@fimbulvetr.bsc.es> References: <20130421191129.8947.77964.stgit@fimbulvetr.bsc.es> User-Agent: StGit/0.16 MIME-Version: 1.0 X-MIME-Autoconverted: from 8bit to quoted-printable by roura.ac.upc.es id r3LJCQNc001813 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 147.83.33.10 Subject: [Qemu-devel] [PATCH v3 10/24] instrument: [dynamic] Call dynamically linked user-provided routines X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Provides a mechanism to dynamically change the routine invoked by 'trace_*'. Signed-off-by: Lluís Vilanova --- .gitignore | 1 Makefile | 4 + Makefile.objs | 6 ++ configure | 8 ++- instrument/Makefile.objs | 11 ++++ libcacard/Makefile | 2 - scripts/tracetool/__init__.py | 1 scripts/tracetool/backend/instr_dynamic.py | 87 ++++++++++++++++++++++++++++ scripts/tracetool/format/api_c.py | 24 ++++++++ scripts/tracetool/format/events_c.py | 36 +++++++++++- trace/event-internal.h | 12 ++++ 11 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 scripts/tracetool/backend/instr_dynamic.py create mode 100644 scripts/tracetool/format/api_c.py diff --git a/.gitignore b/.gitignore index 2c9695c..2a0ea2f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ trace/generated-events.h trace/generated-events.c libcacard/trace/generated-tracers.c instrument/generated-tracers.h +instrument/generated-tracers.c instrument/qemu-instr/events.h *-timestamp *-softmmu diff --git a/Makefile b/Makefile index 2d3431a..cf938be 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,9 @@ GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c GENERATED_HEADERS += instrument/generated-tracers.h +ifdef CONFIG_TRACE_INSTRUMENT_DYNAMIC +GENERATED_SOURCES += instrument/generated-tracers.c +endif GENERATED_HEADERS += instrument/qemu-instr/events.h GENERATED_HEADERS += trace/generated-events.h @@ -234,6 +237,7 @@ clean: @# May not be present in GENERATED_HEADERS rm -f trace/generated-tracers-dtrace.dtrace* rm -f trace/generated-tracers-dtrace.h* + rm -f instrument/generated-tracers.c* rm -f $(foreach f,$(GENERATED_HEADERS),$(f) $(f)-timestamp) rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp) rm -rf qapi-generated diff --git a/Makefile.objs b/Makefile.objs index e568c01..5f8ea2d 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -91,6 +91,11 @@ common-obj-y += qom/ common-obj-y += disas/ ###################################################################### +# instrumentation + +tools-obj-y += instrument/ + +###################################################################### # guest agent # FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed @@ -108,5 +113,6 @@ nested-vars += \ util-obj-y \ qga-obj-y \ block-obj-y \ + tools-obj-y \ common-obj-y dummy := $(call unnest-vars) diff --git a/configure b/configure index 0eafd5a..b51436f 100755 --- a/configure +++ b/configure @@ -1173,7 +1173,7 @@ echo " Available backends:" $($python "$source_path"/s echo " --with-trace-file=NAME Full PATH,NAME of file to store traces" echo " Default:trace-" echo " --with-trace-instrument=TYPE" -echo " Trace instrumentation type (none static; default: $trace_instrument)" +echo " Trace instrumentation type (none static dynamic; default: $trace_instrument)" echo " --with-trace-instrument-path=PATH" echo " Directory to build user-provided static trace event instrumentation library" echo " --disable-spice disable spice" @@ -3074,7 +3074,7 @@ fi ########################################## # Check instrumentation type case "$trace_instrument" in -none|static) ;; +none|static|dynamic) ;; *) echo "Error: invalid trace instrumentation type: $trace_instrument" exit 1 ;; @@ -3922,6 +3922,10 @@ if test "$trace_instrument" = "static"; then echo "TRACETOOL_INSTR_STATIC=--instr-static-path \"\$(TRACE_INSTRUMENT_PATH)\"" >> $config_host_mak QEMU_CFLAGS="-I\"$trace_instrument_path\" $QEMU_CFLAGS" fi +if test "$trace_instrument" = "dynamic"; then + echo "#define QI_TYPE_CONFIG_DYNAMIC 1" >> $config_qi + echo "CONFIG_TRACE_INSTRUMENT_DYNAMIC=y" >> $config_host_mak +fi ########################################## echo "TOOLS=$tools" >> $config_host_mak diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs index 4102b59..cae520d 100644 --- a/instrument/Makefile.objs +++ b/instrument/Makefile.objs @@ -17,6 +17,17 @@ ifdef CONFIG_TRACE_INSTRUMENT_STATIC .PHONY: $(obj)/generated-tracers.h-timestamp endif +$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp +$(obj)/generated-tracers.c-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak + $(call quiet-command,$(TRACETOOL) \ + --format=api-c \ + --backend=$(TRACE_INSTRUMENT_BACKEND) \ + < $< > $@," GEN $(patsubst %-timestamp,%,$@)") + @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) + +tools-obj-$(CONFIG_TRACE_INSTRUMENT_DYNAMIC) += generated-tracers.o +target-obj-$(CONFIG_TRACE_INSTRUMENT_DYNAMIC) += generated-tracers.o + ###################################################################### # User interface diff --git a/libcacard/Makefile b/libcacard/Makefile index c0a5d66..f3f9f28 100644 --- a/libcacard/Makefile +++ b/libcacard/Makefile @@ -7,7 +7,7 @@ libcacard-obj-y = $(stub-obj-y) $(libcacard-y) libcacard-obj-y += util/osdep.o util/cutils.o util/qemu-timer-common.o util/error.o libcacard-obj-$(CONFIG_WIN32) += util/oslib-win32.o util/qemu-thread-win32.o libcacard-obj-$(CONFIG_POSIX) += util/oslib-posix.o util/qemu-thread-posix.o -libcacard-obj-y += $(filter trace/%, $(util-obj-y)) +libcacard-obj-y += $(filter trace/%, $(util-obj-y)) $(filter instrument/%, $(util-obj-y)) libcacard-lobj-y=$(patsubst %.o,%.lo,$(libcacard-obj-y)) diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py index 5406a2b..7624982 100644 --- a/scripts/tracetool/__init__.py +++ b/scripts/tracetool/__init__.py @@ -182,6 +182,7 @@ class Event(object): QI_TRACE_INSTRUMENT = "qi_event_%(name)s" QI_TRACE_NOP = "qi_event_%(name)s_nop" QI_TRACE_BACKEND = "qi_event_%(name)s_trace" + QI_TRACE_CB = QI_TRACE_NOP def api(self, fmt = None): if fmt is None: diff --git a/scripts/tracetool/backend/instr_dynamic.py b/scripts/tracetool/backend/instr_dynamic.py new file mode 100644 index 0000000..a07ee64 --- /dev/null +++ b/scripts/tracetool/backend/instr_dynamic.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Dynamic instrumentation proxy. +""" + +__author__ = "Lluís Vilanova " +__copyright__ = "Copyright 2012-2013, Lluís Vilanova " +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out +import tracetool.format.qemu_h + + +def qemu_h(events): + for e in events: + if "instrument" not in e.properties: + continue + + out('extern void * %(qi)s_cb;', + 'static inline void %(qi)s(%(args)s)', + '{', + ' ((void (*)(%(argtypes)s))%(qi)s_cb)(%(argnames)s);', + '}', + qi = e.api(e.QI_TRACE_INSTRUMENT), + args = e.args, + argnames = ", ".join(e.args.names()), + argtypes = ", ".join(e.args.types()), + ) + + tracetool.format.qemu_h.process_common(events) + + + +def api_h(events): + out('#include ', + '', + ) + + for e in events: + if "instrument" not in e.properties: + continue + + out('QI_VPUBLIC void %(qi)s(%(args)s);', + 'void %(qi_nop)s(%(args)s);', + 'void %(qi_backend)s(%(args)s);', + qi = e.api(e.QI_TRACE_INSTRUMENT), + qi_nop = e.api(e.QI_TRACE_NOP), + qi_backend = e.api(e.QI_TRACE_BACKEND), + args = e.args, + ) + +def api_c(events): + out('#include "instrument/qemu-instr/events.h"', + '', + '#include "trace/generated-events.h"', + '#include "trace/generated-tracers.h"', + '', + ) + + for e in events: + if "instrument" not in e.properties: + continue + + out('void %(qi_nop)s(%(args)s)', + '{', + '}', + '', + 'void %(qi_backend)s(%(args)s)', + '{', + ' %(qemu_backend)s(%(argnames)s);', + '}', + '', + 'void * %(qi)s_cb = %(qi_cb)s;', + qi = e.api(e.QI_TRACE_INSTRUMENT), + qi_nop = e.api(e.QI_TRACE_NOP), + qi_backend = e.api(e.QI_TRACE_BACKEND), + qi_cb = e.api(e.QI_TRACE_CB), + qemu_backend = e.api(e.QEMU_TRACE_BACKEND), + args = e.args, + argnames = ", ".join(e.args.names()), + ) diff --git a/scripts/tracetool/format/api_c.py b/scripts/tracetool/format/api_c.py new file mode 100644 index 0000000..3787f5d --- /dev/null +++ b/scripts/tracetool/format/api_c.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Generate .c for trace instrumentation clients. +""" + +__author__ = "Lluís Vilanova " +__copyright__ = "Copyright 2012-2013, Lluís Vilanova " +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +def begin(events): + out('/* This file is autogenerated by tracetool, do not edit. */', + '', + '#include ', + '', + ) diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py index d670ec8..7531c66 100644 --- a/scripts/tracetool/format/events_c.py +++ b/scripts/tracetool/format/events_c.py @@ -6,7 +6,7 @@ Generate .c for event description. """ __author__ = "Lluís Vilanova " -__copyright__ = "Copyright 2012, Lluís Vilanova " +__copyright__ = "Copyright 2012-2013, Lluís Vilanova " __license__ = "GPL version 2 or (at your option) any later version" __maintainer__ = "Stefan Hajnoczi" @@ -19,17 +19,49 @@ from tracetool import out def begin(events): out('/* This file is autogenerated by tracetool, do not edit. */', '', + '#include "config-host.h"', '#include "trace.h"', '#include "trace/generated-events.h"', '#include "trace/control.h"', '', ) + # declarations + out('#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)') + for e in events: + if "instrument" in e.properties: + out('void %(nop)s(%(args)s);', + 'void %(backend)s(%(args)s);', + nop = e.api(e.QI_TRACE_NOP), + backend = e.api(e.QI_TRACE_BACKEND), + args = e.args, + ) + out('#endif', + '', + ) + + # event state out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {') for e in events: - out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },', + cb = cb_nop = cb_backend = "NULL" + + if "instrument" in e.properties: + cb = "&%s_cb" % e.api(e.QI_TRACE_INSTRUMENT) + cb_nop = e.api(e.QI_TRACE_NOP) + cb_backend = e.api(e.QI_TRACE_BACKEND) + + out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0,', + '#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)', + ' .instr_cb = %(cb)s,', + ' .instr_cb_nop = %(cb_nop)s,', + ' .instr_cb_backend = %(cb_backend)s,', + '#endif', + ' },', id = "TRACE_" + e.name.upper(), + cb = cb, + cb_nop = cb_nop, + cb_backend = cb_backend, name = e.name, sstate = "TRACE_%s_ENABLED" % e.name.upper(), ) diff --git a/trace/event-internal.h b/trace/event-internal.h index b2310d9..aed4050 100644 --- a/trace/event-internal.h +++ b/trace/event-internal.h @@ -1,7 +1,7 @@ /* * Interface for configuring and controlling the state of tracing events. * - * Copyright (C) 2012 Lluís Vilanova + * Copyright (C) 2012-2013 Lluís Vilanova * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -11,6 +11,7 @@ #define TRACE__EVENT_INTERNAL_H #include "trace/generated-events.h" +#include "config-host.h" /** @@ -19,6 +20,9 @@ * @name: Event name. * @sstate: Static tracing state. * @dstate: Dynamic tracing state. + * @instr_cb: Instrumentation callback pointer. + * @instr_cb_nop: Instrumentation callback pointer to no-operation. + * @instr_cb_backend: Instrumentation callback pointer to tracing backend. * * Opaque generic description of a tracing event. */ @@ -27,6 +31,12 @@ typedef struct TraceEvent { const char * name; const bool sstate; bool dstate; + +#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC) + void **instr_cb; + void *instr_cb_nop; + void *instr_cb_backend; +#endif } TraceEvent;