From 7a4bdb546094fea3343bfc80e3744ea26a08dd22 Mon Sep 17 00:00:00 2001 From: Yannick Brosseau Date: Wed, 30 May 2012 17:38:08 -0400 Subject: [PATCH] Initial port of the state system to the LTTng 2.0 trace format Rework the internal data structure (remove Tracefile.c, add a TraceState inside a Trace) There is no callback by event id anymore, so all state event handler receive all the events. Several files were reorganize (including moving them out of ltt to the lttv lib directly. The current implementation use a temporary State structure, so it can only support on trace. Signed-off-by: Mathieu Desnoyers Signed-off-by: Yannick Brosseau --- Makefile.am | 2 +- ltt/compiler.h | 2 + lttv/lttv/Makefile.am | 18 +- lttv/lttv/batchtest.c | 6 +- lttv/lttv/compiler.h | 61 ++ lttv/lttv/event.c | 129 +++ lttv/lttv/event.h | 13 + lttv/lttv/filter.c | 2 + lttv/lttv/filter.h | 2 +- lttv/lttv/hook.c | 128 +-- lttv/lttv/hook.h | 6 +- lttv/lttv/iattribute.h | 2 +- lttv/lttv/main.c | 3 + lttv/lttv/print.c | 76 +- lttv/lttv/print.h | 4 +- lttv/lttv/state.c | 1267 +++++++++++++---------------- lttv/lttv/state.h | 132 +-- lttv/lttv/stats.h | 2 + lttv/lttv/time.h | 250 ++++++ lttv/lttv/trace.h | 41 + lttv/lttv/tracecontext.c | 10 +- lttv/lttv/tracecontext.h | 406 --------- lttv/lttv/traceset-process.c | 198 +++++ lttv/lttv/traceset-process.h | 143 ++++ lttv/lttv/traceset.c | 101 ++- lttv/lttv/traceset.h | 50 +- lttv/modules/text/Makefile.am | 10 +- lttv/modules/text/batchAnalysis.c | 47 +- lttv/modules/text/textDump.c | 20 +- 29 files changed, 1677 insertions(+), 1454 deletions(-) create mode 100644 lttv/lttv/compiler.h create mode 100644 lttv/lttv/event.c create mode 100644 lttv/lttv/time.h create mode 100644 lttv/lttv/trace.h delete mode 100644 lttv/lttv/tracecontext.h create mode 100644 lttv/lttv/traceset-process.c create mode 100644 lttv/lttv/traceset-process.h diff --git a/Makefile.am b/Makefile.am index 89c23b15..9db2889f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ ACLOCAL_AMFLAGS = -I config -SUBDIRS = ltt lttv doc +SUBDIRS = lttv doc EXTRA_DIST = LTTngManual.html diff --git a/ltt/compiler.h b/ltt/compiler.h index 2b496a88..9bc0e49e 100644 --- a/ltt/compiler.h +++ b/ltt/compiler.h @@ -19,6 +19,8 @@ #ifndef COMPILER_H #define COMPILER_H +#error "Using old ltt/" + /* Fast prediction if likely branches */ #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) diff --git a/lttv/lttv/Makefile.am b/lttv/lttv/Makefile.am index b273d475..74b3b03d 100644 --- a/lttv/lttv/Makefile.am +++ b/lttv/lttv/Makefile.am @@ -1,7 +1,7 @@ SUBDIRS= sync AM_CFLAGS= $(PACKAGE_CFLAGS) -LDADD = $(POPT_LIBS) $(M_LIBS) $(GLPK_LIBS) ${top_builddir}/ltt/liblttvtraceread.la +LDADD = $(POPT_LIBS) $(M_LIBS) $(GLPK_LIBS) bin_PROGRAMS = lttv.real @@ -41,8 +41,11 @@ libdir = ${lttvplugindir} #noinst_HEADERS = \ # filter.h +#disabled for babeltrace port batchtest.c stats.c tracecontext.c filter.c + + + lttv_real_SOURCES = \ - batchtest.c\ main.c\ module.c\ option.c\ @@ -50,12 +53,13 @@ lttv_real_SOURCES = \ attribute.c\ iattribute.c\ state.c\ - stats.c\ - tracecontext.c\ traceset.c\ - filter.c\ + traceset-process.c\ print.c\ - sync/sync_chain.c\ + compiler.h\ + event.c\ + time.h +# sync/sync_chain.c\ sync/sync_chain.h\ sync/sync_chain_lttv.c\ sync/sync_chain_lttv.h\ @@ -98,7 +102,7 @@ lttvinclude_HEADERS = \ option.h\ state.h\ stats.h\ - tracecontext.h\ + traceset-process.h\ traceset.h\ filter.h\ print.h\ diff --git a/lttv/lttv/batchtest.c b/lttv/lttv/batchtest.c index a7e16420..6f422268 100644 --- a/lttv/lttv/batchtest.c +++ b/lttv/lttv/batchtest.c @@ -31,11 +31,9 @@ #include #include #include -#include #include -#include -#include -#include +#include +#include #define __UNUSED__ __attribute__((__unused__)) diff --git a/lttv/lttv/compiler.h b/lttv/lttv/compiler.h new file mode 100644 index 00000000..d621a8cc --- /dev/null +++ b/lttv/lttv/compiler.h @@ -0,0 +1,61 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef COMPILER_H +#define COMPILER_H + +/* Fast prediction if likely branches */ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + + +/* + * Check at compile time that something is of a particular type. + * Always evaluates to 1 so you may use it easily in comparisons. + */ +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) + +/* Deal with 32 wrap correctly */ +#define guint32_after(a,b) \ + (typecheck(guint32, a) && \ + typecheck(guint32, b) && \ + ((gint32)(b) - (gint32)(a) < 0)) +#define guint32_before(a,b) guint32_after(b,a) + +#define guint32_after_eq(a,b) \ + (typecheck(guint32, a) && \ + typecheck(guint32, b) && \ + ((gint32)(b) - (gint32)(a) <= 0)) +#define guint32_before_eq(a,b) guint32_after_eq(b,a) + +#define __EXPORT __attribute__ ((visibility ("default"))) + +#ifndef max +#define max(a,b) ((a)>(b)?(a):(b)) +#endif + +#ifndef min +#define min(a,b) ((a)<(b)?(a):(b)) +#endif + +#endif //COMPILER_H diff --git a/lttv/lttv/event.c b/lttv/lttv/event.c new file mode 100644 index 00000000..8c1b6d80 --- /dev/null +++ b/lttv/lttv/event.c @@ -0,0 +1,129 @@ + + + +#include +#include +#include + +LttTime lttv_event_get_timestamp(LttvEvent *event) +{ + return ltt_time_from_uint64(bt_ctf_get_timestamp(event->bt_event)); +} + +//TODO ybrosseau find a way to return an error code +unsigned long lttv_event_get_long_unsigned(LttvEvent *event, const char* field) +{ + struct definition *scope; + unsigned long timestamp; + unsigned long data; + struct bt_ctf_event *ctf_event = event->bt_event; + + timestamp = bt_ctf_get_timestamp(ctf_event); + if (timestamp == -1ULL) { + return 0; + } + //scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); + scope = bt_ctf_get_top_level_scope(ctf_event, BT_EVENT_FIELDS); + if (bt_ctf_field_get_error()) { + return 0; + } + data = bt_ctf_get_uint64(bt_ctf_get_field(ctf_event, scope, field)); + if (bt_ctf_field_get_error()) { + return 0; + } else { + return data; + } +} + + +char* lttv_event_get_string(LttvEvent *event, const char* field) +{ + struct definition *scope; + unsigned long timestamp; + char* data; + struct bt_ctf_event *ctf_event = event->bt_event; + + timestamp = bt_ctf_get_timestamp(ctf_event); + if (timestamp == -1ULL) { + return 0; + } + //scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); + scope = bt_ctf_get_top_level_scope(ctf_event, BT_EVENT_FIELDS); + if (bt_ctf_field_get_error()) { + return 0; + } + data = bt_ctf_get_char_array(bt_ctf_get_field(ctf_event, scope, field)); + if (bt_ctf_field_get_error()) { + return 0; + } else { + return data; + } +} +long lttv_event_get_long(LttvEvent *event, const char* field) +{ + struct definition *scope; + unsigned long timestamp; + long data; + struct bt_ctf_event *ctf_event = event->bt_event; + + timestamp = bt_ctf_get_timestamp(ctf_event); + if (timestamp == -1ULL) { + return 0; + } + scope = bt_ctf_get_top_level_scope(ctf_event, BT_EVENT_FIELDS); + if (bt_ctf_field_get_error()) { + return 0; + } + data = bt_ctf_get_int64(bt_ctf_get_field(ctf_event, scope, field)); + if (bt_ctf_field_get_error()) { + return 0; + } else { + return data; + } +} +/* +unsigned int lttv_event_get_int_unsigned(LttvEvent *event, const char* field) +{ + struct definition *scope; + unsigned long timestamp; + char* data; + struct bt_ctf_event *ctf_event = event->bt_event; + + timestamp = bt_ctf_get_timestamp(ctf_event); + if (timestamp == -1ULL) { + return 0; + } + scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); + if (bt_ctf_field_get_error()) { + return 0; + } + data = bt_ctf_get_char_array(bt_ctf_get_field(ctf_event, scope, field)); + if (bt_ctf_field_get_error()) { + return 0; + } else { + return data; + } +} +int lttv_event_get_int(LttvEvent *event, const char* field) +{ + struct definition *scope; + unsigned long timestamp; + char* data; + struct bt_ctf_event *ctf_event = event->bt_event; + + timestamp = bt_ctf_get_timestamp(ctf_event); + if (timestamp == -1ULL) { + return 0; + } + scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); + if (bt_ctf_field_get_error()) { + return 0; + } + data = bt_ctf_get_char_array(bt_ctf_get_field(ctf_event, scope, field)); + if (bt_ctf_field_get_error()) { + return 0; + } else { + return data; + } +} +*/ diff --git a/lttv/lttv/event.h b/lttv/lttv/event.h index ce15bf60..ebdb331b 100644 --- a/lttv/lttv/event.h +++ b/lttv/lttv/event.h @@ -18,8 +18,11 @@ #ifndef LTTV_EVENT_H #define LTTV_EVENT_H +#include +#include /* Forward declaration */ struct bt_ctf_event; +//struct LttvTraceState; /* Basic event container used through LTTV */ @@ -29,4 +32,14 @@ typedef struct LttvTraceState *state; } LttvEvent; +LttTime lttv_event_get_timestamp(LttvEvent *event); +unsigned long lttv_event_get_long_unsigned(LttvEvent *event, const char* field); +long lttv_event_get_long(LttvEvent *event, const char* field); +/*unsigned int lttv_event_get_int_unsigned(LttvEvent *event, const char* field); +int lttv_event_get_int(LttvEvent *event, const char* field); +*/ + +char* lttv_event_get_string(LttvEvent *event, const char* field); + + #endif /* LTTV_EVENT_H */ diff --git a/lttv/lttv/filter.c b/lttv/lttv/filter.c index ed94f0e9..592e562c 100644 --- a/lttv/lttv/filter.c +++ b/lttv/lttv/filter.c @@ -2213,6 +2213,7 @@ gboolean lttv_filter_tree_parse_branch( return se->op((gpointer)&count,v); } break; +#if BABEL_CLEANUP case LTTV_FILTER_EVENT_TARGET_PID: if(context == NULL) return TRUE; else { @@ -2221,6 +2222,7 @@ gboolean lttv_filter_tree_parse_branch( return se->op((gpointer)&target_pid,v); } break; +#endif case LTTV_FILTER_EVENT_FIELD: /* * TODO: Use the offset to diff --git a/lttv/lttv/filter.h b/lttv/lttv/filter.h index 1bbd5f51..7b60ab40 100644 --- a/lttv/lttv/filter.h +++ b/lttv/lttv/filter.h @@ -47,7 +47,7 @@ #include -#include +#include #include #include #include diff --git a/lttv/lttv/hook.c b/lttv/lttv/hook.c index 57dcb049..62918cd5 100644 --- a/lttv/lttv/hook.c +++ b/lttv/lttv/hook.c @@ -40,7 +40,7 @@ gint lttv_hooks_prio_compare(LttvHookClosure *a, LttvHookClosure *b) } -LttvHooks *lttv_hooks_new() +LttvHooks *lttv_hooks_new(void) { return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure)); } @@ -393,130 +393,4 @@ gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1, } return FALSE; - -} - -/* Two pointer arrays : - * * one indexed by id for quick search : - * size : max id - * typically 4 bytes * 256 facilities * 10 events = 10kbytes - * * another array that keeps a list of used numbers (for later deletion) - * size : number of ids used. - */ - -LttvHooksById *lttv_hooks_by_id_new() -{ - LttvHooksById *h = g_new(LttvHooksById, 1); - h->index = g_ptr_array_sized_new(PREALLOC_EVENTS); - h->array = g_array_sized_new(FALSE, FALSE, sizeof(guint), PREALLOC_EVENTS); - return h; -} - - -void lttv_hooks_by_id_destroy(LttvHooksById *h) -{ - guint i; - - for(i = 0 ; i < h->array->len ; i++) { - guint index = g_array_index(h->array, guint, i); - if(h->index->pdata[index] != NULL) { /* hook may have been removed */ - lttv_hooks_destroy(h->index->pdata[index]); - h->index->pdata[index] = NULL; /* Must be there in case of - multiple addition of the same index */ - } - } - g_ptr_array_free(h->index, TRUE); - g_array_free(h->array, TRUE); -} - -/* Optimised for searching an existing hook */ -LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id) -{ - if(unlikely(h->index->len <= id)) g_ptr_array_set_size(h->index, id + 1); - if(unlikely(h->index->pdata[id] == NULL)) { - h->index->pdata[id] = lttv_hooks_new(); - g_array_append_val(h->array, id); - } - return h->index->pdata[id]; -} - - -unsigned lttv_hooks_by_id_max_id(LttvHooksById *h) -{ - return h->index->len; -} - -/* We don't bother removing the used slot array id : lttv_hooks_by_id_destroy is - * almost never called and is able to deal with used slot repetition. */ -void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id) -{ - if(likely(id < h->index->len && h->index->pdata[id] != NULL)) { - lttv_hooks_destroy((LttvHooks *)h->index->pdata[id]); - h->index->pdata[id] = NULL; - } -} - -void lttv_hooks_by_id_copy(LttvHooksById *dest, LttvHooksById *src) -{ - guint i; - - for(i = 0 ; i < src->array->len ; i++) { - guint index = g_array_index(src->array, guint, i); - LttvHooks *srch = lttv_hooks_by_id_find(src, index); - LttvHooks *desth = lttv_hooks_by_id_find(dest, index); - lttv_hooks_add_list(desth, srch); - } -} - -LttvHooksByIdChannelArray *lttv_hooks_by_id_channel_new(void) -{ - LttvHooksByIdChannelArray *h = g_new(LttvHooksByIdChannelArray, 1); - - h->array = g_array_new(FALSE, FALSE, sizeof(LttvHooksByIdChannel)); - return h; -} - -void lttv_hooks_by_id_channel_destroy(LttvHooksByIdChannelArray *h) -{ - LttvHooksByIdChannel *hid; - int i; - - for (i = 0; i < h->array->len; i++) { - hid = &g_array_index(h->array, LttvHooksByIdChannel, i); - lttv_hooks_by_id_destroy(hid->hooks_by_id); - } - g_array_free(h->array, TRUE); - g_free(h); -} - -static LttvHooksByIdChannel * -lttv_hooks_by_id_channel_find_channel(LttvHooksByIdChannelArray *h, - GQuark channel) -{ - LttvHooksByIdChannel *hid; - int i, found = 0; - - for (i = 0; i < h->array->len; i++) { - hid = &g_array_index(h->array, LttvHooksByIdChannel, i); - if (hid->channel == channel) { - found = 1; - break; - } - } - if (!found) { - g_array_set_size(h->array, h->array->len + 1); - hid = &g_array_index(h->array, LttvHooksByIdChannel, h->array->len - 1); - hid->channel = channel; - hid->hooks_by_id = lttv_hooks_by_id_new(); - } - return hid; -} - -/* get, or create if not found */ -LttvHooks *lttv_hooks_by_id_channel_find(LttvHooksByIdChannelArray *h, - GQuark channel, guint16 id) -{ - LttvHooksByIdChannel *hid; - hid = lttv_hooks_by_id_channel_find_channel(h, channel); - return lttv_hooks_by_id_find(hid->hooks_by_id, id); } diff --git a/lttv/lttv/hook.h b/lttv/lttv/hook.h index c5a71b75..81383b5b 100644 --- a/lttv/lttv/hook.h +++ b/lttv/lttv/hook.h @@ -22,7 +22,7 @@ #define HOOK_H #include -#include +#include /* A hook is a function to call with the supplied hook data, and with call site specific data (e.g., hooks for events are called with a @@ -120,6 +120,8 @@ gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1, gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1, LttvHooks *h2, void *call_data2); +#ifdef BABEL_CLEANUP + /* Sometimes different hooks need to be called based on the case. The case is represented by an unsigned integer id */ @@ -184,4 +186,6 @@ void lttv_hooks_by_id_channel_destroy(LttvHooksByIdChannelArray *h); LttvHooks *lttv_hooks_by_id_channel_find(LttvHooksByIdChannelArray *h, GQuark channel, guint16 id); +#endif /* BABEL_CLEANUP */ + #endif // HOOK_H diff --git a/lttv/lttv/iattribute.h b/lttv/lttv/iattribute.h index d56f320b..01e60f43 100644 --- a/lttv/lttv/iattribute.h +++ b/lttv/lttv/iattribute.h @@ -23,7 +23,7 @@ #include -#include +#include /* The content of a data structure may be seen as an array of pairs of * attribute name and value. This simple model allows generic navigation diff --git a/lttv/lttv/main.c b/lttv/lttv/main.c index d3b69fb6..a24e6bb6 100644 --- a/lttv/lttv/main.c +++ b/lttv/lttv/main.c @@ -278,7 +278,10 @@ void lttv_debug(void *hook_data) void lttv_event_debug(void *hook_data) { + #warning lttv_event_debug does nothing +#ifdef BABEL_CLEANUP ltt_event_debug(1); +#endif g_info("Output event detailed debug"); } diff --git a/lttv/lttv/print.c b/lttv/lttv/print.c index e87cb3e1..5707175c 100644 --- a/lttv/lttv/print.c +++ b/lttv/lttv/print.c @@ -32,8 +32,10 @@ #include #include #include +#ifdef BABEL_CLEANUP #include #include +#endif #include #include #include @@ -45,12 +47,11 @@ #include #include #include - +#include +#ifdef BABEL_CLEANUP static inline void print_enum_events(LttEvent *e, struct marker_field *f, guint64 value, GString *s, LttvTracefileState *tfs) { - LttTracefile *tf = tfs->parent.tf; - struct marker_info *info = marker_get_info_from_id(tf->mdata, e->event_id); LttvTraceState *ts = (LttvTraceState*)(tfs->parent.t_context); LttvNameTables *nt = ts->name_tables; @@ -259,10 +260,10 @@ void lttv_print_field(LttEvent *e, struct marker_field *f, GString *s, break; } } - -int getProcessInfosFromEvent(struct bt_ctf_event *ctf_event, GString* processInfos) +#endif +int getProcessInfosFromEvent(LttvEvent *event, GString* processInfos) { - int pid, tid, ppid; + int pid=0, tid=0, ppid=0; char *procname; struct definition *scope; unsigned long timestamp; @@ -271,10 +272,25 @@ int getProcessInfosFromEvent(struct bt_ctf_event *ctf_event, GString* processInf gboolean noError = TRUE; + guint cpu; + LttvTraceState *state = event->state; + LttvProcessState *process; + struct bt_ctf_event *ctf_event = event->bt_event; + + cpu = lttv_traceset_get_cpuid_from_event(event); + + process = state->running_process[cpu]; + timestamp = bt_ctf_get_timestamp(ctf_event); + + pid = process->pid; + tid = process->tgid; + ppid = process->ppid; + procname = g_quark_to_string(process->name); if (timestamp == -1ULL) { noError = FALSE; } +#if 0 if (noError) { scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_EVENT_CONTEXT); if (bt_ctf_field_get_error()) { @@ -305,8 +321,8 @@ int getProcessInfosFromEvent(struct bt_ctf_event *ctf_event, GString* processInf noError = FALSE; } } - - if (noError) { +#endif + if (noError||1) { g_string_append_printf(processInfos, "%u, %u, %s, %u", pid, tid, procname, ppid); } else { @@ -316,41 +332,17 @@ int getProcessInfosFromEvent(struct bt_ctf_event *ctf_event, GString* processInf return ret; } - -int getCPUIdFromEvent(struct bt_ctf_event *ctf_event, GString* cpuId_str) +static +int getCPUIdFromEvent(LttvEvent *event, GString* cpuId_str) { - struct definition *scope; - unsigned long timestamp; - unsigned int cpu_id; - int ret = 0; + gint cpuid; - gboolean noError = TRUE; - - timestamp = bt_ctf_get_timestamp(ctf_event); - if (timestamp == -1ULL) { - noError = FALSE; - } - if (noError) { - scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); - if (bt_ctf_field_get_error()) { - noError = FALSE; - } - } - if (noError) { - cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(ctf_event, scope, "cpu_id")); - if (bt_ctf_field_get_error()) { - noError = FALSE; - } - else { - g_string_append_printf(cpuId_str, "%u", cpu_id); - } - } - - if (!noError) { - ret = -1; + cpuid = lttv_traceset_get_cpuid_from_event(event); + if (cpuid < 0) { + return -1; } - - return ret; + g_string_append_printf(cpuId_str, "%u", cpuid); + return 0; } int getFields(struct bt_ctf_event *ctf_event, struct definition const *fields, GString* fieldsStr) @@ -444,9 +436,9 @@ void lttv_event_to_string(LttvEvent *event, GString *a_string, gboolean field_na GString* fields = g_string_new(""); GString* cpuId_str = g_string_new(""); - getProcessInfosFromEvent(event->bt_event, processInfos); + getProcessInfosFromEvent(event, processInfos); getFieldsFromEvent(event->bt_event, fields, field_names); - getCPUIdFromEvent(event->bt_event, cpuId_str); + getCPUIdFromEvent(event, cpuId_str); g_string_set_size(a_string,0); diff --git a/lttv/lttv/print.h b/lttv/lttv/print.h index 0dd838b0..47cfb61c 100644 --- a/lttv/lttv/print.h +++ b/lttv/lttv/print.h @@ -25,10 +25,10 @@ */ #include - +#ifdef BABEL_CLEANUP void lttv_print_field(LttEvent *e, struct marker_field *f, GString *s, gboolean field_names, LttvTracefileState *tfs); -#ifdef BABEL_CLEANUP + void lttv_event_to_string(LttEvent *e, GString *s, gboolean mandatory_fields, gboolean field_names, LttvTracefileState *tfs); #endif diff --git a/lttv/lttv/state.c b/lttv/lttv/state.c index f3c4bb7d..792e3cbe 100644 --- a/lttv/lttv/state.c +++ b/lttv/lttv/state.c @@ -25,25 +25,12 @@ #include #include #include -#include -#include -#include -#include +#include +#include #include #include -#include #include -/* Comment : - * Mathieu Desnoyers - * usertrace is there only to be able to update the current CPU of the - * usertraces when there is a schedchange. it is a way to link the ProcessState - * to the associated usertrace. Link only created upon thread creation. - * - * The cpu id is necessary : it gives us back the current ProcessState when we - * are considering data from the usertrace. - */ - #define PREALLOCATED_EXECUTION_STACK 10 /* Channel Quarks */ @@ -75,8 +62,8 @@ GQuark LTT_EVENT_PAGE_FAULT_NOSEM_EXIT, LTT_EVENT_PAGE_FAULT_ENTRY, LTT_EVENT_PAGE_FAULT_EXIT, - LTT_EVENT_TRAP_ENTRY, - LTT_EVENT_TRAP_EXIT, + //LTT_EVENT_TRAP_ENTRY, + //LTT_EVENT_TRAP_EXIT, LTT_EVENT_IRQ_ENTRY, LTT_EVENT_IRQ_EXIT, LTT_EVENT_SOFT_IRQ_RAISE, @@ -196,7 +183,7 @@ static GQuark LTTV_STATE_PROCESSES, LTTV_STATE_PROCESS, LTTV_STATE_RUNNING_PROCESS, - LTTV_STATE_EVENT, + LTTV_STATE_POSITION, LTTV_STATE_SAVED_STATES, LTTV_STATE_SAVED_STATES_TIME, LTTV_STATE_TIME, @@ -235,7 +222,7 @@ static LttvBdevState *bdevstate_new(void); static void bdevstate_free(LttvBdevState *); static void bdevstate_free_cb(gpointer key, gpointer value, gpointer user_data); static LttvBdevState *bdevstate_copy(LttvBdevState *bds); - +void lttv_state_add_event_hooks(LttvTraceset *traceset); #if (__WORDSIZE == 32) guint guint64_hash(gconstpointer key) @@ -254,25 +241,6 @@ gboolean guint64_equal(gconstpointer a, gconstpointer b) } #endif -void lttv_state_save(LttvTraceState *self, LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container); -} - - -void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); -} - - -void lttv_state_state_saved_free(LttvTraceState *self, - LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container); -} - - guint process_hash(gconstpointer key) { guint pid = ((const LttvProcessState *)key)->pid; @@ -297,17 +265,6 @@ gboolean process_equal(gconstpointer a, gconstpointer b) return ret; } -static void delete_usertrace(gpointer key, gpointer value, gpointer user_data) -{ - g_tree_destroy((GTree*)value); -} - -static void lttv_state_free_usertraces(GHashTable *usertraces) -{ - g_hash_table_foreach(usertraces, delete_usertrace, NULL); - g_hash_table_destroy(usertraces); -} - gboolean rettrue(gpointer key, gpointer value, gpointer user_data) { return TRUE; @@ -343,20 +300,6 @@ static void fill_name_table(LttvTraceState *ts, GQuark *table, guint nb, g_string_free(fe_name, TRUE); } -static void expand_syscall_table(LttvTraceState *ts, int id) -{ - LttvNameTables *nt = ts->name_tables; - guint new_nb; - - new_nb = check_expand(nt->nb_syscalls, id); - if(likely(new_nb == nt->nb_syscalls)) - return; - expand_name_table(ts, &nt->syscall_names, nt->nb_syscalls, new_nb); - fill_name_table(ts, nt->syscall_names, nt->nb_syscalls, new_nb, "syscall"); - /* Update the table size */ - nt->nb_syscalls = new_nb; -} - static void expand_kprobe_table(LttvTraceState *ts, guint64 ip, char *symbol) { LttvNameTables *nt = ts->name_tables; @@ -450,13 +393,11 @@ static void restore_init_state(LttvTraceState *self) //LttvTracefileState *tfcs; - LttTime start_time, end_time; + //LttTime start_time, end_time; /* Free the process tables */ if(self->processes != NULL) lttv_state_free_process_table(self->processes); - if(self->usertraces != NULL) lttv_state_free_usertraces(self->usertraces); self->processes = g_hash_table_new(process_hash, process_equal); - self->usertraces = g_hash_table_new(g_direct_hash, g_direct_equal); self->nb_event = 0; /* Seek time to beginning */ @@ -466,11 +407,12 @@ static void restore_init_state(LttvTraceState *self) //g_tree_destroy(self->parent.ts_context->pqueue); //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile); - ltt_trace_time_span_get(self->parent.t, &start_time, &end_time); + //TODO use babeltrace one. + //ltt_trace_time_span_get(self->parent.t, &start_time, &end_time); //lttv_process_trace_seek_time(&self->parent, ltt_time_zero); - nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + nb_cpus = lttv_trace_get_num_cpu(self->trace); nb_irqs = self->name_tables->nb_irqs; nb_soft_irqs = self->name_tables->nb_soft_irqs; nb_traps = self->name_tables->nb_traps; @@ -479,7 +421,8 @@ static void restore_init_state(LttvTraceState *self) for(i=0; i< nb_cpus; i++) { LttvExecutionState *es; self->running_process[i] = lttv_state_create_process(self, NULL, i, 0, 0, - LTTV_STATE_UNNAMED, &start_time); + //TODO use &start_time... + LTTV_STATE_UNNAMED, <t_time_zero); /* We are not sure is it's a kernel thread or normal thread, put the * bottom stack state to unknown */ self->running_process[i]->execution_stack = @@ -551,19 +494,7 @@ static void restore_init_state(LttvTraceState *self) //static LttTime time_zero = {0,0}; -static gint compare_usertraces(gconstpointer a, gconstpointer b, - gpointer user_data) -{ - const LttTime *t1 = (const LttTime *)a; - const LttTime *t2 = (const LttTime *)b; - - return ltt_time_compare(*t1, *t2); -} - -static void free_usertrace_key(gpointer data) -{ - g_free(data); -} +#ifdef BABEL_CLEANUP #define MAX_STRING_LEN 4096 @@ -642,162 +573,89 @@ end: g_ptr_array_free(quarktable, TRUE); return; } +#endif /* BABEL_CLEANUP */ -static void init(LttvTracesetState *self, LttvTraceset *ts) +void lttv_trace_state_init(LttvTraceState *trace_state, LttvTrace *trace) { - guint i, j, nb_trace, nb_tracefile, nb_cpu; + guint j, nb_cpu; guint64 nb_irq; - - LttvTraceContext *tc; - - LttvTraceState *tcs; - - LttvTracefileState *tfcs; - LttvAttributeValue v; - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - init((LttvTracesetContext *)self, ts); + trace_state->trace = trace; - nb_trace = lttv_traceset_number(ts); + trace_state->save_interval = LTTV_STATE_SAVE_INTERVAL; + lttv_attribute_find(lttv_trace_attribute(trace), LTTV_STATE_TRACE_STATE_USE_COUNT, + LTTV_UINT, &v); + (*v.v_uint)++; -#ifdef BABEL_CLEANUP - for(i = 0 ; i < nb_trace ; i++) { - tc = self->parent.traces[i]; - tcs = LTTV_TRACE_STATE(tc); - tcs->save_interval = LTTV_STATE_SAVE_INTERVAL; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT, - LTTV_UINT, &v); - (*v.v_uint)++; - - if(*(v.v_uint) == 1) { - create_name_tables(tcs); - create_max_time(tcs); - } - get_name_tables(tcs); - get_max_time(tcs); - - nb_tracefile = tc->tracefiles->len; - nb_cpu = ltt_trace_get_num_cpu(tc->t); - nb_irq = tcs->name_tables->nb_irqs; - tcs->processes = NULL; - tcs->usertraces = NULL; - tcs->running_process = g_new(LttvProcessState*, nb_cpu); - - /* init cpu resource stuff */ - tcs->cpu_states = g_new(LttvCPUState, nb_cpu); - for(j = 0; jcpu_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode)); - tcs->cpu_states[j].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint)); - tcs->cpu_states[j].softirq_stack = g_array_new(FALSE, FALSE, sizeof(gint)); - tcs->cpu_states[j].trap_stack = g_array_new(FALSE, FALSE, sizeof(gint)); - g_assert(tcs->cpu_states[j].mode_stack != NULL); - } + if (*(v.v_uint) == 1) { + create_name_tables(trace_state); + create_max_time(trace_state); + } + get_name_tables(trace_state); + get_max_time(trace_state); + + nb_cpu = lttv_trace_get_num_cpu(trace); + nb_irq = trace_state->name_tables->nb_irqs; + trace_state->processes = NULL; + trace_state->running_process = g_new(LttvProcessState*, nb_cpu); + + /* init cpu resource stuff */ + trace_state->cpu_states = g_new(LttvCPUState, nb_cpu); + for (j = 0; j < nb_cpu; j++) { + trace_state->cpu_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode)); + trace_state->cpu_states[j].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint)); + trace_state->cpu_states[j].softirq_stack = g_array_new(FALSE, FALSE, sizeof(gint)); + trace_state->cpu_states[j].trap_stack = g_array_new(FALSE, FALSE, sizeof(gint)); + g_assert(trace_state->cpu_states[j].mode_stack != NULL); + } - /* init irq resource stuff */ - tcs->irq_states = g_new(LttvIRQState, nb_irq); - for(j = 0; jirq_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvIRQMode)); - g_assert(tcs->irq_states[j].mode_stack != NULL); - } + /* init irq resource stuff */ + trace_state->irq_states = g_new(LttvIRQState, nb_irq); + for (j = 0; j < nb_irq; j++) { + trace_state->irq_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvIRQMode)); + g_assert(trace_state->irq_states[j].mode_stack != NULL); + } - /* init soft irq stuff */ - /* the kernel has a statically fixed max of 32 softirqs */ - tcs->soft_irq_states = g_new(LttvSoftIRQState, tcs->name_tables->nb_soft_irqs); + /* init soft irq stuff */ + /* the kernel has a statically fixed max of 32 softirqs */ + trace_state->soft_irq_states = g_new(LttvSoftIRQState, trace_state->name_tables->nb_soft_irqs); - /* init trap stuff */ - tcs->trap_states = g_new(LttvTrapState, tcs->name_tables->nb_traps); + /* init trap stuff */ + trace_state->trap_states = g_new(LttvTrapState, trace_state->name_tables->nb_traps); - /* init bdev resource stuff */ - tcs->bdev_states = g_hash_table_new(g_int_hash, g_int_equal); + /* init bdev resource stuff */ + trace_state->bdev_states = g_hash_table_new(g_int_hash, g_int_equal); - restore_init_state(tcs); - for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = - LTTV_TRACEFILE_STATE(g_array_index(tc->tracefiles, - LttvTracefileContext*, j)); - tfcs->tracefile_name = ltt_tracefile_name(tfcs->parent.tf); - tfcs->cpu = ltt_tracefile_cpu(tfcs->parent.tf); - tfcs->cpu_state = &(tcs->cpu_states[tfcs->cpu]); - if(ltt_tracefile_tid(tfcs->parent.tf) != 0) { - /* It's a Usertrace */ - guint tid = ltt_tracefile_tid(tfcs->parent.tf); - GTree *usertrace_tree = (GTree*)g_hash_table_lookup(tcs->usertraces, - GUINT_TO_POINTER(tid)); - if(!usertrace_tree) { - usertrace_tree = g_tree_new_full(compare_usertraces, - NULL, free_usertrace_key, NULL); - g_hash_table_insert(tcs->usertraces, - GUINT_TO_POINTER(tid), usertrace_tree); - } - LttTime *timestamp = g_new(LttTime, 1); - *timestamp = ltt_interpolate_time_from_tsc(tfcs->parent.tf, - ltt_tracefile_creation(tfcs->parent.tf)); - g_tree_insert(usertrace_tree, timestamp, tfcs); - } - } + restore_init_state(trace_state); - /* See if the trace has saved states */ - state_load_saved_states(tcs); - } -#endif + /* See if the trace has saved states */ + //state_load_saved_states(trace_state); } -static void fini(LttvTracesetState *self) +void lttv_trace_state_fini(LttvTraceState *trace_state) { -#ifdef BABEL_CLEANUP - guint i, nb_trace; - - LttvTraceState *tcs; - - //LttvTracefileState *tfcs; - + LttvTrace *trace = trace_state->trace; LttvAttributeValue v; - nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts); - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]); - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT, - LTTV_UINT, &v); + lttv_attribute_find(lttv_trace_attribute(trace), LTTV_STATE_TRACE_STATE_USE_COUNT, + LTTV_UINT, &v); - g_assert(*(v.v_uint) != 0); - (*v.v_uint)--; + g_assert(*(v.v_uint) != 0); + (*v.v_uint)--; - if(*(v.v_uint) == 0) { - free_name_tables(tcs); - free_max_time(tcs); - free_saved_state(tcs); - } - g_free(tcs->running_process); - tcs->running_process = NULL; - lttv_state_free_process_table(tcs->processes); - lttv_state_free_usertraces(tcs->usertraces); - tcs->processes = NULL; - tcs->usertraces = NULL; + if (*(v.v_uint) == 0) { + free_name_tables(trace_state); + free_max_time(trace_state); + free_saved_state(trace_state); } -#endif - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - fini((LttvTracesetContext *)self); -} - - -static LttvTracesetContext *new_traceset_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL)); -} - - -static LttvTraceContext *new_trace_context(LttvTracesetContext *self) -{ - return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL)); -} - - -static LttvTracefileContext *new_tracefile_context(LttvTracesetContext *self) -{ - return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL)); + g_free(trace_state->running_process); + trace_state->running_process = NULL; + lttv_state_free_process_table(trace_state->processes); + trace_state->processes = NULL; } +#ifdef BABEL_CLEANUP /* Write the process state of the trace */ @@ -839,13 +697,6 @@ static void write_process_state(gpointer key, gpointer value, fprintf(fp, " \n", address); } - if(process->usertrace) { - fprintf(fp, " ", - g_quark_to_string(process->usertrace->tracefile_name), - process->usertrace->cpu); - } - - fprintf(fp, " \n"); } @@ -976,21 +827,6 @@ static void write_process_state_raw(gpointer key, gpointer value, fprintf(fp, " \n", address); #endif //0 } - - if(process->usertrace) { - fputc(HDR_USERTRACE, fp); - //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name)); - //fputc('\0', fp); - fwrite(&process->usertrace->tracefile_name, - sizeof(process->usertrace->tracefile_name), 1, fp); - fwrite(&process->usertrace->cpu, sizeof(process->usertrace->cpu), 1, fp); -#if 0 - fprintf(fp, " ", - g_quark_to_string(process->usertrace->tracefile_name), - process->usertrace->cpu); -#endif //0 - } - } @@ -1148,13 +984,6 @@ static void read_process_state_raw(LttvTraceState *self, FILE *fp, process->current_function = *address; break; - case HDR_USERTRACE: - res = fread(&tmpq, sizeof(tmpq), 1, fp); - res += fread(&process->usertrace->cpu, - sizeof(process->usertrace->cpu), 1, fp); - g_assert(res == 2); - break; - default: ungetc(hdr, fp); goto end_loop; @@ -1210,7 +1039,6 @@ void lttv_state_read_raw(LttvTraceState *self, FILE *fp, GPtrArray *quarktable) case HDR_QUARK: case HDR_ES: case HDR_USER_STACK: - case HDR_USERTRACE: case HDR_PROCESS_STATE: case HDR_CPU: ungetc(hdr, fp); @@ -1304,7 +1132,6 @@ void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp, case HDR_QUARK: case HDR_ES: case HDR_USER_STACK: - case HDR_USERTRACE: case HDR_PROCESS: case HDR_CPU: g_error("Error while parsing saved state file :" @@ -1322,7 +1149,7 @@ end_loop: lttv_process_trace_seek_time(&tcs->parent, ltt_time_zero); return; } - +#endif /* BABEL_CLEANUP */ /* Copy each process from an existing hash table to a new one */ @@ -1349,6 +1176,7 @@ static void copy_process_state(gpointer key, gpointer value,gpointer user_data) } new_process->state = &g_array_index(new_process->execution_stack, LttvExecutionState, new_process->execution_stack->len - 1); +#ifdef BABEL_CLEANUP new_process->user_stack = g_array_sized_new(FALSE, FALSE, sizeof(guint64), 0); new_process->user_stack = g_array_set_size(new_process->user_stack, @@ -1358,6 +1186,7 @@ static void copy_process_state(gpointer key, gpointer value,gpointer user_data) g_array_index(process->user_stack, guint64, i); } new_process->current_function = process->current_function; +#endif /* BABEL_CLEANUP */ /* fd hash table stuff */ { @@ -1603,29 +1432,20 @@ static void lttv_state_free_blkdev_hashtable(GHashTable *ht) to the current process and a "position" member storing the tracefile position (needed to seek to the current "next" event. */ -static void state_save(LttvTraceState *self, LttvAttribute *container) +void lttv_state_save(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; + guint i, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps; guint *running_process; LttvAttributeValue value; - LttEventPosition *ep; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - value = lttv_attribute_add(container, LTTV_STATE_PROCESSES, LTTV_POINTER); *(value.v_pointer) = lttv_state_copy_process_table(self->processes); /* Add the currently running processes array */ - nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + nb_cpus = lttv_trace_get_num_cpu(self->trace); running_process = g_new(guint, nb_cpus); for(i=0;irunning_process[i]->pid; @@ -1636,8 +1456,13 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) g_info("State save"); - nb_tracefile = self->parent.tracefiles->len; + /* Save the current position */ + value = lttv_attribute_add(container, LTTV_STATE_POSITION, + LTTV_POINTER); + *(value.v_pointer) = lttv_traceset_create_position(lttv_trace_get_traceset(self->trace)); +#ifdef BABEL_CLEANUP + nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { tfcs = LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, @@ -1673,6 +1498,7 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) tfcs->parent.timestamp.tv_nsec); } } +#endif /* BABEL_CLEANUP */ /* save the cpu state */ { @@ -1715,33 +1541,13 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) *(value.v_pointer) = lttv_state_copy_blkdev_hashtable(self->bdev_states); } - -static void state_restore(LttvTraceState *self, LttvAttribute *container) +void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, pid, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; - + guint i, pid, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps; guint *running_process; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - - gboolean is_named; - - LttEventPosition *ep; - - LttvTracesetContext *tsc = self->parent.ts_context; - int retval; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, &value); g_assert(type == LTTV_POINTER); @@ -1749,7 +1555,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) self->processes = lttv_state_copy_process_table(*(value.v_pointer)); /* Add the currently running processes array */ - nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + nb_cpus = lttv_trace_get_num_cpu(self->trace); type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS, &value); g_assert(type == LTTV_POINTER); @@ -1760,7 +1566,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) g_assert(self->running_process[i] != NULL); } - nb_tracefile = self->parent.tracefiles->len; + //nb_tracefile = self->parent.tracefiles->len; //g_tree_destroy(tsc->pqueue); //tsc->pqueue = g_tree_new(compare_tracefile); @@ -1798,6 +1604,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) lttv_state_free_blkdev_hashtable(self->bdev_states); self->bdev_states = lttv_state_copy_blkdev_hashtable(*(value.v_pointer)); +#ifdef BABEL_CLEANUP for(i = 0 ; i < nb_tracefile ; i++) { tfcs = LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, @@ -1837,30 +1644,30 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) tfc->timestamp = ltt_time_infinite; } } +#endif /* BABEL_CLEANUP */ } - -static void state_saved_free(LttvTraceState *self, LttvAttribute *container) +/* + * Note: the position must be explicitely set on the entire traceset to + * match the trace states. + */ +LttvTracesetPosition *lttv_trace_state_get_position(LttvAttribute *container) { - guint i, nb_tracefile, nb_cpus, nb_irqs, nb_soft_irqs; + LttvAttributeType type; + LttvAttributeValue value; - LttvAttribute *tracefiles_tree, *tracefile_tree; + type = lttv_attribute_get_by_name(container, LTTV_STATE_POSITION, &value); + g_assert(type == LTTV_POINTER); + return *(value.v_pointer); +} +void lttv_state_saved_free(LttvTraceState *self, LttvAttribute *container) +{ + guint nb_cpus, nb_irqs, nb_soft_irqs; guint *running_process; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - - gboolean is_named; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - g_object_ref(G_OBJECT(tracefiles_tree)); - lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES); - type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, &value); g_assert(type == LTTV_POINTER); @@ -1900,6 +1707,12 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) g_assert(type == LTTV_POINTER); lttv_state_free_blkdev_hashtable(*(value.v_pointer)); + /* remove the position */ + type = lttv_attribute_get_by_name(container, LTTV_STATE_POSITION, &value); + g_assert(type == LTTV_POINTER); + lttv_traceset_destroy_position(*(value.v_pointer)); + +#ifdef BABEL_CLEANUP nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { @@ -1914,42 +1727,40 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer)); } g_object_unref(G_OBJECT(tracefiles_tree)); +#endif /* BABEL_CLEANUP */ } static void free_saved_state(LttvTraceState *self) { guint i, nb; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - gboolean is_named; - LttvAttribute *saved_states; - saved_states = lttv_attribute_find_subdir(self->parent.t_a, + saved_states = lttv_attribute_find_subdir(lttv_trace_attribute(self->trace), LTTV_STATE_SAVED_STATES); nb = lttv_attribute_get_number(saved_states); for(i = 0 ; i < nb ; i++) { type = lttv_attribute_get(saved_states, i, &name, &value, &is_named); g_assert(type == LTTV_GOBJECT); - state_saved_free(self, *((LttvAttribute **)value.v_gobject)); + lttv_state_saved_free(self, *((LttvAttribute **)value.v_gobject)); } - lttv_attribute_remove_by_name(self->parent.t_a, LTTV_STATE_SAVED_STATES); + lttv_attribute_remove_by_name(lttv_trace_attribute(self->trace), + LTTV_STATE_SAVED_STATES); } -static void create_max_time(LttvTraceState *tcs) +static void create_max_time(LttvTraceState *trace_state) { LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + lttv_attribute_find(lttv_trace_attribute(trace_state->trace), + LTTV_STATE_SAVED_STATES_TIME, LTTV_POINTER, &v); g_assert(*(v.v_pointer) == NULL); *(v.v_pointer) = g_new(LttTime,1); @@ -1957,22 +1768,24 @@ static void create_max_time(LttvTraceState *tcs) } -static void get_max_time(LttvTraceState *tcs) +static void get_max_time(LttvTraceState *trace_state) { LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + lttv_attribute_find(lttv_trace_attribute(trace_state->trace), + LTTV_STATE_SAVED_STATES_TIME, LTTV_POINTER, &v); g_assert(*(v.v_pointer) != NULL); - tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer); + trace_state->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer); } -static void free_max_time(LttvTraceState *tcs) +static void free_max_time(LttvTraceState *trace_state) { LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + lttv_attribute_find(lttv_trace_attribute(trace_state->trace), + LTTV_STATE_SAVED_STATES_TIME, LTTV_POINTER, &v); g_free(*(v.v_pointer)); *(v.v_pointer) = NULL; @@ -1988,13 +1801,14 @@ static void create_name_tables(LttvTraceState *tcs) LttvAttributeValue v; - GArray *hooks; + // GArray *hooks; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES, LTTV_POINTER, &v); g_assert(*(v.v_pointer) == NULL); *(v.v_pointer) = name_tables; +#ifdef BABEL_CLEANUP hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 1); if(!lttv_trace_find_hook(tcs->parent.t, @@ -2020,6 +1834,7 @@ static void create_name_tables(LttvTraceState *tcs) // g_string_free(string, TRUE); // } // } +#endif /* BABEL_CLEANUP */ name_tables->nb_syscalls = PREALLOC_NB_SYSCALLS; name_tables->syscall_names = g_new(GQuark, name_tables->nb_syscalls); @@ -2027,12 +1842,15 @@ static void create_name_tables(LttvTraceState *tcs) g_string_printf(fe_name, "syscall %d", i); name_tables->syscall_names[i] = g_quark_from_string(fe_name->str); } +#ifdef BABEL_CLEANUP } else { name_tables->syscall_names = NULL; name_tables->nb_syscalls = 0; } lttv_trace_hook_remove_all(&hooks); +#endif /* BABEL_CLEANUP */ +#ifdef BABEL_CLEANUP if(!lttv_trace_find_hook(tcs->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_TRAP_ENTRY, @@ -2055,18 +1873,22 @@ static void create_name_tables(LttvTraceState *tcs) // ltt_enum_string_get(t, i)); // } +#endif /* BABEL_CLEANUP */ name_tables->nb_traps = PREALLOC_NB_TRAPS; name_tables->trap_names = g_new(GQuark, name_tables->nb_traps); for(i = 0 ; i < name_tables->nb_traps; i++) { g_string_printf(fe_name, "trap %d", i); name_tables->trap_names[i] = g_quark_from_string(fe_name->str); } +#ifdef BABEL_CLEANUP } else { name_tables->trap_names = NULL; name_tables->nb_traps = 0; } lttv_trace_hook_remove_all(&hooks); +#endif /* BABEL_CLEANUP */ +#ifdef BABEL_CLEANUP if(!lttv_trace_find_hook(tcs->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_IRQ_ENTRY, @@ -2081,17 +1903,20 @@ static void create_name_tables(LttvTraceState *tcs) */ /* FIXME: LttvIRQState *irq_states should become a g_array */ +#endif /* BABEL_CLEANUP */ name_tables->nb_irqs = PREALLOC_NB_IRQS; name_tables->irq_names = g_new(GQuark, name_tables->nb_irqs); for(i = 0 ; i < name_tables->nb_irqs; i++) { g_string_printf(fe_name, "irq %d", i); name_tables->irq_names[i] = g_quark_from_string(fe_name->str); } +#ifdef BABEL_CLEANUP } else { name_tables->nb_irqs = 0; name_tables->irq_names = NULL; } lttv_trace_hook_remove_all(&hooks); +#endif /* BABEL_CLEANUP */ /* name_tables->soft_irq_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { @@ -2105,7 +1930,7 @@ static void create_name_tables(LttvTraceState *tcs) g_string_printf(fe_name, "softirq %d", i); name_tables->soft_irq_names[i] = g_quark_from_string(fe_name->str); } - g_array_free(hooks, TRUE); + // g_array_free(hooks, TRUE); g_string_free(fe_name, TRUE); @@ -2122,7 +1947,7 @@ static void get_name_tables(LttvTraceState *tcs) { LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES, LTTV_POINTER, &v); g_assert(*(v.v_pointer) != NULL); tcs->name_tables = (LttvNameTables *)*(v.v_pointer); @@ -2135,7 +1960,7 @@ static void free_name_tables(LttvTraceState *tcs) LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES, LTTV_POINTER, &v); name_tables = (LttvNameTables *)*(v.v_pointer); *(v.v_pointer) = NULL; @@ -2229,13 +2054,15 @@ static void irq_pop_mode(LttvIRQState *irqst) g_array_set_size(irqst->mode_stack, irqst->mode_stack->len - 1); } -static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, +static void push_state(LttvEvent *event, + LttvTraceState *ts, LttvExecutionMode t, guint state_id) { LttvExecutionState *es; + gint cpu; - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - guint cpu = tfs->cpu; + cpu = lttv_traceset_get_cpuid_from_event(event); + g_assert(cpu >= 0); #ifdef HASH_TABLE_DEBUG hash_table_check(ts->processes); @@ -2253,7 +2080,7 @@ static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, es = &g_array_index(process->execution_stack, LttvExecutionState, depth); es->t = t; es->n = state_id; - es->entry = es->change = tfs->parent.timestamp; + es->entry = es->change = lttv_event_get_timestamp(event); es->cum_cpu_time = ltt_time_zero; es->s = process->state->s; process->state = es; @@ -2262,7 +2089,7 @@ static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, /* pop state * return 1 when empty, else 0 */ int -lttv_state_pop_state_cleanup(LttvProcessState *process, LttvTracefileState *tfs) +lttv_state_pop_state_cleanup(LttvProcessState *process, LttvEvent *event) { guint depth = process->execution_stack->len; @@ -2274,22 +2101,27 @@ lttv_state_pop_state_cleanup(LttvProcessState *process, LttvTracefileState *tfs) g_array_set_size(process->execution_stack, depth - 1); process->state = &g_array_index(process->execution_stack, LttvExecutionState, depth - 2); - process->state->change = tfs->parent.timestamp; + process->state->change = lttv_event_get_timestamp(event); return 0; } -static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) +static void pop_state(LttvEvent *event, + LttvTraceState *ts, LttvExecutionMode t) { - guint cpu = tfs->cpu; - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; + LttvProcessState *process; + gint cpu; + + cpu = lttv_traceset_get_cpuid_from_event(event); + g_assert(cpu >= 0); + process = ts->running_process[cpu]; guint depth = process->execution_stack->len; if(process->state->t != t){ - g_info("Different execution mode type (%lu.%09lu): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + g_info("Different execution mode type: ignore it\n" + ); + g_info("process state has %s when pop_int is %s\n", g_quark_to_string(process->state->t), g_quark_to_string(t)); @@ -2303,8 +2135,10 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) } if(depth == 1){ - g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + //TODO ybrosseau readd debug + //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n", + // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + g_info("Trying to pop last state on stack: ignore it\n"); return; } @@ -2312,7 +2146,7 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) g_array_set_size(process->execution_stack, depth - 1); process->state = &g_array_index(process->execution_stack, LttvExecutionState, depth - 2); - process->state->change = tfs->parent.timestamp; + process->state->change = lttv_event_get_timestamp(event); } struct search_result { @@ -2320,53 +2154,6 @@ struct search_result { LttTime *best; /* Best result */ }; -static gint search_usertrace(gconstpointer a, gconstpointer b) -{ - const LttTime *elem_time = (const LttTime*)a; - /* Explicit non const cast */ - struct search_result *res = (struct search_result *)b; - - if(ltt_time_compare(*elem_time, *(res->time)) < 0) { - /* The usertrace was created before the schedchange */ - /* Get larger keys */ - return 1; - } else if(ltt_time_compare(*elem_time, *(res->time)) >= 0) { - /* The usertrace was created after the schedchange time */ - /* Get smaller keys */ - if(res->best) { - if(ltt_time_compare(*elem_time, *res->best) < 0) { - res->best = (LttTime *)elem_time; - } - } else { - res->best = (LttTime *)elem_time; - } - return -1; - } - return 0; -} - -static LttvTracefileState *ltt_state_usertrace_find(LttvTraceState *tcs, - guint pid, const LttTime *timestamp) -{ - LttvTracefileState *tfs = NULL; - struct search_result res; - /* Find the usertrace associated with a pid and time interval. - * Search in the usertraces by PID (within a hash) and then, for each - * corresponding element of the array, find the first one with creation - * timestamp the lowest, but higher or equal to "timestamp". */ - res.time = timestamp; - res.best = NULL; - GTree *usertrace_tree = g_hash_table_lookup(tcs->usertraces, - GUINT_TO_POINTER(pid)); - if(usertrace_tree) { - g_tree_search(usertrace_tree, search_usertrace, &res); - if(res.best) - tfs = g_tree_lookup(usertrace_tree, res.best); - } - - return tfs; -} - /* Return a new and initialized LttvProcessState structure */ LttvProcessState *lttv_state_create_process(LttvTraceState *tcs, @@ -2387,8 +2174,6 @@ LttvProcessState *lttv_state_create_process(LttvTraceState *tcs, //process->last_cpu = tfs->cpu_name; //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf); process->type = LTTV_STATE_USER_THREAD; - process->usertrace = ltt_state_usertrace_find(tcs, pid, timestamp); - process->current_function = 0; //function 0x0 by default. g_info("Process %u, core %p", process->pid, process); g_hash_table_insert(tcs->processes, process, process); @@ -2439,9 +2224,10 @@ LttvProcessState *lttv_state_create_process(LttvTraceState *tcs, es->s = LTTV_STATE_WAIT_FORK; /* Allocate an empty function call stack. If it's empty, use 0x0. */ - process->user_stack = g_array_sized_new(FALSE, FALSE, - sizeof(guint64), 0); - +#ifdef BABEL_CLEANUP + //process->user_stack = g_array_sized_new(FALSE, FALSE, + // sizeof(guint64), 0); +#endif process->fds = g_hash_table_new(g_direct_hash, g_direct_equal); return process; @@ -2488,9 +2274,9 @@ LttvProcessState *lttv_state_find_process_or_create(LttvTraceState *ts, * has the flag SA_NOCLDWAIT. It can also happen when the child is part * of a killed thread group, but isn't the leader. */ -static int exit_process(LttvTracefileState *tfs, LttvProcessState *process) +static int exit_process(LttvEvent *event, LttvProcessState *process) { - LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context); + LttvTraceState *ts = event->state; LttvProcessState key; /* Wait for both schedule with exit dead and process free to happen. @@ -2502,7 +2288,6 @@ static int exit_process(LttvTracefileState *tfs, LttvProcessState *process) key.cpu = process->cpu; g_hash_table_remove(ts->processes, &key); g_array_free(process->execution_stack, TRUE); - g_array_free(process->user_stack, TRUE); /* the following also clears the content */ g_hash_table_destroy(process->fds); @@ -2515,7 +2300,6 @@ static int exit_process(LttvTracefileState *tfs, LttvProcessState *process) static void free_process_state(gpointer key, gpointer value,gpointer user_data) { g_array_free(((LttvProcessState *)value)->execution_stack, TRUE); - g_array_free(((LttvProcessState *)value)->user_stack, TRUE); /* the following also clears the content */ g_hash_table_destroy(((LttvProcessState *)value)->fds); @@ -2533,40 +2317,56 @@ static void lttv_state_free_process_table(GHashTable *processes) static gboolean syscall_entry(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + LttvProcessState *process; LttvExecutionSubmode submode; - LttvNameTables *nt = ((LttvTraceState *)(s->parent.t_context))->name_tables; + char syscall_name[200]; + + event = (LttvEvent *) call_data; + if (strncmp(lttv_traceset_get_name_from_event(event), + "sys_", sizeof("sys_") - 1) != 0) + return FALSE; - guint syscall = ltt_event_get_unsigned(e, f); - expand_syscall_table(ts, syscall); - submode = nt->syscall_names[syscall]; + strncpy(syscall_name,lttv_traceset_get_name_from_event(event)+4,200); + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + + submode = g_quark_from_string(syscall_name); /* There can be no system call from PID 0 : unknown state */ if(process->pid != 0) - push_state(s, LTTV_STATE_SYSCALL, submode); + push_state(event, ts, LTTV_STATE_SYSCALL, submode); return FALSE; } static gboolean syscall_exit(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + LttvProcessState *process; + + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "exit_syscall") != 0) + return FALSE; + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; /* There can be no system call from PID 0 : unknown state */ - if(process->pid != 0) - pop_state(s, LTTV_STATE_SYSCALL); + if (process->pid != 0) + pop_state(event, ts, LTTV_STATE_SYSCALL); return FALSE; } - +#ifdef BABEL_CLEANUP static gboolean trap_entry(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -2617,32 +2417,41 @@ static gboolean trap_exit(void *hook_data, void *call_data) } return FALSE; } +#endif /* BABEL_CLEANUP */ static gboolean irq_entry(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); - LttvNameTables *nt = ((LttvTraceState *)(s->parent.t_context))->name_tables; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; LttvExecutionSubmode submode; - guint64 irq = ltt_event_get_long_unsigned(e, f); + LttvNameTables *nt; + guint64 irq; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "irq_handler_entry") != 0) + return FALSE; + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + + nt = ts->name_tables; + irq = lttv_event_get_long_unsigned(event, "irq"); expand_irq_table(ts, irq); submode = nt->irq_names[irq]; /* Do something with the info about being in user or system mode when int? */ - push_state(s, LTTV_STATE_IRQ, submode); + push_state(event, ts, LTTV_STATE_IRQ, submode); /* update cpu status */ - cpu_push_mode(s->cpu_state, LTTV_CPU_IRQ); + cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_IRQ); /* update irq status */ - g_array_append_val(s->cpu_state->irq_stack, irq); + g_array_append_val(ts->cpu_states[cpu].irq_stack, irq); irq_push_mode(&ts->irq_states[irq], LTTV_IRQ_BUSY); return FALSE; @@ -2650,38 +2459,62 @@ static gboolean irq_entry(void *hook_data, void *call_data) static gboolean soft_irq_exit(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; - pop_state(s, LTTV_STATE_SOFT_IRQ); + LttvCPUState *cpu_state; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "softirq_exit") != 0) + return FALSE; + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + + cpu_state = &(ts->cpu_states[cpu]); + pop_state(event, ts, LTTV_STATE_SOFT_IRQ); /* update cpu status */ - cpu_pop_mode(s->cpu_state); + cpu_pop_mode(cpu_state); /* update softirq status */ - if (s->cpu_state->softirq_stack->len > 0) { - gint last = g_array_index(s->cpu_state->softirq_stack, gint, s->cpu_state->softirq_stack->len-1); + if (cpu_state->softirq_stack->len > 0) { + gint last = g_array_index(cpu_state->softirq_stack, gint, cpu_state->softirq_stack->len-1); if(ts->soft_irq_states[last].running) ts->soft_irq_states[last].running--; - g_array_remove_index(s->cpu_state->softirq_stack, s->cpu_state->softirq_stack->len-1); + g_array_remove_index(cpu_state->softirq_stack, cpu_state->softirq_stack->len-1); } return FALSE; } static gboolean irq_exit(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + + LttvCPUState *cpu_state; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "irq_handler_exit") != 0) + return FALSE; - pop_state(s, LTTV_STATE_IRQ); + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + cpu_state = &(ts->cpu_states[cpu]); + + pop_state(event, ts, LTTV_STATE_IRQ); /* update cpu status */ - cpu_pop_mode(s->cpu_state); + cpu_pop_mode(cpu_state); /* update irq status */ - if (s->cpu_state->irq_stack->len > 0) { - gint last = g_array_index(s->cpu_state->irq_stack, gint, s->cpu_state->irq_stack->len-1); - g_array_remove_index(s->cpu_state->irq_stack, s->cpu_state->irq_stack->len-1); + if (cpu_state->irq_stack->len > 0) { + gint last = g_array_index(cpu_state->irq_stack, gint, cpu_state->irq_stack->len-1); + g_array_remove_index(cpu_state->irq_stack, cpu_state->irq_stack->len-1); irq_pop_mode(&ts->irq_states[last]); } @@ -2690,14 +2523,20 @@ static gboolean irq_exit(void *hook_data, void *call_data) static gboolean soft_irq_raise(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); + LttvEvent *event; + //guint cpu; + LttvTraceState *ts; + + + guint64 softirq; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "softirq_raise") != 0) + return FALSE; - guint64 softirq = ltt_event_get_long_unsigned(e, f); + //cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + softirq = lttv_event_get_long_unsigned(event, "vec"); expand_soft_irq_table(ts, softirq); @@ -2710,27 +2549,38 @@ static gboolean soft_irq_raise(void *hook_data, void *call_data) static gboolean soft_irq_entry(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); + LttvEvent *event; + guint cpu; + LttvTraceState *ts; LttvExecutionSubmode submode; - guint64 softirq = ltt_event_get_long_unsigned(e, f); + LttvNameTables *nt; + guint64 softirq; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "softirq_exit") != 0) + return FALSE; + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + + + + + softirq = lttv_event_get_long_unsigned(event, "vec"); expand_soft_irq_table(ts, softirq); - LttvNameTables *nt = ((LttvTraceState *)(s->parent.t_context))->name_tables; + nt = ts->name_tables; submode = nt->soft_irq_names[softirq]; /* Do something with the info about being in user or system mode when int? */ - push_state(s, LTTV_STATE_SOFT_IRQ, submode); + push_state(event, ts, LTTV_STATE_SOFT_IRQ, submode); /* update cpu status */ - cpu_push_mode(s->cpu_state, LTTV_CPU_SOFT_IRQ); + cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_SOFT_IRQ); /* update softirq status */ - g_array_append_val(s->cpu_state->softirq_stack, softirq); - if(ts->soft_irq_states[softirq].pending) + g_array_append_val(ts->cpu_states[cpu].softirq_stack, softirq); + if (ts->soft_irq_states[softirq].pending) ts->soft_irq_states[softirq].pending--; ts->soft_irq_states[softirq].running++; @@ -2739,43 +2589,58 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data) static gboolean enum_interrupt(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttvNameTables *nt = ts->name_tables; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; - GQuark action = g_quark_from_string(ltt_event_get_string(e, - lttv_trace_get_hook_field(th, 0))); - guint irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1)); + LttvNameTables *nt; + + + GQuark action; + guint irq; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "lttng_statedump_interrupt") != 0) + return FALSE; + ts = event->state; + nt = ts->name_tables; + irq = lttv_event_get_long_unsigned(event, "irq"); + action = g_quark_from_string(lttv_event_get_string(event, + "action")); expand_irq_table(ts, irq); nt->irq_names[irq] = action; return FALSE; } - +#ifdef BABEL_CLEANUP static gboolean bdev_request_issue(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; - guint major = ltt_event_get_long_unsigned(e, - lttv_trace_get_hook_field(th, 0)); - guint minor = ltt_event_get_long_unsigned(e, - lttv_trace_get_hook_field(th, 1)); - guint oper = ltt_event_get_long_unsigned(e, - lttv_trace_get_hook_field(th, 2)); - guint32 devcode = MKDEV(major,minor); + guint major; + guint minor; + guint oper; + guint32 devcode; + gpointer bdev; - /* have we seen this block device before? */ - gpointer bdev = get_hashed_bdevstate(ts, devcode); + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "block_rq_issue") != 0) + return FALSE; + ts = event->state; + major = lttv_event_get_long_unsigned(event,); + + minor = lttv_event_get_long_unsigned(event,); + + oper = lttv_event_get_long_unsigned(event,); + + devcode = MKDEV(major,minor); + + /* have we seen this block device before? */ + bdev = get_hashed_bdevstate(ts, devcode); if(oper == 0) bdev_push_mode(bdev, LTTV_BDEV_BUSY_READING); else @@ -2807,85 +2672,9 @@ static gboolean bdev_request_complete(void *hook_data, void *call_data) return FALSE; } - -static void push_function(LttvTracefileState *tfs, guint64 funcptr) -{ - guint64 *new_func; - - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - guint cpu = tfs->cpu; - LttvProcessState *process = ts->running_process[cpu]; - - guint depth = process->user_stack->len; - - process->user_stack = - g_array_set_size(process->user_stack, depth + 1); - - new_func = &g_array_index(process->user_stack, guint64, depth); - *new_func = funcptr; - process->current_function = funcptr; -} - -static void pop_function(LttvTracefileState *tfs, guint64 funcptr) -{ - guint cpu = tfs->cpu; - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; - - if(process->current_function != funcptr){ - g_info("Different functions (%lu.%09lu): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); - g_info("process state has %" PRIu64 " when pop_function is %" PRIu64 "\n", - process->current_function, funcptr); - g_info("{ %u, %u, %s, %s, %s }\n", - process->pid, - process->ppid, - g_quark_to_string(process->name), - g_quark_to_string(process->brand), - g_quark_to_string(process->state->s)); - return; - } - guint depth = process->user_stack->len; - - if(depth == 0){ - g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); - return; - } - - process->user_stack = - g_array_set_size(process->user_stack, depth - 1); - process->current_function = - g_array_index(process->user_stack, guint64, depth - 2); -} - - -static gboolean function_entry(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); - guint64 funcptr = ltt_event_get_long_unsigned(e, f); - - push_function(s, funcptr); - return FALSE; -} - -static gboolean function_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); - guint64 funcptr = ltt_event_get_long_unsigned(e, f); - - pop_function(s, funcptr); - return FALSE; -} - +#endif +#ifdef BABEL_CLEANUP +// We dont have the syscall table in LTTng 2.0 static gboolean dump_syscall(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -2921,9 +2710,11 @@ static gboolean dump_kprobe(void *hook_data, void *call_data) return FALSE; } - +#endif +#ifdef BABEL_CLEANUP static gboolean dump_softirq(void *hook_data, void *call_data) { + LttvTracefileState *s = (LttvTracefileState *)call_data; LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; LttvNameTables *nt = ts->name_tables; @@ -2939,29 +2730,38 @@ static gboolean dump_softirq(void *hook_data, void *call_data) nt->soft_irq_names[id] = g_quark_from_string(symbol); return FALSE; -} +} +#endif static gboolean sched_try_wakeup(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; LttvProcessState *process; gint woken_pid; guint woken_cpu; + LttTime timestamp; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_wakeup") != 0) + return FALSE; - woken_pid = ltt_event_get_int(e, lttv_trace_get_hook_field(th, 0)); - woken_cpu = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); + ts = event->state; + woken_pid = lttv_event_get_long(event, "tid"); + woken_cpu = lttv_event_get_long_unsigned(event, "target_cpu"); + + timestamp = lttv_event_get_timestamp(event); process = lttv_state_find_process_or_create( - (LttvTraceState*)s->parent.t_context, - woken_cpu, woken_pid, - &s->parent.timestamp); + ts, + woken_cpu, woken_pid, + ×tamp); if (process->state->s == LTTV_STATE_WAIT || process->state->s == LTTV_STATE_WAIT_FORK) { process->state->s = LTTV_STATE_WAIT_CPU; - process->state->change = s->parent.timestamp; + process->state->change = timestamp; } g_debug("Wakeup: process %d on CPU %u\n", woken_pid, woken_cpu); @@ -2971,21 +2771,31 @@ static gboolean sched_try_wakeup(void *hook_data, void *call_data) static gboolean schedchange(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + LttvProcessState *process; + + //LttvProcessState *old_process = ts->running_process[cpu]; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; guint pid_in, pid_out; gint64 state_out; + LttTime timestamp; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_switch") != 0) + return FALSE; - pid_out = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - pid_in = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); - state_out = ltt_event_get_long_int(e, lttv_trace_get_hook_field(th, 2)); + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + pid_out = lttv_event_get_long_unsigned(event, "prev_tid"); + pid_in = lttv_event_get_long_unsigned(event, "next_tid"); + state_out = lttv_event_get_long(event, "prev_state"); + timestamp = lttv_event_get_timestamp(event); + if(likely(process != NULL)) { /* We could not know but it was not the idle process executing. @@ -3011,52 +2821,50 @@ static gboolean schedchange(void *hook_data, void *call_data) g_assert(process->execution_stack->len == 1); process->state->t = LTTV_STATE_SYSCALL; process->state->s = LTTV_STATE_WAIT; - process->state->change = s->parent.timestamp; - process->state->entry = s->parent.timestamp; + process->state->change = timestamp; + process->state->entry = timestamp; } } else { if(unlikely(process->state->s == LTTV_STATE_EXIT)) { process->state->s = LTTV_STATE_ZOMBIE; - process->state->change = s->parent.timestamp; + process->state->change = timestamp; } else { if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU; else process->state->s = LTTV_STATE_WAIT; - process->state->change = s->parent.timestamp; + process->state->change = timestamp; } if(state_out == 32 || state_out == 64) { /* EXIT_DEAD || TASK_DEAD */ /* see sched.h for states */ - if (!exit_process(s, process)) { + if (!exit_process(event, process)) { process->state->s = LTTV_STATE_DEAD; - process->state->change = s->parent.timestamp; + process->state->change = timestamp; } } } } process = ts->running_process[cpu] = lttv_state_find_process_or_create( - (LttvTraceState*)s->parent.t_context, + ts, cpu, pid_in, - &s->parent.timestamp); + ×tamp); process->state->s = LTTV_STATE_RUN; process->cpu = cpu; - if(process->usertrace) - process->usertrace->cpu = cpu; // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf); - process->state->change = s->parent.timestamp; + process->state->change = timestamp; /* update cpu status */ if(pid_in == 0) /* going to idle task */ - cpu_set_base_mode(s->cpu_state, LTTV_CPU_IDLE); + cpu_set_base_mode(&(ts->cpu_states[cpu]), LTTV_CPU_IDLE); else { /* scheduling a real task. * we must be careful here: * if we just schedule()'ed to a process that is * in a trap, we must put the cpu in trap mode */ - cpu_set_base_mode(s->cpu_state, LTTV_CPU_BUSY); + cpu_set_base_mode(&(ts->cpu_states[cpu]), LTTV_CPU_BUSY); if(process->state->t == LTTV_STATE_TRAP) - cpu_push_mode(s->cpu_state, LTTV_CPU_TRAP); + cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_TRAP); } return FALSE; @@ -3064,30 +2872,34 @@ static gboolean schedchange(void *hook_data, void *call_data) static gboolean process_fork(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; + LttvProcessState *process; + LttvProcessState *child_process; guint child_pid; /* In the Linux Kernel, there is one PID per thread. */ guint child_tgid; /* tgid in the Linux kernel is the "real" POSIX PID. */ //LttvProcessState *zombie_process; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; - LttvProcessState *child_process; - struct marker_field *f; + guint cpu; + LttTime timestamp; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_process_fork") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + timestamp = lttv_event_get_timestamp(event); + /* Skip Parent PID param */ /* Child PID */ - child_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); - s->parent.target_pid = child_pid; + child_pid = lttv_event_get_long_unsigned(event, "child_tid"); + //ts->target_pid = child_pid; /* Child TGID */ - f = lttv_trace_get_hook_field(th, 2); - if (likely(f)) - child_tgid = ltt_event_get_unsigned(e, f); - else - child_tgid = 0; + + child_tgid = 0; /* Mathieu : it seems like the process might have been scheduled in before the * fork, and, in a rare case, might be the current process. This might happen @@ -3117,7 +2929,7 @@ static gboolean process_fork(void *hook_data, void *call_data) if(child_process == NULL) { child_process = lttv_state_create_process(ts, process, cpu, child_pid, child_tgid, - LTTV_STATE_UNNAMED, &s->parent.timestamp); + LTTV_STATE_UNNAMED, ×tamp); } else { /* The process has already been created : due to time imprecision between * multiple CPUs : it has been scheduled in before creation. Note that we @@ -3134,7 +2946,7 @@ static gboolean process_fork(void *hook_data, void *call_data) child_process->creation_time.tv_nsec, child_process->insertion_time.tv_sec, child_process->insertion_time.tv_nsec, - cpu, ltt_event_time(e).tv_sec, ltt_event_time(e).tv_nsec); + cpu, timestamp.tv_sec, timestamp.tv_nsec); //g_assert(0); /* This is a problematic case : the process has been created // before the fork event */ child_process->ppid = process->pid; @@ -3147,6 +2959,8 @@ static gboolean process_fork(void *hook_data, void *call_data) return FALSE; } +#ifdef BABEL_CLEANUP +//NO KTHREAD_CREATE in LTTng 2.0 /* We stamp a newly created process as kernel_thread. * The thread should not be running yet. */ static gboolean process_kernel_thread(void *hook_data, void *call_data) @@ -3161,7 +2975,7 @@ static gboolean process_kernel_thread(void *hook_data, void *call_data) /* PID */ pid = (guint)ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0)); - s->parent.target_pid = pid; + //s->parent.target_pid = pid; process = lttv_state_find_process_or_create(ts, ANY_CPU, pid, <t_time_zero); @@ -3176,18 +2990,25 @@ static gboolean process_kernel_thread(void *hook_data, void *call_data) return FALSE; } - +#endif static gboolean process_exit(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; guint pid; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; + guint cpu; LttvProcessState *process; // = ts->running_process[cpu]; - pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - s->parent.target_pid = pid; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_process_exit") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + + pid = lttv_event_get_long_unsigned(event, "tid"); + //s->parent.target_pid = pid; // FIXME : Add this test in the "known state" section // g_assert(process->pid == pid); @@ -3201,24 +3022,32 @@ static gboolean process_exit(void *hook_data, void *call_data) static gboolean process_free(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; + guint cpu; guint release_pid; LttvProcessState *process; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_process_free") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + /* PID of the process to release */ - release_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - s->parent.target_pid = release_pid; + release_pid = lttv_event_get_long_unsigned(event, "_tid"); + //s->parent.target_pid = release_pid; g_assert(release_pid != 0); process = lttv_state_find_process(ts, ANY_CPU, release_pid); if(likely(process != NULL)) - exit_process(s, process); + exit_process(event, process); return FALSE; //DISABLED +#if 0 if(likely(process != NULL)) { /* release_task is happening at kernel level : we can now safely release * the data structure of the process */ @@ -3246,18 +3075,25 @@ static gboolean process_free(void *hook_data, void *call_data) } return FALSE; +#endif //DISABLED } static gboolean process_exec(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; +{ + LttvEvent *event; + LttvTraceState *ts; + guint cpu; //gchar *name; - guint cpu = s->cpu; - LttvProcessState *process = ts->running_process[cpu]; + LttvProcessState *process; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sys_execve") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; #if 0//how to use a sequence that must be transformed in a string /* PID of the process to release */ @@ -3274,13 +3110,13 @@ static gboolean process_exec(void *hook_data, void *call_data) process->name = g_quark_from_string(null_term_name); #endif //0 - process->name = g_quark_from_string(ltt_event_get_string(e, - lttv_trace_get_hook_field(th, 0))); + process->name = g_quark_from_string(lttv_event_get_string(event, + "filename")); process->brand = LTTV_STATE_UNBRANDED; //g_free(null_term_name); return FALSE; } - +#ifdef BABEL_CLEANUP static gboolean thread_brand(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -3296,7 +3132,10 @@ static gboolean thread_brand(void *hook_data, void *call_data) return FALSE; } - +#endif +#if 0 + // TODO We only have sys_open, without the FD + // manage to do somehting better static gboolean fs_open(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -3320,7 +3159,7 @@ static gboolean fs_open(void *hook_data, void *call_data) return FALSE; } - +#endif static void print_stack(LttvProcessState *process) { LttvExecutionState *es; @@ -3402,53 +3241,67 @@ static void fix_process(gpointer key, gpointer value, gpointer user_data) static gboolean statedump_end(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; + LttvEvent *event; + LttvTraceState *ts; + LttTime timestamp; //LttEvent *e = ltt_tracefile_get_event(s->parent.tf); //LttvTraceHook *th = (LttvTraceHook *)hook_data; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "lttng_statedump_end") != 0) + return FALSE; + + ts = event->state; + timestamp = lttv_event_get_timestamp(event); /* For all processes */ /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */ /* else, if stack[0] is unknown, set to user mode, running */ - g_hash_table_foreach(ts->processes, fix_process, &tfc->timestamp); + g_hash_table_foreach(ts->processes, fix_process, ×tamp); return FALSE; } static gboolean enum_process_state(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //It's slow : optimise later by doing this before reading trace. - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; + LttTime timestamp; guint parent_pid; guint pid; guint tgid; gchar * command; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; + guint cpu; LttvProcessState *parent_process; - struct marker_field *f; - GQuark type; + LttvProcessState *process; + + guint type; LttvExecutionState *es; guint i, nb_cpus; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "lttng_statedump_process_state") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + timestamp = lttv_event_get_timestamp(event); + /* PID */ - pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - s->parent.target_pid = pid; + pid = lttv_event_get_long_unsigned(event, "tid"); + //s->parent.target_pid = pid; /* Parent PID */ - parent_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); + parent_pid = lttv_event_get_long_unsigned(event, "ppid"); /* Command name */ - command = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2)); + command = lttv_event_get_string(event, "name"); /* type */ - f = lttv_trace_get_hook_field(th, 3); - type = ltt_enum_string_get(f, ltt_event_get_unsigned(e, f)); + + type = lttv_event_get_long_unsigned(event, "type"); //FIXME: type is rarely used, enum must match possible types. @@ -3459,14 +3312,10 @@ static gboolean enum_process_state(void *hook_data, void *call_data) /* Skip status 6th param */ /* TGID */ - f = lttv_trace_get_hook_field(th, 7); - if(f) - tgid = ltt_event_get_unsigned(e, f); - else - tgid = 0; - + tgid = lttv_event_get_long_unsigned(event, "pid"); + if(pid == 0) { - nb_cpus = ltt_trace_get_num_cpu(ts->parent.t); + nb_cpus = lttv_trace_get_num_cpu(ts->trace); for(i=0; iparent.timestamp); + ×tamp); /* Keep the stack bottom : a running user mode */ /* Disabled because of inconsistencies in the current statedump states. */ - if(type == LTTV_STATE_KERNEL_THREAD) { + //if(type == LTTV_STATE_KERNEL_THREAD) { + if(type == 1) { /* Only keep the bottom * FIXME Kernel thread : can be in syscall or interrupt or trap. */ /* Will cause expected trap when in fact being syscall (even after end of @@ -3566,34 +3416,56 @@ static gboolean enum_process_state(void *hook_data, void *call_data) return FALSE; } + + gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data) { - LttvTracesetState *tss = (LttvTracesetState*)(call_data); + LttvTraceset *traceset = (LttvTraceset *)(call_data); - lttv_state_add_event_hooks(tss); + lttv_state_add_event_hooks(traceset); return 0; } -void lttv_state_add_event_hooks(LttvTracesetState *self) +void lttv_state_add_event_hooks(LttvTraceset *traceset) { - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_tracefile; - + gboolean result; + + LttvAttributeValue value; + LttvHooks*event_hook; + LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); + result = lttv_iattribute_find_by_path(attributes, "hooks/event", + LTTV_POINTER, &value); + g_assert(result); + event_hook = *(value.v_pointer); + g_assert(event_hook); + + lttv_hooks_add(event_hook,syscall_entry , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,syscall_exit , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,irq_entry , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,irq_exit , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,soft_irq_raise , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,soft_irq_entry , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,soft_irq_exit , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,schedchange , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,sched_try_wakeup , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,process_exit , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,process_free , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,process_exec , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,enum_process_state , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,statedump_end , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,enum_interrupt , NULL, LTTV_PRIO_STATE); + +#ifdef BABEL_CLEANUP //For the whole function this time + guint i, j, k, nb_trace; LttvTraceState *ts; - - LttvTracefileState *tfs; - GArray *hooks; - - LttvTraceHook *th; - + // LttvTraceHook *th; LttvAttributeValue val; nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = (LttvTraceState *)self->parent.traces[i]; + for (i = 0 ; i < nb_trace ; i++) { + ts = lttv_traceset_get(traceset, i)-; /* Find the eventtype id for the following events and register the associated by id hooks. */ @@ -3602,7 +3474,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks. //hn = 0; - lttv_trace_find_hook(ts->parent.t, + lttv_trace_find_hook(tss->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_SYSCALL_ENTRY, FIELD_ARRAY(LTT_FIELD_SYSCALL_ID), @@ -3614,6 +3486,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) NULL, syscall_exit, NULL, &hooks); +#ifdef BABEL_CLEANUP lttv_trace_find_hook(ts->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_TRAP_ENTRY, @@ -3625,6 +3498,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) LTT_EVENT_TRAP_EXIT, NULL, trap_exit, NULL, &hooks); +#endif /* BABEL_CLEANUP */ lttv_trace_find_hook(ts->parent.t, LTT_CHANNEL_KERNEL, @@ -3638,6 +3512,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) NULL, trap_exit, NULL, &hooks); +#ifdef BABEL_CLEANUP lttv_trace_find_hook(ts->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY, @@ -3649,6 +3524,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) LTT_EVENT_PAGE_FAULT_NOSEM_EXIT, NULL, trap_exit, NULL, &hooks); +#endif /* BABEL_CLEANUP */ lttv_trace_find_hook(ts->parent.t, LTT_CHANNEL_KERNEL, @@ -3821,17 +3697,20 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); *(val.v_pointer) = hooks; } +#endif } gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data) { + //TODO ybrosseau 2012-05-11 Reactivate the remove +#if 0 LttvTracesetState *tss = (LttvTracesetState*)(call_data); lttv_state_remove_event_hooks(tss); - +#endif return 0; } - +#if 0 void lttv_state_remove_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; @@ -3877,7 +3756,8 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) g_array_free(hooks, TRUE); } } - +#endif +#ifdef BABEL_CLEANUP static gboolean state_save_event_hook(void *hook_data, void *call_data) { guint *event_count = (guint*)hook_data; @@ -3927,7 +3807,7 @@ guint lttv_state_current_cpu(LttvTracefileState *tfs) return tfs->cpu; } - +#endif //BABEL_CLEANUP #if 0 static gboolean block_start(void *hook_data, void *call_data) @@ -4045,7 +3925,7 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self) } } #endif //0 - +#ifdef BABEL_CLEANUP void lttv_state_save_add_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; @@ -4093,7 +3973,7 @@ gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data) return 0; } - +#endif #if 0 void lttv_state_save_remove_event_hooks(LttvTracesetState *self) @@ -4132,7 +4012,7 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) } } #endif //0 - +#ifdef BABEL_CLEANUP void lttv_state_save_remove_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; @@ -4263,8 +4143,8 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) } if(!call_rest) g_info("NOT Calling restore"); } - - +#endif +#ifdef BABEL_CLEANUP static void traceset_state_instance_init (GTypeInstance *instance, gpointer g_class) { } @@ -4313,7 +4193,8 @@ GType lttv_traceset_state_get_type(void) return type; } - +#endif +#if BABEL_CLEANUP static void trace_state_instance_init (GTypeInstance *instance, gpointer g_class) { } @@ -4405,8 +4286,8 @@ GType lttv_tracefile_state_get_type(void) return type; } - -static void module_init() +#endif +static void module_init(void) { LTTV_STATE_UNNAMED = g_quark_from_string(""); LTTV_STATE_UNBRANDED = g_quark_from_string(""); @@ -4434,7 +4315,7 @@ static void module_init() LTTV_STATE_PROCESSES = g_quark_from_string("processes"); LTTV_STATE_PROCESS = g_quark_from_string("process"); LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process"); - LTTV_STATE_EVENT = g_quark_from_string("event"); + LTTV_STATE_POSITION = g_quark_from_string("position"); LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states"); LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time"); LTTV_STATE_TIME = g_quark_from_string("time"); @@ -4468,8 +4349,8 @@ static void module_init() LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry"); LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit"); - LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry"); - LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit"); + //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry"); + //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit"); LTT_EVENT_PAGE_FAULT_ENTRY = g_quark_from_string("page_fault_entry"); LTT_EVENT_PAGE_FAULT_EXIT = g_quark_from_string("page_fault_exit"); LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY = g_quark_from_string("page_fault_nosem_entry"); diff --git a/lttv/lttv/state.h b/lttv/lttv/state.h index ef22627f..cd91354c 100644 --- a/lttv/lttv/state.h +++ b/lttv/lttv/state.h @@ -20,9 +20,9 @@ #define STATE_H #include -#include #include - +#include +#include /* The operating system state, kept during the trace analysis, contains a subset of the real operating system state, sufficient for the analysis, and possibly organized quite differently. @@ -48,6 +48,14 @@ contains an execution mode stack (e.g. irq within system call, called from user mode). */ +typedef struct _LttvTraceset LttvTraceset; + +typedef struct _LttvTrace LttvTrace; + +typedef struct _LttvTracesetPosition LttvTracesetPosition; + +struct bt_context; + /* Priority of state hooks */ #define LTTV_PRIO_STATE 25 @@ -109,8 +117,8 @@ extern GQuark LTT_EVENT_EXEC, LTT_EVENT_PROCESS_STATE, LTT_EVENT_STATEDUMP_END, - LTT_EVENT_FUNCTION_ENTRY, - LTT_EVENT_FUNCTION_EXIT, + //LTT_EVENT_FUNCTION_ENTRY, + //LTT_EVENT_FUNCTION_EXIT, LTT_EVENT_THREAD_BRAND, LTT_EVENT_REQUEST_ISSUE, LTT_EVENT_REQUEST_COMPLETE, @@ -157,30 +165,17 @@ extern GQuark LTT_FIELD_STATE, LTT_FIELD_CPU_ID; -typedef struct _LttvTracesetState LttvTracesetState; -typedef struct _LttvTracesetStateClass LttvTracesetStateClass; - typedef struct _LttvTraceState LttvTraceState; typedef struct _LttvTraceStateClass LttvTraceStateClass; typedef struct _LttvTracefileState LttvTracefileState; typedef struct _LttvTracefileStateClass LttvTracefileStateClass; -gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data); -void lttv_state_add_event_hooks(LttvTracesetState *self); - -gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data); -void lttv_state_remove_event_hooks(LttvTracesetState *self); +void lttv_traceset_add_state_event_hooks(LttvTraceset *traceset); -void lttv_state_save_add_event_hooks(LttvTracesetState *self); -// Hook wrapper. call_data is a trace context. -gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data); +void lttv_traceset_remove_state_event_hooks(LttvTraceset *traceset); -void lttv_state_save_remove_event_hooks(LttvTracesetState *self); -// Hook wrapper. call_data is a trace context. -gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data); - -void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t); +void lttv_traceset_seek_time_closest_prior_state(LttvTraceset *traceset, LttTime t); /* The LttvProcessState structure defines the current state for each process. A process can make system calls (in some rare cases nested) and receive @@ -298,12 +293,8 @@ typedef struct _LttvProcessState { guint cpu; /* CPU where process is scheduled (being either in the active or inactive runqueue)*/ // guint last_tracefile_index; /* index in the trace for cpu tracefile */ - LttvTracefileState *usertrace; /* Associated usertrace */ /* opened file descriptors, address map?... */ - GArray *user_stack; /* User space function call stack */ - guint64 current_function; LttvProcessType type; /* kernel thread or user space ? */ - guint target_pid; /* target PID of the current event. */ guint free_events; /* 0 : none, 1 : free or exit dead, 2 : should delete */ GHashTable *fds; /* hash table of int (file descriptor) -> GQuark (file name) */ } LttvProcessState; @@ -321,36 +312,8 @@ LttvProcessState *lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent, guint cpu, guint pid, guint tgid, GQuark name, const LttTime *timestamp); -void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp); -void lttv_state_write_raw(LttvTraceState *self, LttTime t, FILE *fp); - -/* The LttvTracesetState, LttvTraceState and LttvTracefileState types - inherit from the corresponding Context objects defined in processTrace. */ - -#define LTTV_TRACESET_STATE_TYPE (lttv_traceset_state_get_type ()) -#define LTTV_TRACESET_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACESET_STATE_TYPE, LttvTracesetState)) -#define LTTV_TRACESET_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACESET_STATE_TYPE, LttvTracesetStateClass)) -#define LTTV_IS_TRACESET_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACESET_STATE_TYPE)) -#define LTTV_IS_TRACESET_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACESET_STATE_TYPE)) -#define LTTV_TRACESET_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACESET_STATE_TYPE, LttvTracesetStateClass)) - -struct _LttvTracesetState { - LttvTracesetContext parent; -}; - -struct _LttvTracesetStateClass { - LttvTracesetContextClass parent; -}; - -GType lttv_traceset_state_get_type (void); - - -#define LTTV_TRACE_STATE_TYPE (lttv_trace_state_get_type ()) -#define LTTV_TRACE_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACE_STATE_TYPE, LttvTraceState)) -#define LTTV_TRACE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACE_STATE_TYPE, LttvTraceStateClass)) -#define LTTV_IS_TRACE_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACE_STATE_TYPE)) -#define LTTV_IS_TRACE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACE_STATE_TYPE)) -#define LTTV_TRACE_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACE_STATE_TYPE, LttvTraceStateClass)) +//void lttv_state_write(LttvTraceState *trace_state, LttTime t, FILE *fp); +//void lttv_state_write_raw(LttvTraceState *trace_state, LttTime t, FILE *fp); typedef struct _LttvCPUState { GArray *mode_stack; @@ -389,12 +352,9 @@ typedef struct _LttvNameTables { } LttvNameTables; struct _LttvTraceState { - LttvTraceContext parent; - + LttvTrace *trace; /* LttvTrace this state belongs to */ GHashTable *processes; /* LttvProcessState objects indexed by pid and last_cpu */ - GHashTable *usertraces; /* GPtrArray objects indexed by pid, containing - pointers to LttvTracefileState objects. */ guint nb_event, save_interval; /* Block/char devices, locks, memory pages... */ GQuark *eventtype_names; @@ -415,62 +375,22 @@ struct _LttvTraceState { GHashTable *bdev_states; /* state of the block devices */ }; -struct _LttvTraceStateClass { - LttvTraceContextClass parent; - - void (*state_save) (LttvTraceState *self, LttvAttribute *container); - void (*state_restore) (LttvTraceState *self, LttvAttribute *container); - void (*state_saved_free) (LttvTraceState *self, LttvAttribute *container); -}; - -GType lttv_trace_state_get_type (void); +void lttv_trace_state_init(LttvTraceState *self, LttvTrace *trace); +void lttv_trace_state_fini(LttvTraceState *self); void lttv_state_save(LttvTraceState *self, LttvAttribute *container); - void lttv_state_restore(LttvTraceState *self, LttvAttribute *container); +LttvTracesetPosition *lttv_trace_state_get_position(LttvAttribute *container); +void lttv_state_saved_free(LttvTraceState *self, LttvAttribute *container); -void lttv_state_state_saved_free(LttvTraceState *self, - LttvAttribute *container); - -int lttv_state_pop_state_cleanup(LttvProcessState *process, - LttvTracefileState *tfs); - -#define LTTV_TRACEFILE_STATE_TYPE (lttv_tracefile_state_get_type ()) -#define LTTV_TRACEFILE_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileState)) -#define LTTV_TRACEFILE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileStateClass)) -#define LTTV_IS_TRACEFILE_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACEFILE_STATE_TYPE)) -#define LTTV_IS_TRACEFILE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACEFILE_STATE_TYPE)) -#define LTTV_TRACEFILE_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileStateClass)) - -struct _LttvTracefileState { - LttvTracefileContext parent; - - GQuark tracefile_name; - guint cpu; /* Current cpu of the tracefile */ /* perhaps merge in cpu_state */ - LttvCPUState *cpu_state; /* cpu resource state */ -}; - -struct _LttvTracefileStateClass { - LttvTracefileContextClass parent; -}; - -GType lttv_tracefile_state_get_type (void); - -static inline guint lttv_state_get_target_pid(LttvTracefileState *tfs) -{ - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - guint cpu = tfs->cpu; - LttvProcessState *process = ts->running_process[cpu]; - - if(tfs->parent.target_pid >= 0) return tfs->parent.target_pid; - else return process->pid; -} - +//TODO ybrosseau Need to export that cleanly +//int lttv_state_pop_state_cleanup(LttvProcessState *process, +// LttvEvent *event); #define HDR_PROCESS 0 #define HDR_ES 1 #define HDR_USER_STACK 2 -#define HDR_USERTRACE 3 +//#define HDR_USERTRACE 3 #define HDR_PROCESS_STATE 4 #define HDR_CPU 5 #define HDR_TRACEFILE 6 diff --git a/lttv/lttv/stats.h b/lttv/lttv/stats.h index 658633b3..9c50571a 100644 --- a/lttv/lttv/stats.h +++ b/lttv/lttv/stats.h @@ -19,6 +19,8 @@ #ifndef STATS_H #define STATS_H +#error "stats not supported." + #include #include diff --git a/lttv/lttv/time.h b/lttv/lttv/time.h new file mode 100644 index 00000000..c82011e4 --- /dev/null +++ b/lttv/lttv/time.h @@ -0,0 +1,250 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * 2005 Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LTT_TIME_H +#define LTT_TIME_H + +#include +#include +#include + +typedef struct _LttTime { + unsigned long tv_sec; + unsigned long tv_nsec; +} LttTime; + + +#define NANOSECONDS_PER_SECOND 1000000000 + +/* We give the DIV and MUL constants so we can always multiply, for a + * division as well as a multiplication of NANOSECONDS_PER_SECOND */ +/* 2^30/1.07374182400631629848 = 1000000000.0 */ +#define DOUBLE_SHIFT_CONST_DIV 1.07374182400631629848 +#define DOUBLE_SHIFT 30 + +/* 2^30*0.93132257461547851562 = 1000000000.0000000000 */ +#define DOUBLE_SHIFT_CONST_MUL 0.93132257461547851562 + + +/* 1953125 * 2^9 = NANOSECONDS_PER_SECOND */ +#define LTT_TIME_UINT_SHIFT_CONST 1953125 +#define LTT_TIME_UINT_SHIFT 9 + + +static const LttTime ltt_time_zero = { 0, 0 }; + +static const LttTime ltt_time_one = { 0, 1 }; + +static const LttTime ltt_time_infinite = { G_MAXUINT, NANOSECONDS_PER_SECOND }; + +static inline LttTime ltt_time_sub(LttTime t1, LttTime t2) +{ + LttTime res; + res.tv_sec = t1.tv_sec - t2.tv_sec; + res.tv_nsec = t1.tv_nsec - t2.tv_nsec; + /* unlikely : given equal chance to be anywhere in t1.tv_nsec, and + * higher probability of low value for t2.tv_sec, we will habitually + * not wrap. + */ + if(unlikely(t1.tv_nsec < t2.tv_nsec)) { + res.tv_sec--; + res.tv_nsec += NANOSECONDS_PER_SECOND; + } + return res; +} + + +static inline LttTime ltt_time_add(LttTime t1, LttTime t2) +{ + LttTime res; + res.tv_nsec = t1.tv_nsec + t2.tv_nsec; + res.tv_sec = t1.tv_sec + t2.tv_sec; + /* unlikely : given equal chance to be anywhere in t1.tv_nsec, and + * higher probability of low value for t2.tv_sec, we will habitually + * not wrap. + */ + if(unlikely(res.tv_nsec >= NANOSECONDS_PER_SECOND)) { + res.tv_sec++; + res.tv_nsec -= NANOSECONDS_PER_SECOND; + } + return res; +} + +/* Fastest comparison : t1 > t2 */ +static inline int ltt_time_compare(LttTime t1, LttTime t2) +{ + int ret=0; + if(likely(t1.tv_sec > t2.tv_sec)) ret = 1; + else if(unlikely(t1.tv_sec < t2.tv_sec)) ret = -1; + else if(likely(t1.tv_nsec > t2.tv_nsec)) ret = 1; + else if(unlikely(t1.tv_nsec < t2.tv_nsec)) ret = -1; + + return ret; +} + +#define LTT_TIME_MIN(a,b) ((ltt_time_compare((a),(b)) < 0) ? (a) : (b)) +#define LTT_TIME_MAX(a,b) ((ltt_time_compare((a),(b)) > 0) ? (a) : (b)) + +#define MAX_TV_SEC_TO_DOUBLE 0x7FFFFF +static inline double ltt_time_to_double(LttTime t1) +{ + /* We lose precision if tv_sec is > than (2^23)-1 + * + * Max values that fits in a double (53 bits precision on normalised + * mantissa): + * tv_nsec : NANOSECONDS_PER_SECONDS : 2^30 + * + * So we have 53-30 = 23 bits left for tv_sec. + * */ +#ifdef EXTRA_CHECK + g_assert(t1.tv_sec <= MAX_TV_SEC_TO_DOUBLE); + if(t1.tv_sec > MAX_TV_SEC_TO_DOUBLE) + g_warning("Precision loss in conversion LttTime to double"); +#endif //EXTRA_CHECK + return ((double)((guint64)t1.tv_sec< than (2^23)-1 + * + * Max values that fits in a double (53 bits precision on normalised + * mantissa): + * tv_nsec : NANOSECONDS_PER_SECONDS : 2^30 + * + * So we have 53-30 = 23 bits left for tv_sec. + * */ +#ifdef EXTRA_CHECK + g_assert(t1 <= MAX_TV_SEC_TO_DOUBLE); + if(t1 > MAX_TV_SEC_TO_DOUBLE) + g_warning("Conversion from non precise double to LttTime"); +#endif //EXTRA_CHECK + LttTime res; + //res.tv_sec = t1/(double)NANOSECONDS_PER_SECOND; + res.tv_sec = (guint64)(t1 * DOUBLE_SHIFT_CONST_DIV) >> DOUBLE_SHIFT; + res.tv_nsec = (t1 - (((guint64)res.tv_sec< than (2^62)-1 + * */ +#ifdef EXTRA_CHECK + g_assert(t1 <= MAX_TV_SEC_TO_UINT64); + if(t1 > MAX_TV_SEC_TO_UINT64) + g_warning("Conversion from uint64 to non precise LttTime"); +#endif //EXTRA_CHECK + LttTime res; + //if(unlikely(t1 >= NANOSECONDS_PER_SECOND)) { + if(likely(t1>>LTT_TIME_UINT_SHIFT >= LTT_TIME_UINT_SHIFT_CONST)) { + //res.tv_sec = t1/NANOSECONDS_PER_SECOND; + res.tv_sec = (t1>>LTT_TIME_UINT_SHIFT) + /LTT_TIME_UINT_SHIFT_CONST; // acceleration + res.tv_nsec = (t1 - res.tv_sec*NANOSECONDS_PER_SECOND); + } else { + res.tv_sec = 0; + res.tv_nsec = (guint32)t1; + } + return res; +} + +#endif // LTT_TIME_H diff --git a/lttv/lttv/trace.h b/lttv/lttv/trace.h new file mode 100644 index 00000000..4d87010b --- /dev/null +++ b/lttv/lttv/trace.h @@ -0,0 +1,41 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2012 Yannick Brosseau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ +#ifndef LTTV_TRACE_H +#define LTTV_TRACE_H + +#include +typedef struct _LttvTrace LttvTrace; +//typedef struct _LttvTraceset LttvTraceset; + +LttvTraceset *lttv_trace_get_traceset(LttvTrace *trace); + +void lttv_trace_destroy(LttvTrace *t); + +guint lttv_trace_get_ref_number(LttvTrace * t); + +guint lttv_trace_ref(LttvTrace * t); + +guint lttv_trace_unref(LttvTrace * t); + +guint lttv_trace_get_num_cpu(LttvTrace *t); + +/* An attributes table is attached to the set and to each trace in the set. */ + +LttvAttribute *lttv_trace_attribute(LttvTrace *t); + +#endif //LTTV_TRACE_H diff --git a/lttv/lttv/tracecontext.c b/lttv/lttv/tracecontext.c index 596e06f0..165a890f 100644 --- a/lttv/lttv/tracecontext.c +++ b/lttv/lttv/tracecontext.c @@ -22,10 +22,12 @@ #include #include -#include +#include #include #include +#ifdef BABEL_NOFILTER #include +#endif #include #include #include @@ -36,6 +38,8 @@ #include #include + +#ifdef BABEL_CLEANUP gint compare_tracefile(gconstpointer a, gconstpointer b) { gint comparison = 0; @@ -71,7 +75,7 @@ struct _LttvTracesetContextPosition { * set, else, a position is set (may be end * of trace, with ep->len == 0) */ }; - +#endif void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts) { LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts); @@ -238,7 +242,9 @@ init(LttvTracesetContext *self, LttvTraceset *ts) } self->sync_position = lttv_traceset_context_position_new(self); +#ifdef BABEL_CLEANUP self->pqueue = g_tree_new(compare_tracefile); +#endif lttv_process_traceset_seek_time(self, ltt_time_zero); lttv_traceset_context_compute_time_span(self, &self->time_span); diff --git a/lttv/lttv/tracecontext.h b/lttv/lttv/tracecontext.h deleted file mode 100644 index 764e38a7..00000000 --- a/lttv/lttv/tracecontext.h +++ /dev/null @@ -1,406 +0,0 @@ -/* This file is part of the Linux Trace Toolkit viewer - * Copyright (C) 2003-2004 Michel Dagenais - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef PROCESSTRACE_H -#define PROCESSTRACE_H - -#include -#include -#include -#include -#include -#include - -/* This is the generic part of trace processing. All events within a - certain time interval are accessed and processing hooks are called for - each. The events are examined in monotonically increasing time to more - closely follow the traced system behavior. - - Hooks are called at several different places during the processing: - before traceset, after traceset, check trace, before trace, after trace, - check tracefile, before tracefile, after tracefile, - check_event, before_event, before_event_by_id, - after_event, after_event_by_id. - - In each case the "check" hooks are called first to determine if further - processing of the trace, tracefile or event is wanted. Then, the before - hooks and the after hooks are called. The before hooks for a traceset - are called before those for the contained traces, which are called before - those for the contained tracefiles. The after hooks are called in reverse - order. The event hooks are called after all the before_tracefile hooks - and before all the after_tracefile hooks. - - The hooks receive two arguments, the hook_data and call_data. The hook_data - is specified when the hook is registered and typically links to the - object registering the hook (e.g. a graphical events viewer). The call_data - must contain all the context related to the call. The traceset hooks receive - the LttvTracesetContext provided by the caller. The trace hooks receive - the LttvTraceContext from the traces array in the LttvTracesetContext. - The tracefile and event hooks receive the LttvTracefileContext from - the tracefiles array in the LttvTraceContext. The LttEvent and LttTime - fields in the tracefile context are set to the current event and current - event time before calling the event hooks. No other context field is - modified. - - The contexts in the traces and tracefiles arrays must be allocated by - the caller, either before the call or during the before hooks of the - enclosing traceset or trace. The order in the traces array must - correspond to the lttv_traceset_get function. The order in the tracefiles - arrays must correspond to the ltt_trace_control_tracefile_get and - ltt_trace_per_cpu_tracefile_get functions. The traceset, trace and - tracefile contexts may be subtyped as needed. Indeed, both the contexts - and the hooks are defined by the caller. */ - - -typedef struct _LttvTracesetContext LttvTracesetContext; -typedef struct _LttvTracesetContextClass LttvTracesetContextClass; - -typedef struct _LttvTraceContext LttvTraceContext; -typedef struct _LttvTraceContextClass LttvTraceContextClass; - -typedef struct _LttvTracefileContext LttvTracefileContext; -typedef struct _LttvTracefileContextClass LttvTracefileContextClass; - -typedef struct _LttvTracesetContextPosition LttvTracesetContextPosition; -typedef struct _LttvTraceContextPosition LttvTraceContextPosition; - -#ifndef LTTVFILTER_TYPE_DEFINED -typedef struct _LttvFilter LttvFilter; -#define LTTVFILTER_TYPE_DEFINED -#endif - -typedef struct _LttvTraceState LttvTraceState; - - -#define LTTV_TRACESET_CONTEXT_TYPE (lttv_traceset_context_get_type ()) -#define LTTV_TRACESET_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContext)) -#define LTTV_TRACESET_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContextClass)) -#define LTTV_IS_TRACESET_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACESET_CONTEXT_TYPE)) -#define LTTV_IS_TRACESET_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACESET_CONTEXT_TYPE)) -#define LTTV_TRACESET_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContextClass)) - -struct _LttvTracesetContext { - GObject parent; - - LttvTraceset *ts; - LttvTraceContext **traces; - LttvAttribute *a; - LttvAttribute *ts_a; - TimeInterval time_span; - GTree *pqueue; - struct bt_ctf_iter *iter; - /* TODO ybrosseau: Added for babeltrace proto */ - LttvHooks *event_hooks; - LttvTraceState *tmpState; /* Remove when we have the state in LttvTrace */ - - LttvTracesetContextPosition *sync_position; /* position at which to sync the - trace context */ -}; - -struct _LttvTracesetContextClass { - GObjectClass parent; - - void (*init) (LttvTracesetContext *self, LttvTraceset *ts); - void (*fini) (LttvTracesetContext *self); - LttvTracesetContext* (*new_traceset_context) (LttvTracesetContext *self); - LttvTraceContext* (*new_trace_context) (LttvTracesetContext *self); - LttvTracefileContext* (*new_tracefile_context) (LttvTracesetContext *self); -}; - -GType lttv_traceset_context_get_type (void); - -void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts); - -void lttv_context_fini(LttvTracesetContext *self); - -LttvTracesetContext * -lttv_context_new_traceset_context(LttvTracesetContext *self); - -LttvTraceContext * -lttv_context_new_trace_context(LttvTracesetContext *self); - -LttvTracefileContext * -lttv_context_new_tracefile_context(LttvTracesetContext *self); - - -#define LTTV_TRACE_CONTEXT_TYPE (lttv_trace_context_get_type ()) -#define LTTV_TRACE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContext)) -#define LTTV_TRACE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContextClass)) -#define LTTV_IS_TRACE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACE_CONTEXT_TYPE)) -#define LTTV_IS_TRACE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACE_CONTEXT_TYPE)) -#define LTTV_TRACE_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContextClass)) - -struct _LttvTraceContext { - GObject parent; - - LttvTracesetContext *ts_context; - guint index; /* in ts_context->traces */ - LttTrace *t; - LttvTrace *vt; - //LttvTracefileContext **tracefiles; - GArray *tracefiles; - LttvAttribute *a; - LttvAttribute *t_a; - TimeInterval time_span; -}; - -struct _LttvTraceContextClass { - GObjectClass parent; -}; - -GType lttv_trace_context_get_type (void); - -#define LTTV_TRACEFILE_CONTEXT_TYPE (lttv_tracefile_context_get_type ()) -#define LTTV_TRACEFILE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContext)) -#define LTTV_TRACEFILE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContextClass)) -#define LTTV_IS_TRACEFILE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACEFILE_CONTEXT_TYPE)) -#define LTTV_IS_TRACEFILE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACEFILE_CONTEXT_TYPE)) -#define LTTV_TRACEFILE_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContextClass)) - -struct _LttvTracefileContext { - GObject parent; - - LttvTraceContext *t_context; - // gboolean control; - guint index; /* in ts_context->tracefiles */ - LttTracefile *tf; - // LttEvent *e; - LttvHooks *event; - LttvHooksById *event_by_id; - LttTime timestamp; - LttvAttribute *a; - gint target_pid; /* Target PID of the event. - Updated by state.c. -1 means unset. */ -}; - -struct _LttvTracefileContextClass { - GObjectClass parent; -}; - -GType lttv_tracefile_context_get_type (void); - -/* Run through the events in a traceset in sorted order calling all the - hooks appropriately. It starts at the current time and runs until end or - nb_events are processed. */ - -void lttv_process_traceset(LttvTracesetContext *self, LttTime end, - unsigned nb_events); - -/* Process traceset can also be done in smaller pieces calling begin, - * then seek and middle repeatedly, and end. The middle function return the - * number of events processed. It will be smaller than nb_events if the end time - * or end position is reached. */ - - -void lttv_process_traceset_begin(LttvTracesetContext *self, - LttvHooks *before_traceset, - LttvHooks *before_trace, - LttvHooks *before_tracefile, - LttvHooks *event, - LttvHooksByIdChannelArray *event_by_id_channel); - - -guint lttv_process_traceset_middle(LttvTracesetContext *self, - LttTime end, - gulong nb_events, - const LttvTracesetContextPosition *end_position); - -void lttv_process_traceset_end(LttvTracesetContext *self, - LttvHooks *after_traceset, - LttvHooks *after_trace, - LttvHooks *after_tracefile, - LttvHooks *event, - LttvHooksByIdChannelArray *event_by_id_channel); - -guint lttv_process_traceset_update(LttvTracesetContext *self); - - -void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start); - -void lttv_traceset_context_compute_time_span(LttvTracesetContext *self, - TimeInterval *time_span); - -gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self, - const LttvTracesetContextPosition *pos); - -void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start); - -void lttv_traceset_context_add_hooks(LttvTracesetContext *self, - LttvHooks *before_traceset, - LttvHooks *before_trace, - LttvHooks *before_tracefile, - LttvHooks *event, - LttvHooksByIdChannelArray *event_by_id_channel); - -void lttv_traceset_context_remove_hooks(LttvTracesetContext *self, - LttvHooks *after_traceset, - LttvHooks *after_trace, - LttvHooks *after_tracefile, - LttvHooks *event, - LttvHooksByIdChannelArray *event_by_id_channel); - -void lttv_trace_context_add_hooks(LttvTraceContext *self, - LttvHooks *before_trace, - LttvHooks *before_tracefile, - LttvHooks *event, - LttvHooksByIdChannelArray *event_by_id_channel); - -void lttv_trace_context_remove_hooks(LttvTraceContext *self, - LttvHooks *after_trace, - LttvHooks *after_tracefile, - LttvHooks *event, - LttvHooksByIdChannelArray *event_by_id_channel); - -void lttv_tracefile_context_add_hooks(LttvTracefileContext *self, - LttvHooks *before_tracefile, - LttvHooks *event, - LttvHooksById *event_by_id); - - -void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self, - LttvHooks *after_tracefile, - LttvHooks *event, - LttvHooksById *event_by_id); - -typedef struct _LttvTraceHook { - LttvHook h; - struct marker_data *mdata; - GQuark channel; - guint16 id; /* id of the marker associated with this hook */ - GPtrArray *fields; /* struct marker_fields pointers */ - gpointer hook_data; -} LttvTraceHook; - -/* Get the head of marker list corresponding to the given trace hook. - */ -struct marker_info *lttv_trace_hook_get_marker(LttTrace *t, LttvTraceHook *th); - -/* Remove the hooks from the array. Does not free the array itself. */ -void lttv_trace_hook_remove_all(GArray **th); - -/* Search in the trace for the id of the named event type within the named - facility. Then, find the three (if non null) named fields. All that - information is then used to fill the LttvTraceHook structure. This - is useful to find the specific id for an event within a trace, for - registering a hook using this structure as event data; - it already contains the (up to three) needed fields handles. - Returns the modified LttvTraceHook array. - Prints warnings if events or markers are not found. returns 1 on error, - 0 on success. - Adds the hooks to the trace_hooks array. - */ - -int lttv_trace_find_hook(LttTrace *t, GQuark facility_name, GQuark event_name, - GQuark fields[], LttvHook h, gpointer hook_data, - GArray **trace_hooks); - -static inline struct marker_field * -lttv_trace_get_hook_field(LttvTraceHook *hook, unsigned int index) -{ - return g_ptr_array_index(hook->fields, index); -} - -#if 0 -static inline GQuark lttv_merge_facility_event_name(GQuark fac, GQuark ev) -{ - char *tmp; - const char *sfac, *sev; - GQuark ret; - - sfac = g_quark_to_string(fac); - sev = g_quark_to_string(ev); - tmp = g_new(char, strlen(sfac) + strlen(sev) + 3); /* 3: _ \0 \0 */ - strcpy(tmp, sfac); - strcat(tmp, "_"); - strcat(tmp, sev); - ret = g_quark_from_string(tmp); - g_free(tmp); - return ret; -} -#endif //0 - -LttvTracefileContext * -lttv_traceset_context_get_current_tfc(LttvTracesetContext *self); - - -LttvTracesetContextPosition * -lttv_traceset_context_position_new(const LttvTracesetContext *self); - -void lttv_traceset_context_position_save(const LttvTracesetContext *self, - LttvTracesetContextPosition *pos); - -void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos); - -void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest, - const LttvTracesetContextPosition *src); - -gint -lttv_traceset_context_pos_pos_compare(const LttvTracesetContextPosition *pos1, - const LttvTracesetContextPosition *pos2); - -gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self, - const LttvTracesetContextPosition *pos2); - -LttTime -lttv_traceset_context_position_get_time(const LttvTracesetContextPosition *pos); - -gint compare_tracefile(gconstpointer a, gconstpointer b); - - -/* Synchronisation helpers : save/restore synchronization between ltt traces and - * a traceset context. */ -void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *tsc); - -void lttv_process_traceset_get_sync_data(LttvTracesetContext *tsc); - -/* Seek n events forward and backward (without filtering) : only use these where - * necessary : the seek backward is costy. */ - -#define BACKWARD_SEEK_MUL 2 /* Multiplication factor of time_offset between - backward seek iterations */ - -static const LttTime seek_back_default_offset = { 1, 0 }; - -typedef gboolean check_handler(guint count, gboolean *stop_flag, gpointer data); - -guint lttv_process_traceset_seek_n_forward(LttvTracesetContext *self, - guint n, - check_handler *check, - gboolean *stop_flag, - LttvFilter *filter1, - LttvFilter *filter2, - LttvFilter *filter3, - gpointer data); - -typedef void (*seek_time_fct)(LttvTracesetContext *self, LttTime start); - -/* If first_offset is ltt_time_zero, it will choose a default value */ -guint lttv_process_traceset_seek_n_backward(LttvTracesetContext *self, - guint n, - LttTime first_offset, - seek_time_fct, - check_handler *check, - gboolean *stop_flag, - LttvFilter *filter1, - LttvFilter *filter2, - LttvFilter *filter3, - gpointer data); - -#define FIELD_ARRAY(val...) ((GQuark[]){ val, 0 }) - -#endif // PROCESSTRACE_H diff --git a/lttv/lttv/traceset-process.c b/lttv/lttv/traceset-process.c new file mode 100644 index 00000000..3f6554d1 --- /dev/null +++ b/lttv/lttv/traceset-process.c @@ -0,0 +1,198 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2003-2004 Michel Dagenais + * Copyright (C) 2012 Yannick Brosseau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +void lttv_process_traceset_begin(LttvTraceset *traceset, + LttvHooks *before_traceset, + LttvHooks *before_trace, + LttvHooks *event) +{ + + /* simply add hooks in context. _before hooks are called by add_hooks. */ + /* It calls all before_traceset, before_trace, and before_tracefile hooks. */ + lttv_traceset_add_hooks(traceset, + before_traceset, + before_trace, + event); + + +} + +guint lttv_process_traceset_middle(LttvTraceset *traceset, + LttTime end, + gulong nb_events, + const LttvTracesetPosition *end_position) +{ + + unsigned count = 0; + + struct bt_ctf_event *bt_event; + + LttvEvent event; + struct bt_iter_pos begin_pos; + + begin_pos.type = BT_SEEK_BEGIN; + + if(!traceset->iter) { + traceset->iter = bt_ctf_iter_create(lttv_traceset_get_context(traceset), + &begin_pos, + NULL); + } + while(TRUE) { + + if((count >= nb_events) && (nb_events != G_MAXULONG)) { + break; + } + + if((bt_event = bt_ctf_iter_read_event(traceset->iter)) != NULL) { + + count++; + + event.bt_event = bt_event; + /* TODO ybrosseau 2012-04-01: use bt_ctf_get_trace_handle + to retrieve the right state container */ + event.state = traceset->tmpState; + + lttv_hooks_call(traceset->event_hooks, &event); + + if(bt_iter_next(bt_ctf_get_iter(traceset->iter)) < 0) { + printf("ERROR NEXT\n"); + break; + } + } else { + /* READ FAILED */ + + break; + + } + } + + + + return count; +} + +void lttv_process_traceset_end(LttvTraceset *traceset, + LttvHooks *after_traceset, + LttvHooks *after_trace, + LttvHooks *event) +{ + /* Remove hooks from context. _after hooks are called by remove_hooks. */ + /* It calls all after_traceset, after_trace, and after_tracefile hooks. */ + lttv_traceset_remove_hooks(traceset, + after_traceset, + after_trace, + event); + +} + + +void lttv_traceset_add_hooks(LttvTraceset *traceset, + LttvHooks *before_traceset, + LttvHooks *before_trace, + LttvHooks *event) +{ + + guint i, nb_trace; + + LttvTrace *trace; + + lttv_hooks_call(before_traceset, traceset); + + lttv_hooks_add_list(traceset->event_hooks, event); + + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + trace = (LttvTrace *)g_ptr_array_index(traceset->traces,i); + lttv_trace_add_hooks(trace, + before_trace, + event + ); + } +} +void lttv_traceset_remove_hooks(LttvTraceset *traceset, + LttvHooks *after_traceset, + LttvHooks *after_trace, + LttvHooks *event) +{ + + guint i, nb_trace; + + LttvTrace *trace; + + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + trace = (LttvTrace *)g_ptr_array_index(traceset->traces,i); + lttv_trace_remove_hooks(trace, + after_trace, + event); + + } + + lttv_hooks_call(after_traceset, traceset); + + +} + + +void lttv_trace_add_hooks(LttvTrace *trace, + LttvHooks *before_trace, + LttvHooks *event) +{ + lttv_hooks_call(before_trace, trace); +} + +void lttv_trace_remove_hooks(LttvTrace *trace, + LttvHooks *after_trace, + LttvHooks *event) + +{ + lttv_hooks_call(after_trace, trace); + +} + +void lttv_process_traceset_seek_time(LttvTraceset *traceset, LttTime start) +{ +#ifdef WAIT_FOR_BABELTRACE_FIX_SEEK_ZERO + struct bt_iter_pos seekpos; + int ret; + seekpos.type = BT_SEEK_TIME; + seekpos.u.seek_time = ltt_time_to_uint64(start); + ret = bt_iter_set_pos(bt_ctf_get_iter(self->iter), &seekpos); + if(ret < 0) { + printf("Seek by time error: %s,\n",strerror(-ret)); + } +#else +#warning Seek time disabled because of babeltrace bugs +#endif + +} diff --git a/lttv/lttv/traceset-process.h b/lttv/lttv/traceset-process.h new file mode 100644 index 00000000..cc7b75dd --- /dev/null +++ b/lttv/lttv/traceset-process.h @@ -0,0 +1,143 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2003-2004 Michel Dagenais + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef PROCESSTRACE_H +#define PROCESSTRACE_H + +#include +#include +#include +#include + +//typedef void LttvFilter; /* TODO (MD) */ +typedef struct _LttvFilter LttvFilter; + +/* Run through the events in a traceset in sorted order calling all the + hooks appropriately. It starts at the current time and runs until end or + nb_events are processed. */ + +void lttv_process_traceset(LttvTraceset *traceset, LttTime end, + unsigned nb_events); + +/* Process traceset can also be done in smaller pieces calling begin, + * then seek and middle repeatedly, and end. The middle function return the + * number of events processed. It will be smaller than nb_events if the end time + * or end position is reached. */ + + +void lttv_process_traceset_begin(LttvTraceset *traceset, + LttvHooks *before_traceset, + LttvHooks *before_trace, + LttvHooks *event); + +guint lttv_process_traceset_middle(LttvTraceset *traceset, + LttTime end, + gulong nb_events, + const LttvTracesetPosition *end_position); + +void lttv_process_traceset_end(LttvTraceset *traceset, + LttvHooks *after_traceset, + LttvHooks *after_trace, + LttvHooks *event); + +guint lttv_process_traceset_update(LttvTraceset *traceset); + + +void lttv_process_traceset_seek_time(LttvTraceset *traceset, LttTime start); + +void lttv_traceset_compute_time_span(LttvTraceset *traceset, + TimeInterval *time_span); + +gboolean lttv_process_traceset_seek_position(LttvTraceset *traceset, + const LttvTracesetPosition *pos); + +void lttv_process_trace_seek_time(LttvTrace *trace, LttTime start); + +void lttv_traceset_add_hooks(LttvTraceset *traceset, + LttvHooks *before_traceset, + LttvHooks *before_trace, + LttvHooks *event); + +void lttv_traceset_remove_hooks(LttvTraceset *traceset, + LttvHooks *after_traceset, + LttvHooks *after_trace, + LttvHooks *event); + +void lttv_trace_add_hooks(LttvTrace *trace, + LttvHooks *before_trace, + LttvHooks *event); + +void lttv_trace_remove_hooks(LttvTrace *trace, + LttvHooks *after_trace, + LttvHooks *event); + +LttvTracesetPosition * +lttv_traceset_position_new(const LttvTraceset *traceset); + +void lttv_traceset_position_save(const LttvTraceset *traceset, + LttvTracesetPosition *pos); + +void lttv_traceset_position_destroy(LttvTracesetPosition *pos); + +void lttv_traceset_position_copy(LttvTracesetPosition *dest, + const LttvTracesetPosition *src); + +gint +lttv_traceset_pos_pos_compare(const LttvTracesetPosition *pos1, + const LttvTracesetPosition *pos2); + +gint lttv_traceset_ts_pos_compare(const LttvTraceset *traceset, + const LttvTracesetPosition *pos2); + +LttTime +lttv_traceset_position_get_time(const LttvTracesetPosition *pos); + +/* Seek n events forward and backward (without filtering) : only use these where + * necessary : the seek backward is costy. */ + +#define BACKWARD_SEEK_MUL 2 /* Multiplication factor of time_offset between + backward seek iterations */ + +static const LttTime seek_back_default_offset = { 1, 0 }; + +typedef gboolean check_handler(guint count, gboolean *stop_flag, gpointer data); + +guint lttv_process_traceset_seek_n_forward(LttvTraceset *traceset, + guint n, + check_handler *check, + gboolean *stop_flag, + LttvFilter *filter1, + LttvFilter *filter2, + LttvFilter *filter3, + gpointer data); + +typedef void (*seek_time_fct)(LttvTraceset *traceset, LttTime start); + +/* If first_offset is ltt_time_zero, it will choose a default value */ +guint lttv_process_traceset_seek_n_backward(LttvTraceset *traceset, + guint n, + LttTime first_offset, + seek_time_fct, + check_handler *check, + gboolean *stop_flag, + LttvFilter *filter1, + LttvFilter *filter2, + LttvFilter *filter3, + gpointer data); + +#endif // PROCESSTRACE_H diff --git a/lttv/lttv/traceset.c b/lttv/lttv/traceset.c index b28efb3a..16487a11 100644 --- a/lttv/lttv/traceset.c +++ b/lttv/lttv/traceset.c @@ -22,39 +22,43 @@ #include #include +#include +#include #include #include - +#include +#include /* A trace is a sequence of events gathered in the same tracing session. The events may be stored in several tracefiles in the same directory. A trace set is defined when several traces are to be analyzed together, possibly to study the interactions between events in the different traces. */ -struct _LttvTraceset { - char * filename; - GPtrArray *traces; - struct bt_context *context; - LttvAttribute *a; -}; - - -struct _LttvTrace { - // Trace id for babeltrace - gint id; - LttvAttribute *a; - guint ref_count; -}; -LttvTraceset *lttv_traceset_new() +LttvTraceset *lttv_traceset_new(void) { LttvTraceset *s; + struct bt_iter_pos begin_pos; s = g_new(LttvTraceset, 1); s->filename = NULL; s->traces = g_ptr_array_new(); s->context = bt_context_create(); s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + //TODO remove this when we have really mecanism + //s->tmpState = g_new(LttvTraceState *, 1); + //lttv_trace_state_init(s->tmpState,0); + begin_pos.type = BT_SEEK_BEGIN; + + //s->iter = bt_ctf_iter_create(lttv_traceset_get_context(s), + // &begin_pos, + // NULL); + s->iter = 0; + s->event_hooks = lttv_hooks_new(); + + + + return s; } @@ -106,6 +110,10 @@ static LttvTrace *lttv_trace_create(LttvTraceset *ts, const char *path) new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); new_trace->id = id; new_trace->ref_count = 0; + new_trace->traceset = ts; + new_trace->state = g_new(LttvTraceState,1); + lttv_trace_state_init(new_trace->state,new_trace); + ts->tmpState = new_trace->state; return new_trace; } @@ -142,6 +150,7 @@ LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) trace = g_ptr_array_index(s_orig->traces, i); trace->ref_count++; + /* WARNING: this is an alias, not a copy. */ g_ptr_array_add(s->traces, trace); } s->context = s_orig->context; @@ -200,6 +209,16 @@ struct bt_context *lttv_traceset_get_context(LttvTraceset *s) return s->context; } +LttvTraceset *lttv_trace_get_traceset(LttvTrace *trace) +{ + return trace->traceset; +} + +LttvHooks *lttv_traceset_get_hooks(LttvTraceset *s) +{ + return s->event_hooks; +} + void lttv_trace_destroy(LttvTrace *t) { g_object_unref(t->a); @@ -291,3 +310,53 @@ guint lttv_trace_unref(LttvTrace * t) return t->ref_count; } +guint lttv_trace_get_num_cpu(LttvTrace *t) +{ +#warning "TODO - Set the right number of CPU" + return 24; +} + +LttvTracesetPosition *lttv_traceset_create_position(LttvTraceset *traceset) +{ +#warning "TODO" + return NULL; +} + +void lttv_traceset_destroy_position(LttvTracesetPosition *traceset_pos) +{ +#warning "TODO" + return NULL; +} + +void lttv_traceset_seek_to_position(LttvTracesetPosition *traceset_pos) +{ +#warning "TODO" +} + +guint lttv_traceset_get_cpuid_from_event(LttvEvent *event) +{ + struct definition *scope; + unsigned long timestamp; + unsigned int cpu_id; + + struct bt_ctf_event *ctf_event = event->bt_event; + timestamp = bt_ctf_get_timestamp(ctf_event); + if (timestamp == -1ULL) { + return 0; + } + scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); + if (bt_ctf_field_get_error()) { + return 0; + } + cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(ctf_event, scope, "cpu_id")); + if (bt_ctf_field_get_error()) { + return 0; + } else { + return cpu_id; + } +} + +const char *lttv_traceset_get_name_from_event(LttvEvent *event) +{ + return bt_ctf_event_name(event->bt_event); +} diff --git a/lttv/lttv/traceset.h b/lttv/lttv/traceset.h index 6bce443c..9d626876 100644 --- a/lttv/lttv/traceset.h +++ b/lttv/lttv/traceset.h @@ -21,19 +21,47 @@ #include #include +#include #include - +#include /* A traceset is a set of traces to be analyzed together. */ typedef struct _LttvTraceset LttvTraceset; -typedef struct _LttvTrace LttvTrace; +typedef struct _LttvTracesetPosition LttvTracesetPosition; struct bt_context; + +//TODO ybrosseau 2012-05-15 put these struct in the .c to make them opaque +struct _LttvTraceset { + char * filename; + GPtrArray *traces; /* Array of pointers to LttvTrace */ + struct bt_context *context; + LttvAttribute *a; + LttvHooks *event_hooks; + struct bt_ctf_iter *iter; + LttvTraceState *tmpState; + +}; + +struct _LttvTrace { + // Trace id for babeltrace + LttvTraceset *traceset; /* container traceset */ + gint id; + LttvAttribute *a; + guint ref_count; + LttvTraceState *state; +}; + +/* In babeltrace, the position concept is an iterator. */ +struct _LttvTracesetPosition { + struct bt_ctf_iter *iter; +}; + /* Tracesets may be added to, removed from and their content listed. */ -LttvTraceset *lttv_traceset_new(); +LttvTraceset *lttv_traceset_new(void); char * lttv_traceset_name(LttvTraceset * s); @@ -48,11 +76,11 @@ LttvTraceset *lttv_traceset_load(const gchar *filename); struct bt_context *lttv_traceset_get_context(LttvTraceset *s); + gint lttv_traceset_save(LttvTraceset *s); void lttv_traceset_destroy(LttvTraceset *s); -void lttv_trace_destroy(LttvTrace *t); void lttv_traceset_add(LttvTraceset *s, LttvTrace *t); @@ -80,17 +108,21 @@ void lttv_traceset_remove(LttvTraceset *s, unsigned i); LttvAttribute *lttv_traceset_attribute(LttvTraceset *s); -LttvAttribute *lttv_trace_attribute(LttvTrace *t); #ifdef BABEL_CLEANUP LttTrace *lttv_trace(LttvTrace *t); #endif -guint lttv_trace_get_ref_number(LttvTrace * t); +/* Take a position snapshot */ +LttvTracesetPosition *lttv_traceset_create_position(LttvTraceset *traceset); -guint lttv_trace_ref(LttvTrace * t); +/* Destroy position snapshot */ +void lttv_traceset_destroy_position(LttvTracesetPosition *traceset_pos); -guint lttv_trace_unref(LttvTrace * t); +void lttv_traceset_seek_to_position(LttvTracesetPosition *traceset_pos); -#endif // TRACESET_H +guint lttv_traceset_get_cpuid_from_event(LttvEvent *event); + +const char *lttv_traceset_get_name_from_event(LttvEvent *event); +#endif // TRACESET_H diff --git a/lttv/modules/text/Makefile.am b/lttv/modules/text/Makefile.am index b5370199..f67472a3 100644 --- a/lttv/modules/text/Makefile.am +++ b/lttv/modules/text/Makefile.am @@ -3,18 +3,18 @@ AM_LDFLAGS = $(MODULE_LDFLAGS) libdir = ${lttvplugindir} -lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la libtextFilter.la libprecomputeState.la libsync_chain_batch.la +lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la ## # Libraries pending babeltrace conversion -#libdepanalysis.la libformattedDump.la +#libdepanalysis.la libformattedDump.la libtextFilter precomputeState sync_chain_batch libtextDump_la_SOURCES = textDump.c libbatchAnalysis_la_SOURCES = batchAnalysis.c -libtextFilter_la_SOURCES = textFilter.c -libprecomputeState_la_SOURCES = precomputeState.c +#libtextFilter_la_SOURCES = textFilter.c +#libprecomputeState_la_SOURCES = precomputeState.c #libdepanalysis_la_SOURCES = depanalysis.c sstack.c -libsync_chain_batch_la_SOURCES = sync_chain_batch.c +#libsync_chain_batch_la_SOURCES = sync_chain_batch.c #libformattedDump_la_SOURCES = formattedDump.c noinst_HEADERS = \ diff --git a/lttv/modules/text/batchAnalysis.c b/lttv/modules/text/batchAnalysis.c index ae661d47..c830509c 100644 --- a/lttv/modules/text/batchAnalysis.c +++ b/lttv/modules/text/batchAnalysis.c @@ -30,13 +30,16 @@ #include #include #include -#include +#include #include +#ifdef BABEL_CLEANUP #include #include +#endif #include +#ifdef BABEL_CLEANUP_SYNC #include - +#endif #include static LttvTraceset *traceset; @@ -86,17 +89,18 @@ static gboolean process_traceset(void *hook_data, void *call_data) LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); +#ifdef BABEL_CLEANUP LttvTracesetStats *tscs = NULL; LttvTracesetState *tss; LttvTracesetContext *tc; - +#endif LttTime start, end; gboolean retval; g_info("BatchAnalysis begin process traceset"); - +#ifdef BABEL_CLEANUP if (a_stats) { tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL); tss = &tscs->parent; @@ -109,12 +113,12 @@ static gboolean process_traceset(void *hook_data, void *call_data) lttv_context_init(tc, traceset); -#ifdef BABEL_CLEANUP + syncTraceset(tc); lttv_state_add_event_hooks(tss); if(a_stats) lttv_stats_add_event_hooks(tscs); -#endif + retval= lttv_iattribute_find_by_path(attributes, "filter/expression", LTTV_POINTER, &value_expression); @@ -135,16 +139,16 @@ static gboolean process_traceset(void *hook_data, void *call_data) //g_debug("Filter string: %s",((GString*)*(value_expression.v_pointer))->str); lttv_filter_append_expression(*(value_filter.v_pointer),((GString*)*(value_expression.v_pointer))->str); - +#endif //lttv_traceset_context_add_hooks(tc, //before_traceset, after_traceset, NULL, before_trace, after_trace, //NULL, before_tracefile, after_tracefile, NULL, before_event, after_event); - lttv_process_traceset_begin(tc, + + lttv_state_add_event_hooks(traceset); + lttv_process_traceset_begin(traceset, before_traceset, before_trace, - before_tracefile, - event_hook, - NULL); + event_hook); start.tv_sec = 0; start.tv_nsec = 0; @@ -153,12 +157,12 @@ static gboolean process_traceset(void *hook_data, void *call_data) g_info("BatchAnalysis process traceset"); - lttv_process_traceset_seek_time(tc, start); + lttv_process_traceset_seek_time(traceset, start); /* Read as long a we do not reach the end (0) */ unsigned int count; unsigned int updated_count; do { - count = lttv_process_traceset_middle(tc, + count = lttv_process_traceset_middle(traceset, end, G_MAXULONG, NULL); @@ -178,26 +182,24 @@ static gboolean process_traceset(void *hook_data, void *call_data) //lttv_traceset_context_remove_hooks(tc, //before_traceset, after_traceset, NULL, before_trace, after_trace, //NULL, before_tracefile, after_tracefile, NULL, before_event, after_event); - lttv_process_traceset_end(tc, + lttv_process_traceset_end(traceset, after_traceset, after_trace, - after_tracefile, - event_hook, - NULL); + event_hook); g_info("BatchAnalysis destroy context"); - - lttv_filter_destroy(*(value_filter.v_pointer)); #ifdef BABEL_CLEANUP + lttv_filter_destroy(*(value_filter.v_pointer)); + lttv_state_remove_event_hooks(tss); if(a_stats) lttv_stats_remove_event_hooks(tscs); -#endif + lttv_context_fini(tc); if (a_stats) g_object_unref(tscs); else g_object_unref(tss); - +#endif g_info("BatchAnalysis end process traceset"); return FALSE; } @@ -331,4 +333,5 @@ static void destroy() LTTV_MODULE("batchAnalysis", "Batch processing of a trace", \ "Run through a trace calling all the registered hooks", \ - init, destroy, "state", "stats", "option","textFilter", "sync") + init, destroy, "state", "option") +//TODO ybrosseau 2012-05-15 reenable textFilter, stats, sync diff --git a/lttv/modules/text/textDump.c b/lttv/modules/text/textDump.c index dd5f5ee0..a8fadb5d 100644 --- a/lttv/modules/text/textDump.c +++ b/lttv/modules/text/textDump.c @@ -31,8 +31,10 @@ #include #include #include +#ifdef BABEL_CLEANUP #include #include +#endif #include #include #include @@ -197,7 +199,7 @@ print_tree(FILE *fp, GString *indent, LttvAttribute *tree) } } } - +#ifdef BABEL_CLEANUP static void print_stats(FILE *fp, LttvTracesetStats *tscs) { @@ -244,7 +246,7 @@ print_stats(FILE *fp, LttvTracesetStats *tscs) } g_string_free(indent, TRUE); } - +#endif /* Insert the hooks before and after each trace and tracefile, and for each event. Print a global header. */ @@ -254,7 +256,7 @@ static GString *a_string; static gboolean write_traceset_header(void *hook_data, void *call_data) { - LttvTracesetContext *tc = (LttvTracesetContext *)call_data; + LttvTraceset *traceset = (LttvTraceset *)call_data; g_info("TextDump traceset header"); @@ -265,7 +267,7 @@ static gboolean write_traceset_header(void *hook_data, void *call_data) /* Print the trace set header */ fprintf(a_file,"Trace set contains %d traces\n\n", - lttv_traceset_number(tc->ts)); + lttv_traceset_number(traceset)); return FALSE; } @@ -273,17 +275,17 @@ static gboolean write_traceset_header(void *hook_data, void *call_data) static gboolean write_traceset_footer(void *hook_data, void *call_data) { - LttvTracesetContext *tc = (LttvTracesetContext *)call_data; + LttvTraceset *traceset = (LttvTraceset *)call_data; g_info("TextDump traceset footer"); fprintf(a_file,"End trace set\n\n"); - +#ifdef BABEL_CLEANUP if(LTTV_IS_TRACESET_STATS(tc)) { lttv_stats_sum_traceset((LttvTracesetStats *)tc, ltt_time_infinite); print_stats(a_file, (LttvTracesetStats *)tc); } - +#endif if(a_file_name != NULL) fclose(a_file); return FALSE; @@ -310,7 +312,7 @@ static int write_event_content(void *hook_data, void *call_data) LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); - LttvEvent *event = (struct bt_ctf_event *)call_data; + LttvEvent *event = (LttvEvent *)call_data; #ifdef BABEL_CLEANUP LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; @@ -483,5 +485,5 @@ static void destroy() LTTV_MODULE("textDump", "Print events in a file", \ "Produce a detailed text printout of a trace", \ - init, destroy, "stats", "batchAnalysis", "option", "print") + init, destroy, "batchAnalysis", "option", "print") -- 2.34.1