X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttv%2Flttv%2Fsync%2Fevent_processing_lttng_standard.c;h=d37d357c659a4b4333aef66676cce36bafd085af;hb=0a87ec9a018cc9731ce3b04309eaa4dcc77df6d2;hp=1ee27c761567ddbee8e707b149cb00cc708208dd;hpb=2bd4b3e43e525da7b4c9738915ec847f7fe4906a;p=lttv.git diff --git a/lttv/lttv/sync/event_processing_lttng_standard.c b/lttv/lttv/sync/event_processing_lttng_standard.c index 1ee27c76..d37d357c 100644 --- a/lttv/lttv/sync/event_processing_lttng_standard.c +++ b/lttv/lttv/sync/event_processing_lttng_standard.c @@ -1,30 +1,26 @@ /* This file is part of the Linux Trace Toolkit viewer - * Copyright (C) 2009 Benjamin Poirier + * Copyright (C) 2009, 2010 Benjamin Poirier * - * 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 free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or (at + * your option) any later version. * - * 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. + * 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 Lesser 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. + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -#define _ISOC99_SOURCE - #ifdef HAVE_CONFIG_H #include #endif -#include -#include #include +#include #include #include #include @@ -34,26 +30,26 @@ #include "event_processing_lttng_standard.h" - -#ifndef g_info -#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) -#endif +/* IPv4 Ethertype, taken from , unlikely to change as it's + * defined by IANA: http://www.iana.org/assignments/ethernet-numbers + */ +#define ETH_P_IP 0x0800 // Functions common to all processing modules -static void initProcessingLTTVStandard(SyncState* const syncState, - LttvTracesetContext* const traceSetContext); +static void initProcessingLTTVStandard(SyncState* const syncState, ...); static void destroyProcessingLTTVStandard(SyncState* const syncState); -static void finalizeProcessingLTTVStandard(SyncState* const syncState); +static AllFactors* finalizeProcessingLTTVStandard(SyncState* const syncState); static void printProcessingStatsLTTVStandard(SyncState* const syncState); -static void writeProcessingGraphsPlotsLTTVStandard(FILE* stream, SyncState* - const syncState, const unsigned int i, const unsigned int j); -static void writeProcessingGraphsOptionsLTTVStandard(FILE* stream, SyncState* - const syncState, const unsigned int i, const unsigned int j); +static void writeProcessingGraphVariablesLTTVStandard(SyncState* const + syncState, const unsigned int i); +static void writeProcessingTraceTraceOptionsLTTVStandard(SyncState* const + syncState, const unsigned int i, const unsigned int j); +static void writeProcessingTraceTimeOptionsLTTVStandard(SyncState* const + syncState, const unsigned int i, const unsigned int j); // Functions specific to this module -static void registerProcessingLTTVStandard() __attribute__((constructor (102))); static gboolean processEventLTTVStandard(void* hookData, void* callData); static void partialDestroyProcessingLTTVStandard(SyncState* const syncState); @@ -64,16 +60,18 @@ static ProcessingModule processingModuleLTTVStandard = { .destroyProcessing= &destroyProcessingLTTVStandard, .finalizeProcessing= &finalizeProcessingLTTVStandard, .printProcessingStats= &printProcessingStatsLTTVStandard, - .writeProcessingGraphsPlots= &writeProcessingGraphsPlotsLTTVStandard, - .writeProcessingGraphsOptions= &writeProcessingGraphsOptionsLTTVStandard, + .graphFunctions= { + .writeVariables= &writeProcessingGraphVariablesLTTVStandard, + .writeTraceTraceOptions= &writeProcessingTraceTraceOptionsLTTVStandard, + .writeTraceTimeOptions= &writeProcessingTraceTimeOptionsLTTVStandard, + }, }; - /* * Processing Module registering function */ -static void registerProcessingLTTVStandard() +void registerProcessingLTTVStandard() { g_queue_push_tail(&processingModules, &processingModuleLTTVStandard); @@ -92,17 +90,39 @@ static void registerProcessingLTTVStandard() * pendingRecv * hookListList * stats - * traceSetContext: set of LTTV traces + * traceSetContext: LttvTracesetContext*, set of LTTV traces */ -static void initProcessingLTTVStandard(SyncState* const syncState, LttvTracesetContext* - const traceSetContext) +static void initProcessingLTTVStandard(SyncState* const syncState, ...) { unsigned int i; ProcessingDataLTTVStandard* processingData; + va_list ap; processingData= malloc(sizeof(ProcessingDataLTTVStandard)); syncState->processingData= processingData; - processingData->traceSetContext= traceSetContext; + va_start(ap, syncState); + processingData->traceSetContext= va_arg(ap, LttvTracesetContext*); + va_end(ap); + syncState->traceNb= + lttv_traceset_number(processingData->traceSetContext->ts); + processingData->hookListList= g_array_sized_new(FALSE, FALSE, + sizeof(GArray*), syncState->traceNb); + + processingData->traceNumTable= g_hash_table_new(&g_direct_hash, NULL); + for(i= 0; i < syncState->traceNb; i++) + { + g_hash_table_insert(processingData->traceNumTable, + processingData->traceSetContext->traces[i]->t, + GUINT_TO_POINTER(i)); + } + + processingData->pendingRecv= malloc(sizeof(GHashTable*) * + syncState->traceNb); + for(i= 0; i < syncState->traceNb; i++) + { + processingData->pendingRecv[i]= g_hash_table_new_full(&g_direct_hash, + NULL, NULL, &gdnDestroyEvent); + } if (syncState->stats) { @@ -113,26 +133,26 @@ static void initProcessingLTTVStandard(SyncState* const syncState, LttvTracesetC processingData->stats= NULL; } - processingData->traceNumTable= g_hash_table_new(&g_direct_hash, NULL); - processingData->hookListList= g_array_sized_new(FALSE, FALSE, - sizeof(GArray*), syncState->traceNb); - processingData->pendingRecv= malloc(sizeof(GHashTable*) * - syncState->traceNb); - - for(i= 0; i < syncState->traceNb; i++) + if (syncState->graphsStream) { - g_hash_table_insert(processingData->traceNumTable, - processingData->traceSetContext->traces[i]->t, (gpointer) i); - } + processingData->graphs= malloc(syncState->traceNb * + sizeof(ProcessingGraphsLTTVStandard)); - for(i= 0; i < syncState->traceNb; i++) + for(i= 0; i < syncState->traceNb; i++) + { + LttTrace* traceI= processingData->traceSetContext->traces[i]->t; + + processingData->graphs[i].startFreq= traceI->start_freq; + processingData->graphs[i].freqScale= traceI->freq_scale; + } + } + else { - processingData->pendingRecv[i]= g_hash_table_new_full(&g_direct_hash, - NULL, NULL, &gdnDestroyEvent); + processingData->graphs= NULL; } - registerHooks(processingData->hookListList, traceSetContext, - &processEventLTTVStandard, syncState, + registerHooks(processingData->hookListList, + processingData->traceSetContext, &processEventLTTVStandard, syncState, syncState->matchingModule->canMatch); } @@ -143,96 +163,31 @@ static void initProcessingLTTVStandard(SyncState* const syncState, LttvTracesetC * * Args: * syncState container for synchronization data. + * + * Returns: + * AllFactors synchronization factors for each trace pair */ -static void finalizeProcessingLTTVStandard(SyncState* const syncState) +static AllFactors* finalizeProcessingLTTVStandard(SyncState* const syncState) { - unsigned int i; - GArray* factors; - double minOffset, minDrift; - unsigned int refFreqTrace; ProcessingDataLTTVStandard* processingData; processingData= (ProcessingDataLTTVStandard*) syncState->processingData; partialDestroyProcessingLTTVStandard(syncState); - factors= syncState->matchingModule->finalizeMatching(syncState); - - /* The offsets are adjusted so the lowest one is 0. This is done because - * of a Lttv specific limitation: events cannot have negative times. By - * having non-negative offsets, events cannot be moved backwards to - * negative times. - */ - minOffset= 0; - for (i= 0; i < syncState->traceNb; i++) - { - minOffset= MIN(g_array_index(factors, Factors, i).offset, minOffset); - } - - for (i= 0; i < syncState->traceNb; i++) - { - g_array_index(factors, Factors, i).offset-= minOffset; - } - - /* Because the timestamps are corrected at the TSC level (not at the - * LttTime level) all trace frequencies must be made equal. We choose to - * use the frequency of the system with the lowest drift - */ - minDrift= INFINITY; - refFreqTrace= 0; - for (i= 0; i < syncState->traceNb; i++) - { - if (g_array_index(factors, Factors, i).drift < minDrift) - { - minDrift= g_array_index(factors, Factors, i).drift; - refFreqTrace= i; - } - } - g_assert(syncState->traceNb == 0 || minDrift != INFINITY); - - // Write the factors to the LttTrace structures - for (i= 0; i < syncState->traceNb; i++) - { - LttTrace* t; - Factors* traceFactors; - - t= processingData->traceSetContext->traces[i]->t; - traceFactors= &g_array_index(factors, Factors, i); - - t->drift= traceFactors->drift; - t->offset= traceFactors->offset; - t->start_freq= - processingData->traceSetContext->traces[refFreqTrace]->t->start_freq; - t->freq_scale= - processingData->traceSetContext->traces[refFreqTrace]->t->freq_scale; - t->start_time_from_tsc = - ltt_time_from_uint64(tsc_to_uint64(t->freq_scale, t->start_freq, - t->drift * t->start_tsc + t->offset)); - } - - g_array_free(factors, TRUE); - - lttv_traceset_context_compute_time_span(processingData->traceSetContext, - &processingData->traceSetContext->time_span); - - g_debug("traceset start %ld.%09ld end %ld.%09ld\n", - processingData->traceSetContext->time_span.start_time.tv_sec, - processingData->traceSetContext->time_span.start_time.tv_nsec, - processingData->traceSetContext->time_span.end_time.tv_sec, - processingData->traceSetContext->time_span.end_time.tv_nsec); + return syncState->matchingModule->finalizeMatching(syncState); } /* - * Print statistics related to processing and downstream modules. Must be - * called after finalizeProcessing. + * Print statistics related to processing Must be called after + * finalizeProcessing. * * Args: * syncState container for synchronization data. */ static void printProcessingStatsLTTVStandard(SyncState* const syncState) { - unsigned int i; ProcessingDataLTTVStandard* processingData; if (!syncState->stats) @@ -261,24 +216,6 @@ static void printProcessingStatsLTTVStandard(SyncState* const syncState) printf("\tsent packets that are TCP: %d\n", processingData->stats->totOutE); } - - if (syncState->matchingModule->printMatchingStats != NULL) - { - syncState->matchingModule->printMatchingStats(syncState); - } - - printf("Resulting synchronization factors:\n"); - for (i= 0; i < syncState->traceNb; i++) - { - LttTrace* t; - - t= processingData->traceSetContext->traces[i]->t; - - printf("\ttrace %u drift= %g offset= %g (%f) start time= %ld.%09ld\n", - i, t->drift, t->offset, (double) tsc_to_uint64(t->freq_scale, - t->start_freq, t->offset) / NANOSECONDS_PER_SECOND, - t->start_time_from_tsc.tv_sec, t->start_time_from_tsc.tv_nsec); - } } @@ -308,6 +245,11 @@ static void destroyProcessingLTTVStandard(SyncState* const syncState) free(processingData->stats); } + if (syncState->graphsStream) + { + free(processingData->graphs); + } + free(syncState->processingData); syncState->processingData= NULL; } @@ -344,7 +286,7 @@ static void partialDestroyProcessingLTTVStandard(SyncState* const syncState) for(i= 0; i < syncState->traceNb; i++) { - g_debug("Cleaning up pendingRecv list\n"); + g_debug("Cleaning up pendingRecv list"); g_hash_table_destroy(processingData->pendingRecv[i]); } free(processingData->pendingRecv); @@ -370,13 +312,15 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) LttvTraceHook* traceHook; LttvTracefileContext* tfc; LttEvent* event; - LttTime time; LttCycleCount tsc; + LttTime time; + WallTime wTime; LttTrace* trace; unsigned long traceNum; struct marker_info* info; SyncState* syncState; ProcessingDataLTTVStandard* processingData; + gpointer traceNumP; traceHook= (LttvTraceHook*) hookData; tfc= (LttvTracefileContext*) callData; @@ -384,15 +328,18 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) syncState= (SyncState*) traceHook->hook_data; processingData= (ProcessingDataLTTVStandard*) syncState->processingData; event= ltt_tracefile_get_event(tfc->tf); - time= ltt_event_time(event); - tsc= trace->drift * ltt_event_cycle_count(event) + trace->offset; info= marker_get_info_from_id(tfc->tf->mdata, event->event_id); + tsc= ltt_event_cycle_count(event); + time= ltt_event_time(event); + wTime.seconds= time.tv_sec; + wTime.nanosec= time.tv_nsec; g_assert(g_hash_table_lookup_extended(processingData->traceNumTable, - trace, NULL, (gpointer*) &traceNum)); + trace, NULL, &traceNumP)); + traceNum= GPOINTER_TO_INT(traceNumP); - g_debug("XXXX process event: time: %ld.%09ld trace: %ld (%p) name: %s ", - (long) time.tv_sec, time.tv_nsec, traceNum, trace, + g_debug("Process event: time: %ld.%09ld trace: %ld (%p) name: %s ", + time.tv_sec, time.tv_nsec, traceNum, trace, g_quark_to_string(info->name)); if (info->name == LTT_EVENT_DEV_XMIT_EXTENDED) @@ -419,18 +366,20 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) outE= malloc(sizeof(Event)); outE->traceNum= traceNum; - outE->time= tsc; + outE->cpuTime= tsc; + outE->wallTime= wTime; outE->type= TCP; + outE->copy= ©TCPEvent; outE->destroy= &destroyTCPEvent; outE->event.tcpEvent= malloc(sizeof(TCPEvent)); outE->event.tcpEvent->direction= OUT; outE->event.tcpEvent->segmentKey= malloc(sizeof(SegmentKey)); outE->event.tcpEvent->segmentKey->connectionKey.saddr= - ltt_event_get_unsigned(event, lttv_trace_get_hook_field(traceHook, - 3)); + htonl(ltt_event_get_unsigned(event, + lttv_trace_get_hook_field(traceHook, 3))); outE->event.tcpEvent->segmentKey->connectionKey.daddr= - ltt_event_get_unsigned(event, lttv_trace_get_hook_field(traceHook, - 4)); + htonl(ltt_event_get_unsigned(event, + lttv_trace_get_hook_field(traceHook, 4))); outE->event.tcpEvent->segmentKey->tot_len= ltt_event_get_unsigned(event, lttv_trace_get_hook_field(traceHook, 5)); @@ -460,7 +409,7 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) syncState->matchingModule->matchEvent(syncState, outE); - g_debug("Output event done\n"); + g_debug("Output event done"); } else if (info->name == LTT_EVENT_DEV_RECEIVE) { @@ -486,8 +435,10 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) inE= malloc(sizeof(Event)); inE->traceNum= traceNum; - inE->time= tsc; + inE->cpuTime= tsc; + inE->wallTime= wTime; inE->event.tcpEvent= NULL; + inE->copy= ©Event; inE->destroy= &destroyEvent; skb= (void*) (long) ltt_event_get_long_unsigned(event, @@ -495,11 +446,7 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) g_hash_table_replace(processingData->pendingRecv[traceNum], skb, inE); - g_debug("Adding inE %p for skb %p to pendingRecv\n", inE, skb); - } - else - { - g_debug("\n"); + g_debug("Adding inE %p for skb %p to pendingRecv", inE, skb); } } else if (info->name == LTT_EVENT_TCPV4_RCV_EXTENDED) @@ -530,15 +477,16 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) inE->type= TCP; inE->event.tcpEvent= malloc(sizeof(TCPEvent)); + inE->copy= ©TCPEvent; inE->destroy= &destroyTCPEvent; inE->event.tcpEvent->direction= IN; inE->event.tcpEvent->segmentKey= malloc(sizeof(SegmentKey)); inE->event.tcpEvent->segmentKey->connectionKey.saddr= - ltt_event_get_unsigned(event, - lttv_trace_get_hook_field(traceHook, 1)); + htonl(ltt_event_get_unsigned(event, + lttv_trace_get_hook_field(traceHook, 1))); inE->event.tcpEvent->segmentKey->connectionKey.daddr= - ltt_event_get_unsigned(event, - lttv_trace_get_hook_field(traceHook, 2)); + htonl(ltt_event_get_unsigned(event, + lttv_trace_get_hook_field(traceHook, 2))); inE->event.tcpEvent->segmentKey->tot_len= ltt_event_get_unsigned(event, lttv_trace_get_hook_field(traceHook, 3)); @@ -575,7 +523,7 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) syncState->matchingModule->matchEvent(syncState, inE); - g_debug("TCP input event %p for skb %p done\n", inE, skb); + g_debug("TCP input event %p for skb %p done", inE, skb); } } else if (info->name == LTT_EVENT_UDPV4_RCV_EXTENDED) @@ -608,15 +556,16 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) inE->type= UDP; inE->event.udpEvent= malloc(sizeof(UDPEvent)); + inE->copy= ©UDPEvent; inE->destroy= &destroyUDPEvent; inE->event.udpEvent->direction= IN; inE->event.udpEvent->datagramKey= malloc(sizeof(DatagramKey)); inE->event.udpEvent->datagramKey->saddr= - ltt_event_get_unsigned(event, - lttv_trace_get_hook_field(traceHook, 1)); + htonl(ltt_event_get_unsigned(event, + lttv_trace_get_hook_field(traceHook, 1))); inE->event.udpEvent->datagramKey->daddr= - ltt_event_get_unsigned(event, - lttv_trace_get_hook_field(traceHook, 2)); + htonl(ltt_event_get_unsigned(event, + lttv_trace_get_hook_field(traceHook, 2))); inE->event.udpEvent->unicast= ltt_event_get_unsigned(event, lttv_trace_get_hook_field(traceHook, 3)) == 0 ? false : true; inE->event.udpEvent->datagramKey->ulen= @@ -648,7 +597,7 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) syncState->matchingModule->matchEvent(syncState, inE); - g_debug("UDP input event %p for skb %p done\n", inE, skb); + g_debug("UDP input event %p for skb %p done", inE, skb); } } else @@ -661,59 +610,67 @@ static gboolean processEventLTTVStandard(void* hookData, void* callData) /* - * Write the processing-specific graph lines in the gnuplot script (none at - * the moment). Call the downstream module's graph function. + * Write the processing-specific variables in the gnuplot script. * * Args: - * stream: stream where to write the data * syncState: container for synchronization data - * i: first trace number - * j: second trace number, garanteed to be larger than i + * i: trace number */ -static void writeProcessingGraphsPlotsLTTVStandard(FILE* stream, SyncState* - const syncState, const unsigned int i, const unsigned int j) +static void writeProcessingGraphVariablesLTTVStandard(SyncState* const + syncState, const unsigned int i) { - if (syncState->matchingModule->writeMatchingGraphsPlots != NULL) - { - syncState->matchingModule->writeMatchingGraphsPlots(stream, syncState, - i, j); - } + ProcessingDataLTTVStandard* processingData= syncState->processingData; + ProcessingGraphsLTTVStandard* traceI= &processingData->graphs[i]; + + fprintf(syncState->graphsStream, "clock_freq_%u= %.3f\n", i, (double) + traceI->startFreq / traceI->freqScale); } /* - * Write the processing-specific options in the gnuplot script. Call the - * downstream module's options function. + * Write the processing-specific options in the gnuplot script. * * Args: - * stream: stream where to write the data * syncState: container for synchronization data * i: first trace number * j: second trace number, garanteed to be larger than i */ -static void writeProcessingGraphsOptionsLTTVStandard(FILE* stream, SyncState* - const syncState, const unsigned int i, const unsigned int j) +static void writeProcessingTraceTraceOptionsLTTVStandard(SyncState* const + syncState, const unsigned int i, const unsigned int j) { - ProcessingDataLTTVStandard* processingData; - LttTrace* traceI, * traceJ; - - processingData= (ProcessingDataLTTVStandard*) syncState->processingData; - - traceI= processingData->traceSetContext->traces[i]->t; - traceJ= processingData->traceSetContext->traces[j]->t; - - fprintf(stream, + fprintf(syncState->graphsStream, + "set key inside right bottom\n" + "set xlabel \"Clock %1$u\"\n" + "set xtics nomirror\n" + "set ylabel \"Clock %2$u\"\n" + "set ytics nomirror\n" "set x2label \"Clock %1$d (s)\"\n" - "set x2range [GPVAL_X_MIN / %2$.1f : GPVAL_X_MAX / %2$.1f]\n" + "set x2range [GPVAL_X_MIN / clock_freq_%1$u : GPVAL_X_MAX / clock_freq_%1$u]\n" "set x2tics\n" - "set y2label \"Clock %3$d (s)\"\n" - "set y2range [GPVAL_Y_MIN / %4$.1f : GPVAL_Y_MAX / %4$.1f]\n" - "set y2tics\n", i, (double) traceI->start_freq / traceI->freq_scale, - j, (double) traceJ->start_freq / traceJ->freq_scale); + "set y2label \"Clock %2$d (s)\"\n" + "set y2range [GPVAL_Y_MIN / clock_freq_%2$u : GPVAL_Y_MAX / clock_freq_%2$u]\n" + "set y2tics\n", i, j); +} - if (syncState->matchingModule->writeMatchingGraphsOptions != NULL) - { - syncState->matchingModule->writeMatchingGraphsOptions(stream, - syncState, i, j); - } + +/* + * Write the processing-specific options in the gnuplot script. + * + * Args: + * syncState: container for synchronization data + * i: first trace number + * j: second trace number, garanteed to be larger than i + */ +static void writeProcessingTraceTimeOptionsLTTVStandard(SyncState* const + syncState, const unsigned int i, const unsigned int j) +{ + fprintf(syncState->graphsStream, + "set key inside right bottom\n" + "set xlabel \"Clock %1$u\"\n" + "set xtics nomirror\n" + "set ylabel \"time (s)\"\n" + "set ytics nomirror\n" + "set x2label \"Clock %1$d (s)\"\n" + "set x2range [GPVAL_X_MIN / clock_freq_%1$u : GPVAL_X_MAX / clock_freq_%1$u]\n" + "set x2tics\n", i); }