From patchwork Tue Mar 26 14:01:56 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: 231222 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 66DB52C0091 for ; Wed, 27 Mar 2013 01:12:12 +1100 (EST) Received: from localhost ([::1]:51948 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UKUbg-00068T-FD for incoming@patchwork.ozlabs.org; Tue, 26 Mar 2013 10:12:08 -0400 Received: from eggs.gnu.org ([208.118.235.92]:36779) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UKURu-0008Rk-Or for qemu-devel@nongnu.org; Tue, 26 Mar 2013 10:02:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UKURp-0008Dg-Vl for qemu-devel@nongnu.org; Tue, 26 Mar 2013 10:02:02 -0400 Received: from roura.ac.upc.es ([147.83.33.10]:37489) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UKURp-0008DH-IT for qemu-devel@nongnu.org; Tue, 26 Mar 2013 10:01:57 -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 r2QE1uKL005232 for ; Tue, 26 Mar 2013 15:01:56 +0100 Received: from localhost (unknown [84.88.51.85]) by gw.ac.upc.edu (Postfix) with ESMTP id 6486E6B01C4 for ; Tue, 26 Mar 2013 15:01:56 +0100 (CET) From: =?utf-8?b?TGx1w61z?= Vilanova To: qemu-devel@nongnu.org Date: Tue, 26 Mar 2013 15:01:56 +0100 Message-Id: <20130326140156.4471.26154.stgit@fimbulvetr.bsc.es> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <20130326140021.4471.99597.stgit@fimbulvetr.bsc.es> References: <20130326140021.4471.99597.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 r2QE1uKL005232 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 147.83.33.10 Subject: [Qemu-devel] [PATCH 17/22] instrument: Add client-side API to enumerate events 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 Signed-off-by: Lluís Vilanova --- .gitignore | 1 Makefile | 1 configure | 1 instrument/Makefile.objs | 13 +++ instrument/api-control.c | 14 +++ instrument/qemu-instr/control-internal.h | 48 ++++++++++ instrument/qemu-instr/control.h | 124 +++++++++++++++++++++++++++ instrument/qemu-instr/visibility-internal.h | 94 ++++++++++++++++++++ scripts/tracetool/backend/instr_dynamic.py | 3 + scripts/tracetool/backend/instr_none.py | 3 + scripts/tracetool/backend/instr_static.py | 3 + scripts/tracetool/format/api_events_h.py | 56 ++++++++++++ 12 files changed, 361 insertions(+) create mode 100644 instrument/api-control.c create mode 100644 instrument/qemu-instr/control-internal.h create mode 100644 instrument/qemu-instr/control.h create mode 100644 instrument/qemu-instr/visibility-internal.h create mode 100644 scripts/tracetool/format/api_events_h.py diff --git a/.gitignore b/.gitignore index a46e490..a7c66d4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ libcacard/trace/generated-tracers.c instrument/generated-tracers.h instrument/generated-tracers.c instrument/qemu-instr/events.h +instrument/qemu-instr/events-list.h *-timestamp *-softmmu *-darwin-user diff --git a/Makefile b/Makefile index 9137b31..feb395c 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,7 @@ ifdef CONFIG_TRACE_INSTRUMENT_DYNAMIC GENERATED_SOURCES += instrument/generated-tracers.c endif GENERATED_HEADERS += instrument/qemu-instr/events.h +GENERATED_HEADERS += instrument/qemu-instr/events-list.h GENERATED_HEADERS += trace/generated-events.h GENERATED_SOURCES += trace/generated-events.c diff --git a/configure b/configure index e1ac5ff..624dce4 100755 --- a/configure +++ b/configure @@ -290,6 +290,7 @@ QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS" QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" +QEMU_CFLAGS="-DBUILDING_QEMU $QEMU_CFLAGS" QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/include" if test "$debug_info" = "yes"; then CFLAGS="-g $CFLAGS" diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs index 9c7ea5c..40a2b81 100644 --- a/instrument/Makefile.objs +++ b/instrument/Makefile.objs @@ -40,6 +40,15 @@ $(obj)/qemu-instr/events.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.m < $< > $@," GEN $(patsubst %-timestamp,%,$@)") @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) +$(obj)/qemu-instr/events-list.h: $(obj)/qemu-instr/events-list.h-timestamp +$(obj)/qemu-instr/events-list.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak + $(call quiet-command,$(TRACETOOL) \ + --format=api-events-h \ + --backend=$(TRACE_INSTRUMENT_BACKEND) \ + $(TRACETOOL_INSTR_STATIC) \ + < $< > $@," GEN $(patsubst %-timestamp,%,$@)") + @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) + ###################################################################### # User code (static instrumentation) @@ -70,3 +79,7 @@ target-obj-y += control.o common-obj-$(CONFIG_SOFTMMU) += hmp.o common-obj-$(CONFIG_SOFTMMU) += qmp.o + +target-obj-y += api-control.o + +QEMU_CFLAGS += -I$(BUILD_DIR)/instrument -I$(SRC_PATH)/instrument diff --git a/instrument/api-control.c b/instrument/api-control.c new file mode 100644 index 0000000..10f2b45 --- /dev/null +++ b/instrument/api-control.c @@ -0,0 +1,14 @@ +/* + * Interface for controlling the state of events. + * + * Copyright (C) 2012 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. + */ + +#include "instrument/qemu-instr/control.h" + +#if defined(QI_TYPE_DYNAMIC) +#include "instrument/qemu-instr/control-internal.h" +#endif diff --git a/instrument/qemu-instr/control-internal.h b/instrument/qemu-instr/control-internal.h new file mode 100644 index 0000000..5898466 --- /dev/null +++ b/instrument/qemu-instr/control-internal.h @@ -0,0 +1,48 @@ +/* + * Interface for controlling the state of events. + * + * Copyright (C) 2012 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. + */ + +#include "trace/control.h" + + +QI_IDEF QIEvent* qi_ctrl_event_id(QIEventID id) +{ + return (QIEvent*)trace_event_id(id); +} + +QI_IDEF QIEvent* qi_ctrl_event_name(const char *name) +{ + return (QIEvent*)trace_event_name(name); +} + +QI_IDEF QIEvent* qi_ctrl_event_pattern(const char *pat, QIEvent *ev) +{ + return (QIEvent*)trace_event_pattern(pat, (TraceEvent*)ev); +} + +QI_IDEF bool qi_ctrl_event_is_pattern(const char *str) +{ + return trace_event_is_pattern(str); +} + +QI_IDEF QIEventID qi_ctrl_event_count(void) +{ + return (QIEventID)trace_event_count(); +} + + + +QI_IDEF QIEventID qi_ctrl_event_get_id(QIEvent *ev) +{ + return (QIEventID)trace_event_get_id((TraceEvent*)ev); +} + +QI_IDEF const char * qi_ctrl_event_get_name(QIEvent *ev) +{ + return trace_event_get_name((TraceEvent*)ev); +} diff --git a/instrument/qemu-instr/control.h b/instrument/qemu-instr/control.h new file mode 100644 index 0000000..f19b4d7 --- /dev/null +++ b/instrument/qemu-instr/control.h @@ -0,0 +1,124 @@ +/* + * Interface for controlling the state of events. + * + * Copyright (C) 2012 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. + */ + +#ifndef QI__CONTROL_H +#define QI__CONTROL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include + + +/** + * SECTION:control + * @section_id: qi-control + * @title: QEMU instrumentation event control interface + */ + +/** + * QIEvent: + * + * Opaque structure defining an instrumentation event. + */ +struct QIEvent; +typedef struct QIEvent QIEvent; + +/** + * QIEventID: + * + * Unique instrumentation event identifier. + * + * These are named as 'QI_EVENT_${EVENT}'. + * + * See also: qemu-instr/events-list.h + */ + +/** + * qi_ctrl_event_id: + * @id: Event identifier. + * + * Get an event by its identifier. + * + * This routine has a constant cost, as opposed to qi_ctrl_event_name() and + * qi_ctrl_event_pattern(). + * + * Pre-conditions: @id is valid. + * + * Returns: Pointer to selected #QIEvent. + * + */ +QI_IDECL QIEvent* qi_ctrl_event_id(QIEventID id); + +/** + * qi_ctrl_event_name: + * @id: Event name. + * + * Search an event by its name. + * + * Returns: Pointer to #QIEvent or #NULL if not found. + */ +QI_IDECL QIEvent* qi_ctrl_event_name(const char *name); + +/** + * qi_ctrl_event_pattern: + * @pat: Event name pattern. + * @ev: Event to start searching from (not included). + * + * Iteratively get all events with a given name pattern. + * + * Returns: pointer to #TraceEvent or #NULL if not found. + */ +QI_IDECL QIEvent* qi_ctrl_event_pattern(const char *pat, QIEvent *ev); + +/** + * qi_ctrl_event_is_pattern: + * + * Whether the given string is an event name pattern. + */ +QI_IDECL bool qi_ctrl_event_is_pattern(const char *str); + +/** + * qi_ctrl_event_count: + * + * Return the number of events. + */ +QI_IDECL QIEventID qi_ctrl_event_count(void); + + + +/** + * qi_ctrl_event_get_id: + * + * Get the identifier of an event. + */ +QI_IDECL QIEventID qi_ctrl_event_get_id(QIEvent *ev); + +/** + * qi_ctrl_event_get_name: + * + * Get the name of an event. + */ +QI_IDECL const char * qi_ctrl_event_get_name(QIEvent *ev); + + +#if !defined(QI_TYPE_DYNAMIC) +#include "instrument/qemu-instr/control-internal.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* QI__CONTROL_H */ diff --git a/instrument/qemu-instr/visibility-internal.h b/instrument/qemu-instr/visibility-internal.h new file mode 100644 index 0000000..b68075d --- /dev/null +++ b/instrument/qemu-instr/visibility-internal.h @@ -0,0 +1,94 @@ +/* + * Macros for symbol visibility. + * + * Copyright (C) 2012 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 of QEMU. + */ + +#ifndef QI__VISIBILITY_INTERNAL_H +#define QI__VISIBILITY_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +/** + * SECTION:visibility + * @section_id: qi-visibility + * @title: Symbol visibility + * + * This code is taken from http://gcc.gnu.org/wiki/Visibility. + */ + +/** + * QI_VPUBLIC: + * + * Make an element public to third-party code. + */ + +/** + * QI_VLOCAL: + * + * Make an element not visible to third-party code. + */ + +#if defined _WIN32 || defined __CYGWIN__ + #ifdef BUILDING_QEMU + #ifdef __GNUC__ + #define QI_VPUBLIC __attribute__ ((dllexport)) + #else + #define QI_VPUBLIC __declspec(dllexport) + #endif + #else + #ifdef __GNUC__ + #define QI_VPUBLIC __attribute__ ((dllimport)) + #else + #define QI_VPUBLIC __declspec(dllimport) + #endif + #endif + #define QI_VLOCAL +#else + #if __GNUC__ >= 4 + #define QI_VPUBLIC __attribute__ ((visibility ("default"))) + #define QI_VLOCAL __attribute__ ((visibility ("hidden"))) + #else + #define QI_VPUBLIC + #define QI_VLOCAL + #endif +#endif + +/** + * QI_IDECL: + * + * Instrumentation-type dependant declaration attribute for inlined routines. + */ + +#if defined(QI_TYPE_DYNAMIC) +#define QI_IDECL QI_VPUBLIC +#else +#define QI_IDECL static +#endif + +/** + * QI_IDEF: + * + * Instrumentation-type dependant definition attribute for inlined routines. + */ + +#if defined(QI_TYPE_DYNAMIC) +#define QI_IDEF +#else +#define QI_IDEF static inline +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* QI__VISIBILITY_INTERNAL_H */ diff --git a/scripts/tracetool/backend/instr_dynamic.py b/scripts/tracetool/backend/instr_dynamic.py index 5125a16..74a3565 100644 --- a/scripts/tracetool/backend/instr_dynamic.py +++ b/scripts/tracetool/backend/instr_dynamic.py @@ -88,3 +88,6 @@ def api_c(events): args = e.args, argnames = ", ".join(e.args.names()), ) + +def api_events_h(events): + pass diff --git a/scripts/tracetool/backend/instr_none.py b/scripts/tracetool/backend/instr_none.py index 93e57f9..b373992 100644 --- a/scripts/tracetool/backend/instr_none.py +++ b/scripts/tracetool/backend/instr_none.py @@ -39,3 +39,6 @@ def api_h(events): qemu_backend = e.api(e.QEMU_TRACE_BACKEND), argnames = ", ".join(e.args.names()), ) + +def api_events_h(events): + pass diff --git a/scripts/tracetool/backend/instr_static.py b/scripts/tracetool/backend/instr_static.py index 1f5520f..17ce68b 100644 --- a/scripts/tracetool/backend/instr_static.py +++ b/scripts/tracetool/backend/instr_static.py @@ -77,3 +77,6 @@ def api_h(events): argnames = ", ".join(e.args.names()), upper_name = e.name.upper(), ) + +def api_events_h(events): + pass diff --git a/scripts/tracetool/format/api_events_h.py b/scripts/tracetool/format/api_events_h.py new file mode 100644 index 0000000..c4fd839 --- /dev/null +++ b/scripts/tracetool/format/api_events_h.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Generate .h with event description for trace instrumentation clients. +""" + +__author__ = "Lluís Vilanova " +__copyright__ = "Copyright 2012, 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. */', + '', + '#ifndef QI__EVENTS_LIST_H', + '#define QI__EVENTS_LIST_H', + '', + '#ifdef __cplusplus', + 'extern "C" {', + '#endif', + '', + ) + + # event identifiers + out('typedef enum {') + + for e in events: + out(' QI_EVENT_%s,' % e.name.upper()) + + out(' QI_EVENT_COUNT', + '} QIEventID;', + '', + ) + + # static state + for e in events: + if 'disable' in e.properties: + enabled = 0 + else: + enabled = 1 + out('#define QI_EVENT_%s_ENABLED %d' % (e.name.upper(), enabled)) + + out('#ifdef __cplusplus', + '}', + '#endif', + '', + '#endif /* QI__EVENTS_LIST_H */', + '', + )