From: dagenais Date: Wed, 14 Apr 2004 18:35:19 +0000 (+0000) Subject: Add reference counts to state and stats saved attributes. This way, the X-Git-Tag: v0.12.20~2989 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=f95bc8309fe113855266f4445874248b6a285062;p=lttv.git Add reference counts to state and stats saved attributes. This way, the information can be shared among several contexts using the same trace but is freed when all contexts are "finished". Summing statistics is now done separately to permit more reuse for trace statistics (same trace in several tracesets). The statistics viewer does not yet call this. Use a more generic lttv_attribute_write_xml xml writer to save stats. Place the .h files along with their base package instead of in a separate include tree. git-svn-id: http://ltt.polymtl.ca/svn@500 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/ltt/branches/poly/configure.in b/ltt/branches/poly/configure.in index 47baf9d2..193f3414 100644 --- a/ltt/branches/poly/configure.in +++ b/ltt/branches/poly/configure.in @@ -109,7 +109,6 @@ AC_CONFIG_FILES([Makefile lttd/Makefile ltt/Makefile include/Makefile - include/ltt/Makefile ltt/convert/Makefile include/lttv/Makefile]) AC_OUTPUT diff --git a/ltt/branches/poly/include/Makefile.am b/ltt/branches/poly/include/Makefile.am index fdd2bdb6..1a1d52d1 100644 --- a/ltt/branches/poly/include/Makefile.am +++ b/ltt/branches/poly/include/Makefile.am @@ -1 +1 @@ -SUBDIRS = ltt lttv +SUBDIRS = lttv diff --git a/ltt/branches/poly/include/ltt/Makefile.am b/ltt/branches/poly/include/ltt/Makefile.am deleted file mode 100644 index 2ffd9244..00000000 --- a/ltt/branches/poly/include/ltt/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -lttinclude_HEADERS = \ - event.h\ - facility.h\ - ltt.h\ - time.h\ - trace.h\ - type.h diff --git a/ltt/branches/poly/include/ltt/event.h b/ltt/branches/poly/include/ltt/event.h deleted file mode 100644 index 4cee9713..00000000 --- a/ltt/branches/poly/include/ltt/event.h +++ /dev/null @@ -1,124 +0,0 @@ -/* This file is part of the Linux Trace Toolkit trace reading library - * Copyright (C) 2003-2004 Michel Dagenais - * - * 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 EVENT_H -#define EVENT_H - -#include - -/* Events and their content, including the raw data, are only valid - until reading another event from the same tracefile. - Indeed, since event reading is critical to the performance, - the memory associated with an event may be reused at each read. */ - - -/* Obtain the trace unique integer id associated with the type of - this event */ - -unsigned ltt_event_eventtype_id(LttEvent *e); - - -/* Facility and type for the event */ - -LttFacility *ltt_event_facility(LttEvent *e); - -LttEventType *ltt_event_eventtype(LttEvent *e); - - -/* Root field for the event */ - -LttField *ltt_event_field(LttEvent *e); - - -/* Time and cycle count for the event */ - -LttTime ltt_event_time(LttEvent *e); - -LttCycleCount ltt_event_cycle_count(LttEvent *e); - - -/* Obtain the position of the event within the tracefile. This - is used to seek back to this position later or to seek to another - position, computed relative to this position. The event position - structure is opaque and contains several fields, only two - of which are user accessible: block number and event index - within the block. */ - -void ltt_event_position(LttEvent *e, LttEventPosition *ep); - -LttEventPosition * ltt_event_position_new(); - -void ltt_event_position_get(LttEventPosition *ep, - unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf); - -void ltt_event_position_set(LttEventPosition *ep, - unsigned block_number, unsigned index_in_block); - - -/* CPU id of the event */ - -unsigned ltt_event_cpu_id(LttEvent *e); - - -/* Pointer to the raw data for the event. This should not be used directly - unless prepared to do all the architecture specific conversions. */ - -void *ltt_event_data(LttEvent *e); - - -/* The number of elements in a sequence field is specific to each event - instance. This function returns the number of elements for an array or - sequence field in an event. */ - -unsigned ltt_event_field_element_number(LttEvent *e, LttField *f); - - -/* Set the currently selected element for a sequence or array field. */ - -void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i); - - -/* A union is like a structure except that only a single member at a time - is present depending on the specific event instance. This function tells - the active member for a union field in an event. */ - -unsigned ltt_event_field_union_member(LttEvent *e, LttField *f); - - -/* These functions extract data from an event after architecture specific - conversions. */ - -unsigned ltt_event_get_unsigned(LttEvent *e, LttField *f); - -int ltt_event_get_int(LttEvent *e, LttField *f); - -unsigned long ltt_event_get_long_unsigned(LttEvent *e, LttField *f); - -long int ltt_event_get_long_int(LttEvent *e, LttField *f); - -float ltt_event_get_float(LttEvent *e, LttField *f); - -double ltt_event_get_double(LttEvent *e, LttField *f); - - -/* The string obtained is only valid until the next read from - the same tracefile. */ - -char *ltt_event_get_string(LttEvent *e, LttField *f); - -#endif // EVENT_H diff --git a/ltt/branches/poly/include/ltt/facility.h b/ltt/branches/poly/include/ltt/facility.h deleted file mode 100644 index 8fda81e9..00000000 --- a/ltt/branches/poly/include/ltt/facility.h +++ /dev/null @@ -1,49 +0,0 @@ -/* This file is part of the Linux Trace Toolkit trace reading library - * Copyright (C) 2003-2004 Michel Dagenais - * - * 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 FACILITY_H -#define FACILITY_H - -#include - -/* Facilities are obtained from an opened trace. The structures associated - with a facility are released when the trace is closed. Each facility - is characterized by its name and checksum. */ - -char *ltt_facility_name(LttFacility *f); - -LttChecksum ltt_facility_checksum(LttFacility *f); - -/* open facility */ -void ltt_facility_open(LttTrace * t, char * facility_name); - -/* Discover the event types within the facility. The event type integer id - relative to the trace is from 0 to nb_event_types - 1. The event - type id within the trace is the relative id + the facility base event - id. */ - -unsigned ltt_facility_base_id(LttFacility *f); - -unsigned ltt_facility_eventtype_number(LttFacility *f); - -LttEventType *ltt_facility_eventtype_get(LttFacility *f, unsigned i); - -LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, char *name); - -#endif // FACILITY_H - diff --git a/ltt/branches/poly/include/ltt/ltt.h b/ltt/branches/poly/include/ltt/ltt.h deleted file mode 100644 index 0aa413bd..00000000 --- a/ltt/branches/poly/include/ltt/ltt.h +++ /dev/null @@ -1,133 +0,0 @@ -/* This file is part of the Linux Trace Toolkit trace reading library - * Copyright (C) 2003-2004 Michel Dagenais - * - * 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_H -#define LTT_H - -#include -#include - -/* A trace is associated with a tracing session run on a single, possibly - multi-cpu, system. It is defined as a pathname to a directory containing - all the relevant trace files. All the tracefiles for a trace were - generated in a single system for the same time period by the same - trace daemon. They simply contain different events. Typically control - tracefiles contain the important events (process creations and registering - tracing facilities) for all CPUs, and one file for each CPU contains all - the events for that CPU. All the tracefiles within the same trace directory - then use the exact same id numbers for event types. - - A tracefile (LttTracefile) contains a list of events (LttEvent) sorted - by time for each CPU; events from different CPUs may be slightly out of - order, especially using the (possibly drifting) cycle counters as - time unit. - - A facility is a list of event types (LttEventType), declared in a special - eventdefs file. A corresponding checksum differentiates different - facilities which would have the same name but a different content - (e.g., different versions). The files are stored within the trace - directory and are accessed automatically upon opening a trace. - The list of facilities (and associated checksum) used in a trace - must be known in order to properly decode the contained events. An event - is stored in the "facilities" control tracefile to denote each different - facility used. - - Event types (LttEventType) refer to data types (LttType) describing - their content. The data types supported are integer and unsigned integer - (of various length), enumerations (a special form of unsigned integer), - floating point (of various length), fixed size arrays, sequence - (variable sized arrays), structures and null terminated strings. - The elements of arrays and sequences, and the data members for - structures, may be of any nested data type (LttType). - - An LttField is a special object to denote a specific, possibly nested, - field within an event type. Suppose an event type socket_connect is a - structure containing two data members, source and destination, of type - socket_address. Type socket_address contains two unsigned integer - data members, ip and port. An LttField is different from a data type - structure member since it can denote a specific nested field, like the - source port, and store associated access information (byte offset within - the event data). The LttField objects are trace specific since the - contained information (byte offsets) may vary with the architecture - associated to the trace. */ - -typedef struct _LttTrace LttTrace; - -typedef struct _LttTracefile LttTracefile; - -typedef struct _LttFacility LttFacility; - -typedef struct _LttEventType LttEventType; - -typedef struct _LttType LttType; - -typedef struct _LttField LttField; - -typedef struct _LttEvent LttEvent; - -typedef struct _LttSystemDescription LttSystemDescription; - -/* Checksums are used to differentiate facilities which have the same name - but differ. */ - -typedef unsigned long LttChecksum; - - -/* Events are usually stored with the easily obtained CPU clock cycle count, - ltt_cycle_count. This can be converted to the real time value, LttTime, - using linear interpolation between regularly sampled values (e.g. a few - times per second) of the real time clock with their corresponding - cycle count values. */ - - -typedef struct _TimeInterval{ - LttTime startTime; - LttTime endTime; -} TimeInterval; - - -typedef guint64 LttCycleCount; - - -/* Event positions are used to seek within a tracefile based on - the block number and event position within the block. */ - -typedef struct _LttEventPosition LttEventPosition; - - -/* Differences between architectures include word sizes, endianess, - alignment, floating point format and calling conventions. For a - packed binary trace, endianess and size matter, assuming that the - floating point format is standard (and is seldom used anyway). */ - -typedef enum _LttArchSize -{ LTT_LP32, LTT_ILP32, LTT_LP64, LTT_ILP64, LTT_UNKNOWN -} LttArchSize; - - -typedef enum _LttArchEndian -{ LTT_LITTLE_ENDIAN, LTT_BIG_ENDIAN -} LttArchEndian; - -typedef enum _LttTypeEnum -{ LTT_INT, LTT_UINT, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY, - LTT_SEQUENCE, LTT_STRUCT, LTT_UNION -} LttTypeEnum; - - -#endif // LTT_H diff --git a/ltt/branches/poly/include/ltt/time.h b/ltt/branches/poly/include/ltt/time.h deleted file mode 100644 index 2cce2760..00000000 --- a/ltt/branches/poly/include/ltt/time.h +++ /dev/null @@ -1,123 +0,0 @@ -/* This file is part of the Linux Trace Toolkit trace reading library - * Copyright (C) 2003-2004 Michel Dagenais - * - * 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 - - -typedef struct _LttTime { - unsigned long tv_sec; - unsigned long tv_nsec; -} LttTime; - - -static const unsigned long NANOSECONDS_PER_SECOND = 1000000000; - -static const LttTime ltt_time_zero = { 0, 0}; - - -static inline LttTime ltt_time_sub(LttTime t1, LttTime t2) -{ - LttTime res; - res.tv_sec = t1.tv_sec - t2.tv_sec; - if(t1.tv_nsec < t2.tv_nsec) { - res.tv_sec--; - res.tv_nsec = NANOSECONDS_PER_SECOND + t1.tv_nsec - t2.tv_nsec; - } - else { - res.tv_nsec = t1.tv_nsec - t2.tv_nsec; - } - return res; -} - - -static inline LttTime ltt_time_add(LttTime t1, LttTime t2) -{ - LttTime res; - res.tv_sec = t1.tv_sec + t2.tv_sec; - res.tv_nsec = t1.tv_nsec + t2.tv_nsec; - if(res.tv_nsec >= NANOSECONDS_PER_SECOND) { - res.tv_sec++; - res.tv_nsec -= NANOSECONDS_PER_SECOND; - } - return res; -} - - -static inline LttTime ltt_time_mul(LttTime t1, float f) -{ - LttTime res; - float d; - double sec; - - if(f == 0.0){ - res.tv_sec = 0; - res.tv_nsec = 0; - }else{ - d = 1.0/f; - sec = t1.tv_sec / (double)d; - res.tv_sec = sec; - res.tv_nsec = t1.tv_nsec / (double)d + (sec - res.tv_sec) * - NANOSECONDS_PER_SECOND; - res.tv_sec += res.tv_nsec / NANOSECONDS_PER_SECOND; - res.tv_nsec %= NANOSECONDS_PER_SECOND; - } - return res; -} - - -static inline LttTime ltt_time_div(LttTime t1, float f) -{ - double sec; - LttTime res; - - sec = t1.tv_sec / (double)f; - res.tv_sec = sec; - res.tv_nsec = t1.tv_nsec / (double)f + (sec - res.tv_sec) * - NANOSECONDS_PER_SECOND; - res.tv_sec += res.tv_nsec / NANOSECONDS_PER_SECOND; - res.tv_nsec %= NANOSECONDS_PER_SECOND; - return res; -} - - -static inline int ltt_time_compare(LttTime t1, LttTime t2) -{ - if(t1.tv_sec > t2.tv_sec) return 1; - if(t1.tv_sec < t2.tv_sec) return -1; - if(t1.tv_nsec > t2.tv_nsec) return 1; - if(t1.tv_nsec < t2.tv_nsec) return -1; - return 0; -} - - -static inline double ltt_time_to_double(LttTime t1) -{ - return (double)t1.tv_sec + (double)t1.tv_nsec / NANOSECONDS_PER_SECOND; -} - - -static inline LttTime ltt_time_from_double(double t1) -{ - LttTime res; - res.tv_sec = t1; - res.tv_nsec = (t1 - res.tv_sec) * NANOSECONDS_PER_SECOND; - return res; -} - -#endif // LTT_TIME_H diff --git a/ltt/branches/poly/include/ltt/trace.h b/ltt/branches/poly/include/ltt/trace.h deleted file mode 100644 index 2b3f8533..00000000 --- a/ltt/branches/poly/include/ltt/trace.h +++ /dev/null @@ -1,167 +0,0 @@ -/* This file is part of the Linux Trace Toolkit trace reading library - * Copyright (C) 2003-2004 Michel Dagenais - * - * 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 TRACE_H -#define TRACE_H - -#include - -/* A trace is specified as a pathname to the directory containing all the - associated data (control tracefiles, per cpu tracefiles, event - descriptions...). - - When a trace is closed, all the associated facilities, types and fields - are released as well. */ - -LttTrace *ltt_trace_open(const char *pathname); - -/* copy reopens a trace */ -LttTrace *ltt_trace_copy(LttTrace *self); - -char * ltt_trace_name(LttTrace *t); - -void ltt_trace_close(LttTrace *t); - - -LttSystemDescription *ltt_trace_system_description(LttTrace *t); - - -/* Functions to discover the facilities in the trace. Once the number - of facilities is known, they may be accessed by position. Multiple - versions of a facility (same name, different checksum) have consecutive - positions. */ - -unsigned ltt_trace_facility_number(LttTrace *t); - -LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i); - -LttFacility * ltt_trace_facility_by_id(LttTrace * trace, unsigned id); - -/* Look for a facility by name. It returns the number of facilities found - and sets the position argument to the first found. Returning 0, the named - facility is unknown, returning 1, the named facility is at the specified - position, returning n, the facilities are from position to - position + n - 1. */ - -unsigned ltt_trace_facility_find(LttTrace *t, char *name, unsigned *position); - - -/* Functions to discover all the event types in the trace */ - -unsigned ltt_trace_eventtype_number(LttTrace *t); - -LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned i); - - -/* There is one "per cpu" tracefile for each CPU, numbered from 0 to - the maximum number of CPU in the system. When the number of CPU installed - is less than the maximum, some positions are unused. There are also a - number of "control" tracefiles (facilities, interrupts...). */ - -unsigned ltt_trace_control_tracefile_number(LttTrace *t); - -unsigned ltt_trace_per_cpu_tracefile_number(LttTrace *t); - - -/* It is possible to search for the tracefiles by name or by CPU position. - The index within the tracefiles of the same type is returned if found - and a negative value otherwise. */ - -int ltt_trace_control_tracefile_find(LttTrace *t, char *name); - -int ltt_trace_per_cpu_tracefile_find(LttTrace *t, unsigned i); - - -/* Get a specific tracefile */ - -LttTracefile *ltt_trace_control_tracefile_get(LttTrace *t, unsigned i); - -LttTracefile *ltt_trace_per_cpu_tracefile_get(LttTrace *t, unsigned i); - - -/* Get the start time and end time of the trace */ - -void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end); - - -/* Get the name of a tracefile */ - -char *ltt_tracefile_name(LttTracefile *tf); - - -/* Get the number of blocks in the tracefile */ - -unsigned ltt_tracefile_block_number(LttTracefile *tf); - - -/* Seek to the first event of the trace with time larger or equal to time */ - -void ltt_tracefile_seek_time(LttTracefile *t, LttTime time); - -/* Seek to the first event with position equal or larger to ep */ - -void ltt_tracefile_seek_position(LttTracefile *t, - LttEventPosition *ep); - -/* Read the next event */ - -LttEvent *ltt_tracefile_read(LttTracefile *t); - -/* open tracefile */ - -LttTracefile * ltt_tracefile_open(LttTrace *t, char * tracefile_name); - -void ltt_tracefile_open_cpu(LttTrace *t, char * tracefile_name); - -void ltt_tracefile_open_control(LttTrace *t, char * control_name); - - -/* obtain the time of an event */ - -LttTime getEventTime(LttTracefile * tf); - - -/* get the data type size and endian type of the local machine */ - -void getDataEndianType(LttArchSize * size, LttArchEndian * endian); - -/* get an integer number */ - -int getIntNumber(int size1, void *evD); - - -/* get the node name of the system */ - -char * ltt_trace_system_description_node_name (LttSystemDescription * s); - - -/* get the domain name of the system */ - -char * ltt_trace_system_description_domain_name (LttSystemDescription * s); - - -/* get the description of the system */ - -char * ltt_trace_system_description_description (LttSystemDescription * s); - - -/* get the start time of the trace */ - -LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s); - -#endif // TRACE_H diff --git a/ltt/branches/poly/include/ltt/type.h b/ltt/branches/poly/include/ltt/type.h deleted file mode 100644 index 91828126..00000000 --- a/ltt/branches/poly/include/ltt/type.h +++ /dev/null @@ -1,102 +0,0 @@ -/* This file is part of the Linux Trace Toolkit trace reading library - * Copyright (C) 2003-2004 Michel Dagenais - * - * 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 TYPE_H -#define TYPE_H - - -/* Different types allowed */ - -#include - - -/* All event types, data types and fields belong to their trace and - are released at the same time. */ - -/* Obtain the name, description, facility, facility relative id, global id, - type and root field for an eventtype */ - -char *ltt_eventtype_name(LttEventType *et); - -char *ltt_eventtype_description(LttEventType *et); - -LttFacility *ltt_eventtype_facility(LttEventType *et); - -unsigned ltt_eventtype_relative_id(LttEventType *et); - -unsigned ltt_eventtype_id(LttEventType *et); - -LttType *ltt_eventtype_type(LttEventType *et); - -LttField *ltt_eventtype_field(LttEventType *et); - - -/* obtain the type name and size. The size is the number of bytes for - primitive types (INT, UINT, FLOAT, ENUM), or the size for the unsigned - integer length count for sequences. */ - -char *ltt_type_name(LttType *t); - -LttTypeEnum ltt_type_class(LttType *t); - -unsigned ltt_type_size(LttTrace *trace, LttType *t); - - -/* The type of nested elements for arrays and sequences. */ - -LttType *ltt_type_element_type(LttType *t); - - -/* The number of elements for arrays. */ - -unsigned ltt_type_element_number(LttType *t); - - -/* The number of data members for structures and unions. */ - -unsigned ltt_type_member_number(LttType *t); - - -/* The type of a data member in a structure. */ - -LttType *ltt_type_member_type(LttType *t, unsigned i, char ** name); - - -/* For enumerations, obtain the symbolic string associated with a value - (0 to n - 1 for an enumeration of n elements). */ - -char *ltt_enum_string_get(LttType *t, unsigned i); - - -/* The fields form a tree representing a depth first search of the - corresponding event type directed acyclic graph. Fields for arrays and - sequences simply point to one nested field representing the currently - selected element among all the (identically typed) elements. For structures, - a nested field exists for each data member. Each field stores the - platform/trace specific offset values (for efficient access) and - points back to the corresponding LttType for the rest. */ - -LttField *ltt_field_element(LttField *f); - -LttField *ltt_field_member(LttField *f, unsigned i); - -LttType *ltt_field_type(LttField *f); - -int ltt_field_size(LttField * f); - -#endif // TYPE_H diff --git a/ltt/branches/poly/include/lttv/attribute.h b/ltt/branches/poly/include/lttv/attribute.h index dedae373..e721b3bf 100644 --- a/ltt/branches/poly/include/lttv/attribute.h +++ b/ltt/branches/poly/include/lttv/attribute.h @@ -21,6 +21,7 @@ #include #include +#include #define LTTV_ATTRIBUTE_TYPE (lttv_attribute_get_type ()) #define LTTV_ATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_ATTRIBUTE_TYPE, LttvAttribute)) @@ -112,4 +113,9 @@ void lttv_attribute_recursive_free(LttvAttribute *self); void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src); +void +lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent); + +void lttv_attribute_read_xml(LttvAttribute *self, FILE *fp); + #endif // ATTRIBUTE_H diff --git a/ltt/branches/poly/include/lttv/gtktraceset.h b/ltt/branches/poly/include/lttv/gtktraceset.h index 392e3205..19035482 100644 --- a/ltt/branches/poly/include/lttv/gtktraceset.h +++ b/ltt/branches/poly/include/lttv/gtktraceset.h @@ -16,6 +16,34 @@ * MA 02111-1307, USA. */ +/* +CHECK Rename to viewer.h + +Things that can happen to a viewer: + +update_time_window +update_current_time +update_traceset +update_filter +show_viewer +update_dividor +?? Reshape, damage ?? + +Things that a viewer can do: + +update_status +set_time_window +set_current_time +update_traceset? +update_filter? +show_viewer? +set_focused_pane +set_hpane_dividor +*/ + + + + /*! \file gtktraceset.h * \brief API used by the graphical viewers to interact with their top window. * @@ -350,6 +378,10 @@ void unreg_update_dividor(LttvHook hook, gpointer hook_data, void set_hpane_dividor(MainWindow *main_win, gint position); +/* +CHECK These functions really should not appear here. Directr calls would +be OK unless there is a linker problem. +*/ /** * Function to process traceset. It will call lttv_process_trace, * each view will call this api to get events. diff --git a/ltt/branches/poly/include/lttv/state.h b/ltt/branches/poly/include/lttv/state.h index fb2fa998..85b90498 100644 --- a/ltt/branches/poly/include/lttv/state.h +++ b/ltt/branches/poly/include/lttv/state.h @@ -214,7 +214,7 @@ void lttv_state_save(LttvTraceState *self, LttvAttribute *container); void lttv_state_restore(LttvTraceState *self, LttvAttribute *container); -void lttv_state_saved_state_free(LttvTraceState *self, +void lttv_state_state_saved_free(LttvTraceState *self, LttvAttribute *container); diff --git a/ltt/branches/poly/include/lttv/stats.h b/ltt/branches/poly/include/lttv/stats.h index ad941ad3..37d36945 100644 --- a/ltt/branches/poly/include/lttv/stats.h +++ b/ltt/branches/poly/include/lttv/stats.h @@ -150,9 +150,9 @@ gboolean lttv_stats_add_event_hooks(LttvTracesetStats *self); gboolean lttv_stats_remove_event_hooks(LttvTracesetStats *self); -void lttv_stats_save_statistics(LttvTracesetStats *self); +void lttv_stats_sum_traceset(LttvTracesetStats *self); -gboolean lttv_stats_load_statistics(LttvTracesetStats *self); +void lttv_stats_sum_trace(LttvTraceStats *self); /* The LttvTracesetStats, LttvTraceStats and LttvTracefileStats types diff --git a/ltt/branches/poly/ltt/Makefile.am b/ltt/branches/poly/ltt/Makefile.am index 92e4dcef..cc5eed55 100644 --- a/ltt/branches/poly/ltt/Makefile.am +++ b/ltt/branches/poly/ltt/Makefile.am @@ -15,5 +15,12 @@ lib_LTLIBRARIES = libtraceread.la libtraceread_la_SOURCES = event.c facility.c parser.c tracefile.c type.c noinst_HEADERS = parser.h ltt-private.h +lttinclude_HEADERS = \ + event.h\ + facility.h\ + ltt.h\ + time.h\ + trace.h\ + type.h EXTRA_DIST = crc32.tab diff --git a/ltt/branches/poly/ltt/event.h b/ltt/branches/poly/ltt/event.h new file mode 100644 index 00000000..4cee9713 --- /dev/null +++ b/ltt/branches/poly/ltt/event.h @@ -0,0 +1,124 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * 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 EVENT_H +#define EVENT_H + +#include + +/* Events and their content, including the raw data, are only valid + until reading another event from the same tracefile. + Indeed, since event reading is critical to the performance, + the memory associated with an event may be reused at each read. */ + + +/* Obtain the trace unique integer id associated with the type of + this event */ + +unsigned ltt_event_eventtype_id(LttEvent *e); + + +/* Facility and type for the event */ + +LttFacility *ltt_event_facility(LttEvent *e); + +LttEventType *ltt_event_eventtype(LttEvent *e); + + +/* Root field for the event */ + +LttField *ltt_event_field(LttEvent *e); + + +/* Time and cycle count for the event */ + +LttTime ltt_event_time(LttEvent *e); + +LttCycleCount ltt_event_cycle_count(LttEvent *e); + + +/* Obtain the position of the event within the tracefile. This + is used to seek back to this position later or to seek to another + position, computed relative to this position. The event position + structure is opaque and contains several fields, only two + of which are user accessible: block number and event index + within the block. */ + +void ltt_event_position(LttEvent *e, LttEventPosition *ep); + +LttEventPosition * ltt_event_position_new(); + +void ltt_event_position_get(LttEventPosition *ep, + unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf); + +void ltt_event_position_set(LttEventPosition *ep, + unsigned block_number, unsigned index_in_block); + + +/* CPU id of the event */ + +unsigned ltt_event_cpu_id(LttEvent *e); + + +/* Pointer to the raw data for the event. This should not be used directly + unless prepared to do all the architecture specific conversions. */ + +void *ltt_event_data(LttEvent *e); + + +/* The number of elements in a sequence field is specific to each event + instance. This function returns the number of elements for an array or + sequence field in an event. */ + +unsigned ltt_event_field_element_number(LttEvent *e, LttField *f); + + +/* Set the currently selected element for a sequence or array field. */ + +void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i); + + +/* A union is like a structure except that only a single member at a time + is present depending on the specific event instance. This function tells + the active member for a union field in an event. */ + +unsigned ltt_event_field_union_member(LttEvent *e, LttField *f); + + +/* These functions extract data from an event after architecture specific + conversions. */ + +unsigned ltt_event_get_unsigned(LttEvent *e, LttField *f); + +int ltt_event_get_int(LttEvent *e, LttField *f); + +unsigned long ltt_event_get_long_unsigned(LttEvent *e, LttField *f); + +long int ltt_event_get_long_int(LttEvent *e, LttField *f); + +float ltt_event_get_float(LttEvent *e, LttField *f); + +double ltt_event_get_double(LttEvent *e, LttField *f); + + +/* The string obtained is only valid until the next read from + the same tracefile. */ + +char *ltt_event_get_string(LttEvent *e, LttField *f); + +#endif // EVENT_H diff --git a/ltt/branches/poly/ltt/facility.h b/ltt/branches/poly/ltt/facility.h new file mode 100644 index 00000000..8fda81e9 --- /dev/null +++ b/ltt/branches/poly/ltt/facility.h @@ -0,0 +1,49 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * 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 FACILITY_H +#define FACILITY_H + +#include + +/* Facilities are obtained from an opened trace. The structures associated + with a facility are released when the trace is closed. Each facility + is characterized by its name and checksum. */ + +char *ltt_facility_name(LttFacility *f); + +LttChecksum ltt_facility_checksum(LttFacility *f); + +/* open facility */ +void ltt_facility_open(LttTrace * t, char * facility_name); + +/* Discover the event types within the facility. The event type integer id + relative to the trace is from 0 to nb_event_types - 1. The event + type id within the trace is the relative id + the facility base event + id. */ + +unsigned ltt_facility_base_id(LttFacility *f); + +unsigned ltt_facility_eventtype_number(LttFacility *f); + +LttEventType *ltt_facility_eventtype_get(LttFacility *f, unsigned i); + +LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, char *name); + +#endif // FACILITY_H + diff --git a/ltt/branches/poly/ltt/ltt.h b/ltt/branches/poly/ltt/ltt.h new file mode 100644 index 00000000..0aa413bd --- /dev/null +++ b/ltt/branches/poly/ltt/ltt.h @@ -0,0 +1,133 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * 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_H +#define LTT_H + +#include +#include + +/* A trace is associated with a tracing session run on a single, possibly + multi-cpu, system. It is defined as a pathname to a directory containing + all the relevant trace files. All the tracefiles for a trace were + generated in a single system for the same time period by the same + trace daemon. They simply contain different events. Typically control + tracefiles contain the important events (process creations and registering + tracing facilities) for all CPUs, and one file for each CPU contains all + the events for that CPU. All the tracefiles within the same trace directory + then use the exact same id numbers for event types. + + A tracefile (LttTracefile) contains a list of events (LttEvent) sorted + by time for each CPU; events from different CPUs may be slightly out of + order, especially using the (possibly drifting) cycle counters as + time unit. + + A facility is a list of event types (LttEventType), declared in a special + eventdefs file. A corresponding checksum differentiates different + facilities which would have the same name but a different content + (e.g., different versions). The files are stored within the trace + directory and are accessed automatically upon opening a trace. + The list of facilities (and associated checksum) used in a trace + must be known in order to properly decode the contained events. An event + is stored in the "facilities" control tracefile to denote each different + facility used. + + Event types (LttEventType) refer to data types (LttType) describing + their content. The data types supported are integer and unsigned integer + (of various length), enumerations (a special form of unsigned integer), + floating point (of various length), fixed size arrays, sequence + (variable sized arrays), structures and null terminated strings. + The elements of arrays and sequences, and the data members for + structures, may be of any nested data type (LttType). + + An LttField is a special object to denote a specific, possibly nested, + field within an event type. Suppose an event type socket_connect is a + structure containing two data members, source and destination, of type + socket_address. Type socket_address contains two unsigned integer + data members, ip and port. An LttField is different from a data type + structure member since it can denote a specific nested field, like the + source port, and store associated access information (byte offset within + the event data). The LttField objects are trace specific since the + contained information (byte offsets) may vary with the architecture + associated to the trace. */ + +typedef struct _LttTrace LttTrace; + +typedef struct _LttTracefile LttTracefile; + +typedef struct _LttFacility LttFacility; + +typedef struct _LttEventType LttEventType; + +typedef struct _LttType LttType; + +typedef struct _LttField LttField; + +typedef struct _LttEvent LttEvent; + +typedef struct _LttSystemDescription LttSystemDescription; + +/* Checksums are used to differentiate facilities which have the same name + but differ. */ + +typedef unsigned long LttChecksum; + + +/* Events are usually stored with the easily obtained CPU clock cycle count, + ltt_cycle_count. This can be converted to the real time value, LttTime, + using linear interpolation between regularly sampled values (e.g. a few + times per second) of the real time clock with their corresponding + cycle count values. */ + + +typedef struct _TimeInterval{ + LttTime startTime; + LttTime endTime; +} TimeInterval; + + +typedef guint64 LttCycleCount; + + +/* Event positions are used to seek within a tracefile based on + the block number and event position within the block. */ + +typedef struct _LttEventPosition LttEventPosition; + + +/* Differences between architectures include word sizes, endianess, + alignment, floating point format and calling conventions. For a + packed binary trace, endianess and size matter, assuming that the + floating point format is standard (and is seldom used anyway). */ + +typedef enum _LttArchSize +{ LTT_LP32, LTT_ILP32, LTT_LP64, LTT_ILP64, LTT_UNKNOWN +} LttArchSize; + + +typedef enum _LttArchEndian +{ LTT_LITTLE_ENDIAN, LTT_BIG_ENDIAN +} LttArchEndian; + +typedef enum _LttTypeEnum +{ LTT_INT, LTT_UINT, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY, + LTT_SEQUENCE, LTT_STRUCT, LTT_UNION +} LttTypeEnum; + + +#endif // LTT_H diff --git a/ltt/branches/poly/ltt/time.h b/ltt/branches/poly/ltt/time.h new file mode 100644 index 00000000..2cce2760 --- /dev/null +++ b/ltt/branches/poly/ltt/time.h @@ -0,0 +1,123 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * 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 + + +typedef struct _LttTime { + unsigned long tv_sec; + unsigned long tv_nsec; +} LttTime; + + +static const unsigned long NANOSECONDS_PER_SECOND = 1000000000; + +static const LttTime ltt_time_zero = { 0, 0}; + + +static inline LttTime ltt_time_sub(LttTime t1, LttTime t2) +{ + LttTime res; + res.tv_sec = t1.tv_sec - t2.tv_sec; + if(t1.tv_nsec < t2.tv_nsec) { + res.tv_sec--; + res.tv_nsec = NANOSECONDS_PER_SECOND + t1.tv_nsec - t2.tv_nsec; + } + else { + res.tv_nsec = t1.tv_nsec - t2.tv_nsec; + } + return res; +} + + +static inline LttTime ltt_time_add(LttTime t1, LttTime t2) +{ + LttTime res; + res.tv_sec = t1.tv_sec + t2.tv_sec; + res.tv_nsec = t1.tv_nsec + t2.tv_nsec; + if(res.tv_nsec >= NANOSECONDS_PER_SECOND) { + res.tv_sec++; + res.tv_nsec -= NANOSECONDS_PER_SECOND; + } + return res; +} + + +static inline LttTime ltt_time_mul(LttTime t1, float f) +{ + LttTime res; + float d; + double sec; + + if(f == 0.0){ + res.tv_sec = 0; + res.tv_nsec = 0; + }else{ + d = 1.0/f; + sec = t1.tv_sec / (double)d; + res.tv_sec = sec; + res.tv_nsec = t1.tv_nsec / (double)d + (sec - res.tv_sec) * + NANOSECONDS_PER_SECOND; + res.tv_sec += res.tv_nsec / NANOSECONDS_PER_SECOND; + res.tv_nsec %= NANOSECONDS_PER_SECOND; + } + return res; +} + + +static inline LttTime ltt_time_div(LttTime t1, float f) +{ + double sec; + LttTime res; + + sec = t1.tv_sec / (double)f; + res.tv_sec = sec; + res.tv_nsec = t1.tv_nsec / (double)f + (sec - res.tv_sec) * + NANOSECONDS_PER_SECOND; + res.tv_sec += res.tv_nsec / NANOSECONDS_PER_SECOND; + res.tv_nsec %= NANOSECONDS_PER_SECOND; + return res; +} + + +static inline int ltt_time_compare(LttTime t1, LttTime t2) +{ + if(t1.tv_sec > t2.tv_sec) return 1; + if(t1.tv_sec < t2.tv_sec) return -1; + if(t1.tv_nsec > t2.tv_nsec) return 1; + if(t1.tv_nsec < t2.tv_nsec) return -1; + return 0; +} + + +static inline double ltt_time_to_double(LttTime t1) +{ + return (double)t1.tv_sec + (double)t1.tv_nsec / NANOSECONDS_PER_SECOND; +} + + +static inline LttTime ltt_time_from_double(double t1) +{ + LttTime res; + res.tv_sec = t1; + res.tv_nsec = (t1 - res.tv_sec) * NANOSECONDS_PER_SECOND; + return res; +} + +#endif // LTT_TIME_H diff --git a/ltt/branches/poly/ltt/trace.h b/ltt/branches/poly/ltt/trace.h new file mode 100644 index 00000000..2b3f8533 --- /dev/null +++ b/ltt/branches/poly/ltt/trace.h @@ -0,0 +1,167 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * 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 TRACE_H +#define TRACE_H + +#include + +/* A trace is specified as a pathname to the directory containing all the + associated data (control tracefiles, per cpu tracefiles, event + descriptions...). + + When a trace is closed, all the associated facilities, types and fields + are released as well. */ + +LttTrace *ltt_trace_open(const char *pathname); + +/* copy reopens a trace */ +LttTrace *ltt_trace_copy(LttTrace *self); + +char * ltt_trace_name(LttTrace *t); + +void ltt_trace_close(LttTrace *t); + + +LttSystemDescription *ltt_trace_system_description(LttTrace *t); + + +/* Functions to discover the facilities in the trace. Once the number + of facilities is known, they may be accessed by position. Multiple + versions of a facility (same name, different checksum) have consecutive + positions. */ + +unsigned ltt_trace_facility_number(LttTrace *t); + +LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i); + +LttFacility * ltt_trace_facility_by_id(LttTrace * trace, unsigned id); + +/* Look for a facility by name. It returns the number of facilities found + and sets the position argument to the first found. Returning 0, the named + facility is unknown, returning 1, the named facility is at the specified + position, returning n, the facilities are from position to + position + n - 1. */ + +unsigned ltt_trace_facility_find(LttTrace *t, char *name, unsigned *position); + + +/* Functions to discover all the event types in the trace */ + +unsigned ltt_trace_eventtype_number(LttTrace *t); + +LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned i); + + +/* There is one "per cpu" tracefile for each CPU, numbered from 0 to + the maximum number of CPU in the system. When the number of CPU installed + is less than the maximum, some positions are unused. There are also a + number of "control" tracefiles (facilities, interrupts...). */ + +unsigned ltt_trace_control_tracefile_number(LttTrace *t); + +unsigned ltt_trace_per_cpu_tracefile_number(LttTrace *t); + + +/* It is possible to search for the tracefiles by name or by CPU position. + The index within the tracefiles of the same type is returned if found + and a negative value otherwise. */ + +int ltt_trace_control_tracefile_find(LttTrace *t, char *name); + +int ltt_trace_per_cpu_tracefile_find(LttTrace *t, unsigned i); + + +/* Get a specific tracefile */ + +LttTracefile *ltt_trace_control_tracefile_get(LttTrace *t, unsigned i); + +LttTracefile *ltt_trace_per_cpu_tracefile_get(LttTrace *t, unsigned i); + + +/* Get the start time and end time of the trace */ + +void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end); + + +/* Get the name of a tracefile */ + +char *ltt_tracefile_name(LttTracefile *tf); + + +/* Get the number of blocks in the tracefile */ + +unsigned ltt_tracefile_block_number(LttTracefile *tf); + + +/* Seek to the first event of the trace with time larger or equal to time */ + +void ltt_tracefile_seek_time(LttTracefile *t, LttTime time); + +/* Seek to the first event with position equal or larger to ep */ + +void ltt_tracefile_seek_position(LttTracefile *t, + LttEventPosition *ep); + +/* Read the next event */ + +LttEvent *ltt_tracefile_read(LttTracefile *t); + +/* open tracefile */ + +LttTracefile * ltt_tracefile_open(LttTrace *t, char * tracefile_name); + +void ltt_tracefile_open_cpu(LttTrace *t, char * tracefile_name); + +void ltt_tracefile_open_control(LttTrace *t, char * control_name); + + +/* obtain the time of an event */ + +LttTime getEventTime(LttTracefile * tf); + + +/* get the data type size and endian type of the local machine */ + +void getDataEndianType(LttArchSize * size, LttArchEndian * endian); + +/* get an integer number */ + +int getIntNumber(int size1, void *evD); + + +/* get the node name of the system */ + +char * ltt_trace_system_description_node_name (LttSystemDescription * s); + + +/* get the domain name of the system */ + +char * ltt_trace_system_description_domain_name (LttSystemDescription * s); + + +/* get the description of the system */ + +char * ltt_trace_system_description_description (LttSystemDescription * s); + + +/* get the start time of the trace */ + +LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s); + +#endif // TRACE_H diff --git a/ltt/branches/poly/ltt/type.h b/ltt/branches/poly/ltt/type.h new file mode 100644 index 00000000..91828126 --- /dev/null +++ b/ltt/branches/poly/ltt/type.h @@ -0,0 +1,102 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * 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 TYPE_H +#define TYPE_H + + +/* Different types allowed */ + +#include + + +/* All event types, data types and fields belong to their trace and + are released at the same time. */ + +/* Obtain the name, description, facility, facility relative id, global id, + type and root field for an eventtype */ + +char *ltt_eventtype_name(LttEventType *et); + +char *ltt_eventtype_description(LttEventType *et); + +LttFacility *ltt_eventtype_facility(LttEventType *et); + +unsigned ltt_eventtype_relative_id(LttEventType *et); + +unsigned ltt_eventtype_id(LttEventType *et); + +LttType *ltt_eventtype_type(LttEventType *et); + +LttField *ltt_eventtype_field(LttEventType *et); + + +/* obtain the type name and size. The size is the number of bytes for + primitive types (INT, UINT, FLOAT, ENUM), or the size for the unsigned + integer length count for sequences. */ + +char *ltt_type_name(LttType *t); + +LttTypeEnum ltt_type_class(LttType *t); + +unsigned ltt_type_size(LttTrace *trace, LttType *t); + + +/* The type of nested elements for arrays and sequences. */ + +LttType *ltt_type_element_type(LttType *t); + + +/* The number of elements for arrays. */ + +unsigned ltt_type_element_number(LttType *t); + + +/* The number of data members for structures and unions. */ + +unsigned ltt_type_member_number(LttType *t); + + +/* The type of a data member in a structure. */ + +LttType *ltt_type_member_type(LttType *t, unsigned i, char ** name); + + +/* For enumerations, obtain the symbolic string associated with a value + (0 to n - 1 for an enumeration of n elements). */ + +char *ltt_enum_string_get(LttType *t, unsigned i); + + +/* The fields form a tree representing a depth first search of the + corresponding event type directed acyclic graph. Fields for arrays and + sequences simply point to one nested field representing the currently + selected element among all the (identically typed) elements. For structures, + a nested field exists for each data member. Each field stores the + platform/trace specific offset values (for efficient access) and + points back to the corresponding LttType for the rest. */ + +LttField *ltt_field_element(LttField *f); + +LttField *ltt_field_member(LttField *f, unsigned i); + +LttType *ltt_field_type(LttField *f); + +int ltt_field_size(LttField * f); + +#endif // TYPE_H diff --git a/ltt/branches/poly/lttv/main/attribute.c b/ltt/branches/poly/lttv/main/attribute.c index fcdc8329..a3f8ab9a 100644 --- a/ltt/branches/poly/lttv/main/attribute.c +++ b/ltt/branches/poly/lttv/main/attribute.c @@ -307,6 +307,167 @@ void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src) } +static void +print_indent(FILE *fp, int pos) +{ + int i; + + for(i = 0 ; i < pos ; i++) putc(' ', fp); +} + + +void +lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent) +{ + int i, nb; + + Attribute *a; + + nb = self->attributes->len; + + fprintf(fp,"\n"); + for(i = 0 ; i < nb ; i++) { + a = &g_array_index(self->attributes, Attribute, i); + print_indent(fp, pos); + fprintf(fp, "name); + if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { + fprintf(fp, "TYPE=ATTRS>"); + lttv_attribute_write_xml((LttvAttribute *)(a->value.dv_gobject), fp, + pos + indent, indent); + } + else { + switch(a->type) { + case LTTV_INT: + fprintf(fp, "TYPE=INT VALUE=%d/>\n", a->value.dv_int); + break; + case LTTV_UINT: + fprintf(fp, "TYPE=UINT VALUE=%u/>\n", a->value.dv_uint); + break; + case LTTV_LONG: + fprintf(fp, "TYPE=LONG VALUE=%ld/>\n", a->value.dv_long); + break; + case LTTV_ULONG: + fprintf(fp, "TYPE=ULONG VALUE=%lu/>\n", a->value.dv_ulong); + break; + case LTTV_FLOAT: + fprintf(fp, "TYPE=FLOAT VALUE=%f/>\n", a->value.dv_float); + break; + case LTTV_DOUBLE: + fprintf(fp, "TYPE=DOUBLE VALUE=%f/>\n", a->value.dv_double); + break; + case LTTV_TIME: + fprintf(fp, "TYPE=TIME SEC=%u NSEC=%u/>\n", a->value.dv_time.tv_sec, + a->value.dv_time.tv_nsec); + break; + case LTTV_POINTER: + fprintf(fp, "TYPE=POINTER VALUE=%p/>\n", a->value.dv_pointer); + break; + case LTTV_STRING: + fprintf(fp, "TYPE=STRING VALUE=\"%s\"/>\n", a->value.dv_string); + break; + case LTTV_GOBJECT: + fprintf(fp, "TYPE=GOBJECT VALUE=%p/>\n", a->value.dv_gobject); + break; + case LTTV_NONE: + fprintf(fp, "TYPE=NONE/>\n"); + break; + } + } + } + print_indent(fp, pos); + fprintf(fp,"\n"); +} + + +void +lttv_attribute_read_xml(LttvAttribute *self, FILE *fp) +{ + int i, nb, res; + + Attribute *a; + + char buffer[256], type[10]; + + LttvAttributeName name; + + LttvAttributeValue value; + + LttvAttribute *subtree; + + fscanf(fp,""); + while(1) { + res = fscanf(fp, "]", buffer, type); + g_assert(res == 2); + name = g_quark_from_string(buffer); + if(strcmp(type, "ATTRS") == 0) { + fscanf(fp, ">"); + subtree = lttv_attribute_find_subdir(self, name); + lttv_attribute_read_xml(subtree, fp); + } + else if(strcmp(type, "INT") == 0) { + value = lttv_attribute_add(self, name, LTTV_INT); + res = fscanf(fp, " VALUE=%d/>", value.v_int); + g_assert(res == 1); + } + else if(strcmp(type, "UINT") == 0) { + value = lttv_attribute_add(self, name, LTTV_UINT); + res = fscanf(fp, " VALUE=%u/>", value.v_uint); + g_assert(res == 1); + } + else if(strcmp(type, "LONG") == 0) { + value = lttv_attribute_add(self, name, LTTV_LONG); + res = fscanf(fp, " VALUE=%ld/>", value.v_long); + g_assert(res == 1); + } + else if(strcmp(type, "ULONG") == 0) { + value = lttv_attribute_add(self, name, LTTV_ULONG); + res = fscanf(fp, " VALUE=%lu/>", value.v_ulong); + g_assert(res == 1); + } + else if(strcmp(type, "FLOAT") == 0) { + float d; + value = lttv_attribute_add(self, name, LTTV_FLOAT); + res = fscanf(fp, " VALUE=%f/>", &d); + *(value.v_float) = d; + g_assert(res == 1); + } + else if(strcmp(type, "DOUBLE") == 0) { + value = lttv_attribute_add(self, name, LTTV_DOUBLE); + res = fscanf(fp, " VALUE=%f/>", value.v_double); + g_assert(res == 1); + } + else if(strcmp(type, "TIME") == 0) { + value = lttv_attribute_add(self, name, LTTV_TIME); + res = fscanf(fp, " SEC=%u NSEC=%u/>", &(value.v_time->tv_sec), + &(value.v_time->tv_nsec)); + g_assert(res == 2); + } + else if(strcmp(type, "POINTER") == 0) { + value = lttv_attribute_add(self, name, LTTV_POINTER); + res = fscanf(fp, " VALUE=%p/>", value.v_pointer); + g_error("Cannot read a pointer"); + } + else if(strcmp(type, "STRING") == 0) { + value = lttv_attribute_add(self, name, LTTV_STRING); + res = fscanf(fp, " VALUE=\"%256[^\"]\"/>", buffer); + *(value.v_string) = g_strdup(buffer); + g_assert(res == 1); + } + else if(strcmp(type, "GOBJECT") == 0) { + value = lttv_attribute_add(self, name, LTTV_GOBJECT); + res = fscanf(fp, " VALUE=%p/>", value.v_gobject); + g_error("Cannot read a pointer"); + } + else if(strcmp(type, "NONE") == 0) { + value = lttv_attribute_add(self, name, LTTV_NONE); + fscanf(fp, "/>"); + } + else g_error("Unknown type to read"); + } + fscanf(fp,""); +} + + static void attribute_interface_init (gpointer g_iface, gpointer iface_data) { diff --git a/ltt/branches/poly/lttv/main/processTrace.c b/ltt/branches/poly/lttv/main/processTrace.c index c811da0e..cb50c0a3 100644 --- a/ltt/branches/poly/lttv/main/processTrace.c +++ b/ltt/branches/poly/lttv/main/processTrace.c @@ -564,7 +564,20 @@ lttv_tracefile_context_get_type(void) gint compare_tracefile(gconstpointer a, gconstpointer b) { - return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); + gint comparison; + + LttvTracefileContext *trace_a = (LttvTracefileContext *)a; + + LttvTracefileContext *trace_b = (LttvTracefileContext *)b; + + if(trace_a == trace_b) return 0; + comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp); + if(comparison != 0) return comparison; + if(trace_a->index < trace_b->index) return -1; + else if(trace_a->index > trace_b->index) return 1; + if(trace_a->t_context->index < trace_b->t_context->index) return -1; + else if(trace_a->t_context->index > trace_b->t_context->index) return 1; + g_assert(FALSE); } @@ -608,7 +621,7 @@ void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end) if(tfc->timestamp.tv_sec < end.tv_sec || (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)) { - g_tree_insert(self->pqueue, &(tfc->timestamp), tfc); + g_tree_insert(self->pqueue, tfc, tfc); } } } @@ -660,8 +673,7 @@ guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end, or more tracefiles have events for the same time, hope that lookup and remove are consistent. */ - tfc = g_tree_lookup(pqueue, &(tfc->timestamp)); - g_tree_remove(pqueue, &(tfc->timestamp)); + g_tree_remove(pqueue, tfc); count++; if(!lttv_hooks_call(tfc->check_event, tfc)) { @@ -678,7 +690,7 @@ guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end, tfc->timestamp = ltt_event_time(event); if(tfc->timestamp.tv_sec < end.tv_sec || (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)) - g_tree_insert(pqueue, &(tfc->timestamp), tfc); + g_tree_insert(pqueue, tfc, tfc); } } } diff --git a/ltt/branches/poly/lttv/main/state.c b/ltt/branches/poly/lttv/main/state.c index c69d6a6a..0624fe4b 100644 --- a/ltt/branches/poly/lttv/main/state.c +++ b/ltt/branches/poly/lttv/main/state.c @@ -24,6 +24,7 @@ #include #include #include +#include LttvExecutionMode LTTV_STATE_MODE_UNKNOWN, @@ -52,13 +53,25 @@ static GQuark LTTV_STATE_SAVED_STATES, LTTV_STATE_SAVED_STATES_TIME, LTTV_STATE_TIME, - LTTV_STATE_HOOKS; + LTTV_STATE_HOOKS, + LTTV_STATE_NAME_TABLES, + LTTV_STATE_TRACE_STATE_USE_COUNT; -static void fill_name_tables(LttvTraceState *tcs); +static void create_max_time(LttvTraceState *tcs); + +static void get_max_time(LttvTraceState *tcs); + +static void free_max_time(LttvTraceState *tcs); + +static void create_name_tables(LttvTraceState *tcs); + +static void get_name_tables(LttvTraceState *tcs); static void free_name_tables(LttvTraceState *tcs); +static void free_saved_state(LttvTraceState *tcs); + static void lttv_state_free_process_table(GHashTable *processes); @@ -74,10 +87,10 @@ void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) } -void lttv_state_saved_state_free(LttvTraceState *self, +void lttv_state__state_saved_free(LttvTraceState *self, LttvAttribute *container) { - LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); + LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container); } @@ -150,15 +163,16 @@ init(LttvTracesetState *self, LttvTraceset *ts) tc = self->parent.traces[i]; tcs = (LttvTraceState *)tc; tcs->save_interval = 50000; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, - LTTV_POINTER, &v); - if(*(v.v_pointer) == NULL) { - *(v.v_pointer) = g_new(LttTime,1); - *((LttTime *)*(v.v_pointer)) = time_zero; - } - tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer); + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT, + LTTV_UINT, &v); + (*v.v_uint)++; - fill_name_tables(tcs); + if(*(v.v_uint) == 1) { + create_name_tables(tcs); + create_max_time(tcs); + } + get_name_tables(tcs); + get_max_time(tcs); nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + ltt_trace_per_cpu_tracefile_number(tc->t); @@ -182,12 +196,23 @@ fini(LttvTracesetState *self) LttvTracefileState *tfcs; + 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); + (*v.v_uint)--; + + g_assert(*(v.v_uint) >= 0); + if(*(v.v_uint) == 0) { + free_name_tables(tcs); + free_max_time(tcs); + free_saved_state(tcs); + } lttv_state_free_process_table(tcs->processes); tcs->processes = NULL; - free_name_tables(tcs); } LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> fini((LttvTracesetContext *)self); @@ -230,8 +255,8 @@ static void write_process_state(gpointer key, gpointer value, process = (LttvProcessState *)value; fprintf(fp, -" \n", - process->pid, process->ppid, process->creation_time.tv_sec, +" \n", + process, process->pid, process->ppid, process->creation_time.tv_sec, process->creation_time.tv_nsec, g_quark_to_string(process->name), g_quark_to_string(process->last_cpu)); @@ -476,8 +501,80 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) } +static void free_saved_state(LttvTraceState *self) +{ + guint i, nb; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttvAttribute *saved_states; + + saved_states = lttv_attribute_find_subdir(self->parent.t_a, + 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); + g_assert(type == LTTV_GOBJECT); + state_saved_free(self, *((LttvAttribute **)value.v_gobject)); + } + + lttv_attribute_remove_by_name(self->parent.t_a, LTTV_STATE_SAVED_STATES); + lttv_attribute_recursive_free(saved_states); +} + + +static void +create_max_time(LttvTraceState *tcs) +{ + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + LTTV_POINTER, &v); + g_assert(*(v.v_pointer) == NULL); + *(v.v_pointer) = g_new(LttTime,1); + *((LttTime *)*(v.v_pointer)) = time_zero; +} + + +static void +get_max_time(LttvTraceState *tcs) +{ + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, 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); +} + + +static void +free_max_time(LttvTraceState *tcs) +{ + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + LTTV_POINTER, &v); + g_free(*(v.v_pointer)); + *(v.v_pointer) = NULL; +} + + +typedef struct _LttvNameTables { + GQuark *eventtype_names; + GQuark *syscall_names; + GQuark *trap_names; + GQuark *irq_names; +} LttvNameTables; + + static void -fill_name_tables(LttvTraceState *tcs) +create_name_tables(LttvTraceState *tcs) { int i, nb; @@ -491,14 +588,23 @@ fill_name_tables(LttvTraceState *tcs) GString *fe_name = g_string_new(""); + LttvNameTables *name_tables = g_new(LttvNameTables, 1); + + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + LTTV_POINTER, &v); + g_assert(*(v.v_pointer) == NULL); + *(v.v_pointer) = name_tables; + nb = ltt_trace_eventtype_number(tcs->parent.t); - tcs->eventtype_names = g_new(GQuark, nb); + name_tables->eventtype_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { et = ltt_trace_eventtype_get(tcs->parent.t, i); e_name = ltt_eventtype_name(et); f_name = ltt_facility_name(ltt_eventtype_facility(et)); g_string_printf(fe_name, "%s.%s", f_name, e_name); - tcs->eventtype_names[i] = g_quark_from_string(fe_name->str); + name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str); } lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry", @@ -507,17 +613,18 @@ fill_name_tables(LttvTraceState *tcs) nb = ltt_type_element_number(t); /* CHECK syscalls should be an emun but currently are not! - tcs->syscall_names = g_new(GQuark, nb); + name_tables->syscall_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { - tcs->syscall_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + name_tables->syscall_names[i] = g_quark_from_string( + ltt_enum_string_get(t, i)); } */ - tcs->syscall_names = g_new(GQuark, 256); + name_tables->syscall_names = g_new(GQuark, 256); for(i = 0 ; i < 256 ; i++) { g_string_printf(fe_name, "syscall %d", i); - tcs->syscall_names[i] = g_quark_from_string(fe_name->str); + name_tables->syscall_names[i] = g_quark_from_string(fe_name->str); } lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry", @@ -526,16 +633,17 @@ fill_name_tables(LttvTraceState *tcs) nb = ltt_type_element_number(t); /* - tcs->trap_names = g_new(GQuark, nb); + name_tables->trap_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { - tcs->trap_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + name_tables->trap_names[i] = g_quark_from_string( + ltt_enum_string_get(t, i)); } */ - tcs->trap_names = g_new(GQuark, 256); + name_tables->trap_names = g_new(GQuark, 256); for(i = 0 ; i < 256 ; i++) { g_string_printf(fe_name, "trap %d", i); - tcs->trap_names[i] = g_quark_from_string(fe_name->str); + name_tables->trap_names[i] = g_quark_from_string(fe_name->str); } lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry", @@ -544,29 +652,57 @@ fill_name_tables(LttvTraceState *tcs) nb = ltt_type_element_number(t); /* - tcs->irq_names = g_new(GQuark, nb); + name_tables->irq_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { - tcs->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); } */ - tcs->irq_names = g_new(GQuark, 256); + name_tables->irq_names = g_new(GQuark, 256); for(i = 0 ; i < 256 ; i++) { g_string_printf(fe_name, "irq %d", i); - tcs->irq_names[i] = g_quark_from_string(fe_name->str); + name_tables->irq_names[i] = g_quark_from_string(fe_name->str); } g_string_free(fe_name, TRUE); } +static void +get_name_tables(LttvTraceState *tcs) +{ + LttvNameTables *name_tables; + + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + LTTV_POINTER, &v); + g_assert(*(v.v_pointer) != NULL); + name_tables = (LttvNameTables *)*(v.v_pointer); + tcs->eventtype_names = name_tables->eventtype_names; + tcs->syscall_names = name_tables->syscall_names; + tcs->trap_names = name_tables->trap_names; + tcs->irq_names = name_tables->irq_names; +} + + static void free_name_tables(LttvTraceState *tcs) { - g_free(tcs->eventtype_names); - g_free(tcs->syscall_names); - g_free(tcs->trap_names); - g_free(tcs->irq_names); + LttvNameTables *name_tables; + + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + LTTV_POINTER, &v); + name_tables = (LttvNameTables *)*(v.v_pointer); + *(v.v_pointer) = NULL; + + g_free(name_tables->eventtype_names); + g_free(name_tables->syscall_names); + g_free(name_tables->trap_names); + g_free(name_tables->irq_names); + g_free(name_tables); } @@ -593,7 +729,7 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) { LttvProcessState *process = tfs->process; - guint depth = process->execution_stack->len - 1; + guint depth = process->execution_stack->len; if(process->state->t != t){ g_info("Different execution mode type (%d.%09d): ignore it\n", @@ -609,16 +745,15 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) return; } - if(depth == 0){ + if(depth == 1){ g_info("Trying to pop last state on stack (%d.%09d): ignore it\n", tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); return; } - g_array_remove_index(process->execution_stack, depth); - depth--; + g_array_set_size(process->execution_stack, depth - 1); process->state = &g_array_index(process->execution_stack, LttvExecutionState, - depth); + depth - 2); process->state->change = tfs->parent.timestamp; } @@ -637,10 +772,11 @@ lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent, char buffer[128]; - tcs = (LttvTraceState *)tc = tfs->parent.t_context; + tcs = ((LttvTraceState *)tc = tfs->parent.t_context); process->pid = pid; process->last_cpu = tfs->cpu_name; + g_warning("Process %u, core %p", process->pid, process); g_hash_table_insert(tcs->processes, process, process); if(parent) { @@ -825,14 +961,21 @@ static gboolean schedchange(void *hook_data, void *call_data) if(s->process != NULL) { + /* We could not know but it was not the idle process executing. + This should only happen at the beginning, before the first schedule + event, and when the initial information (current process for each CPU) + is missing. It is not obvious how we could, after the fact, compensate + the wrongly attributed statistics. */ + + if(s->process->pid != pid_out) { + g_assert(s->process->pid == 0); + } + if(state_out == 0) s->process->state->s = LTTV_STATE_WAIT_CPU; else if(s->process->state->s == LTTV_STATE_EXIT) exit_process(s, s->process); else s->process->state->s = LTTV_STATE_WAIT; - if(s->process->pid == 0) - s->process->pid = pid_out; - s->process->state->change = s->parent.timestamp; } s->process = lttv_state_find_process_or_create(s, pid_in); @@ -1175,7 +1318,9 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) } /* restore the closest earlier saved state */ - if(min_pos != -1) lttv_state_restore(tcs, closest_tree); + if(min_pos != -1) { + lttv_state_restore(tcs, closest_tree); + } /* There is no saved state, yet we want to have it. Restart at T0 */ else { @@ -1364,6 +1509,9 @@ static void module_init() LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time"); LTTV_STATE_TIME = g_quark_from_string("time"); LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks"); + LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables"); + LTTV_STATE_TRACE_STATE_USE_COUNT = + g_quark_from_string("trace_state_use_count"); } static void module_destroy() diff --git a/ltt/branches/poly/lttv/main/stats.c b/ltt/branches/poly/lttv/main/stats.c index c577ab77..d5cd80b4 100644 --- a/ltt/branches/poly/lttv/main/stats.c +++ b/ltt/branches/poly/lttv/main/stats.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,11 @@ GQuark LTTV_STATS_CPU_TIME, LTTV_STATS_ELAPSED_TIME, LTTV_STATS_EVENTS, - LTTV_STATS_EVENTS_COUNT; + LTTV_STATS_EVENTS_COUNT, + LTTV_STATS_USE_COUNT, + LTTV_STATS, + LTTV_STATS_TRACEFILES, + LTTV_STATS_SUMMED; static GQuark LTTV_STATS_BEFORE_HOOKS, @@ -66,22 +71,47 @@ init(LttvTracesetStats *self, LttvTraceset *ts) LttTime timestamp = {0,0}; + LttvAttributeValue v; + + LttvAttribute + *stats_tree, + *tracefiles_stats; + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> init((LttvTracesetContext *)self, ts); - self->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + self->stats =lttv_attribute_find_subdir(self->parent.parent.ts_a,LTTV_STATS); + lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT, + LTTV_UINT, &v); + + *(v.v_uint)++; + if(*(v.v_uint) == 1) { + g_assert(lttv_attribute_get_number(self->stats) == 0); + } + nb_trace = lttv_traceset_number(ts); for(i = 0 ; i < nb_trace ; i++) { tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); - tcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + + tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS); + tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a, + LTTV_STATS_TRACEFILES); + lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT, + LTTV_UINT, &v); + + *(v.v_uint)++; + if(*(v.v_uint) == 1) { + g_assert(lttv_attribute_get_number(tcs->stats) == 0); + } nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + ltt_trace_per_cpu_tracefile_number(tc->t); for(j = 0 ; j < nb_tracefile ; j++) { tfcs = LTTV_TRACEFILE_STATS(tc->tracefiles[j]); - tfcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats, + tfcs->parent.cpu_name); find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN, tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN, LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree, @@ -108,20 +138,47 @@ fini(LttvTracesetStats *self) LttTime timestamp = {0,0}; - lttv_attribute_recursive_free(self->stats); + LttvAttributeValue v; + + LttvAttribute *tracefiles_stats; + + lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT, + LTTV_UINT, &v); + *(v.v_uint)--; + + if(*(v.v_uint) == 0) { + lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS); + lttv_attribute_recursive_free(self->stats); + } + self->stats = NULL; + ts = self->parent.parent.ts; nb_trace = lttv_traceset_number(ts); for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); - lttv_attribute_recursive_free(tcs->stats); + tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i])); + + lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT, + LTTV_UINT, &v); + *(v.v_uint)--; + + if(*(v.v_uint) == 0) { + lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS); + lttv_attribute_recursive_free(tcs->stats); + tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a, + LTTV_STATS_TRACEFILES); + lttv_attribute_remove_by_name(tcs->parent.parent.t_a, + LTTV_STATS_TRACEFILES); + lttv_attribute_recursive_free(tracefiles_stats); + } + tcs->stats = NULL; nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + ltt_trace_per_cpu_tracefile_number(tc->t); for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = (LttvTracefileStats *)tfc = tc->tracefiles[j]; - lttv_attribute_recursive_free(tfcs->stats); + tfcs = ((LttvTracefileStats *)tfc = tc->tracefiles[j]); + tfcs->stats = NULL; tfcs->current_events_tree = NULL; tfcs->current_event_types_tree = NULL; } @@ -516,15 +573,11 @@ gboolean every_event(void *hook_data, void *call_data) } -static gboolean -sum_stats(void *hook_data, void *call_data) +void +lttv_stats_sum_trace(LttvTraceStats *self) { - LttvTracesetStats *tscs = (LttvTracesetStats *)call_data; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - LttvAttributeType type; LttvAttributeValue value; @@ -533,86 +586,115 @@ sum_stats(void *hook_data, void *call_data) unsigned sum; - int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode, + int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode, nb_event_type; LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, *submode_tree, *event_types_tree, *mode_events_tree, *cpu_events_tree, *process_modes_tree, *trace_cpu_tree, - *trace_modes_tree, *traceset_modes_tree; - - traceset_modes_tree = lttv_attribute_find_subdir(tscs->stats, - LTTV_STATS_MODES); - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - main_tree = tcs->stats; - processes_tree = lttv_attribute_find_subdir(main_tree, - LTTV_STATS_PROCESSES); - trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); - nb_process = lttv_attribute_get_number(processes_tree); - - for(j = 0 ; j < nb_process ; j++) { - type = lttv_attribute_get(processes_tree, j, &name, &value); - process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + *trace_modes_tree; + + main_tree = self->stats; + + lttv_attribute_find(self->parent.parent.t_a, LTTV_STATS_SUMMED, + LTTV_UINT, &value); + if(*(value.v_uint) != 0) return; + *(value.v_uint) = 1; + + processes_tree = lttv_attribute_find_subdir(main_tree, + LTTV_STATS_PROCESSES); + trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); + nb_process = lttv_attribute_get_number(processes_tree); + + for(i = 0 ; i < nb_process ; i++) { + type = lttv_attribute_get(processes_tree, i, &name, &value); + process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); + process_modes_tree = lttv_attribute_find_subdir(process_tree, + LTTV_STATS_MODES); + nb_cpu = lttv_attribute_get_number(cpus_tree); + + for(j = 0 ; j < nb_cpu ; j++) { + type = lttv_attribute_get(cpus_tree, j, &name, &value); + cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + mode_types_tree = lttv_attribute_find_subdir(cpu_tree, + LTTV_STATS_MODE_TYPES); + cpu_events_tree = lttv_attribute_find_subdir(cpu_tree, + LTTV_STATS_EVENTS); + trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU); + trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name); + nb_mode_type = lttv_attribute_get_number(mode_types_tree); + + for(k = 0 ; k < nb_mode_type ; k++) { + type = lttv_attribute_get(mode_types_tree, k, &name, &value); + mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + submodes_tree = lttv_attribute_find_subdir(mode_tree, + LTTV_STATS_SUBMODES); + mode_events_tree = lttv_attribute_find_subdir(mode_tree, + LTTV_STATS_EVENTS); + nb_submode = lttv_attribute_get_number(submodes_tree); - cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); - process_modes_tree = lttv_attribute_find_subdir(process_tree, - LTTV_STATS_MODES); - nb_cpu = lttv_attribute_get_number(cpus_tree); + for(l = 0 ; l < nb_submode ; l++) { + type = lttv_attribute_get(submodes_tree, l, &name, &value); + submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - for(k = 0 ; k < nb_cpu ; k++) { - type = lttv_attribute_get(cpus_tree, k, &name, &value); - cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + event_types_tree = lttv_attribute_find_subdir(submode_tree, + LTTV_STATS_EVENT_TYPES); + nb_event_type = lttv_attribute_get_number(event_types_tree); - mode_types_tree = lttv_attribute_find_subdir(cpu_tree, - LTTV_STATS_MODE_TYPES); - cpu_events_tree = lttv_attribute_find_subdir(cpu_tree, - LTTV_STATS_EVENTS); - trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU); - trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name); - nb_mode_type = lttv_attribute_get_number(mode_types_tree); - - for(l = 0 ; l < nb_mode_type ; l++) { - type = lttv_attribute_get(mode_types_tree, l, &name, &value); - mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - submodes_tree = lttv_attribute_find_subdir(mode_tree, - LTTV_STATS_SUBMODES); - mode_events_tree = lttv_attribute_find_subdir(mode_tree, - LTTV_STATS_EVENTS); - nb_submode = lttv_attribute_get_number(submodes_tree); - - for(m = 0 ; m < nb_submode ; m++) { - type = lttv_attribute_get(submodes_tree, m, &name, &value); - submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - event_types_tree = lttv_attribute_find_subdir(submode_tree, - LTTV_STATS_EVENT_TYPES); - nb_event_type = lttv_attribute_get_number(event_types_tree); - - sum = 0; - for(n = 0 ; n < nb_event_type ; n++) { - type = lttv_attribute_get(event_types_tree, n, &name, &value); - sum += *(value.v_uint); - } - lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT, - LTTV_UINT, &value); - *(value.v_uint) = sum; - lttv_attribute_recursive_add(mode_events_tree, submode_tree); + sum = 0; + for(m = 0 ; m < nb_event_type ; m++) { + type = lttv_attribute_get(event_types_tree, m, &name, &value); + sum += *(value.v_uint); } - lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree); + lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT, + LTTV_UINT, &value); + *(value.v_uint) = sum; + lttv_attribute_recursive_add(mode_events_tree, submode_tree); } - lttv_attribute_recursive_add(process_modes_tree, cpu_tree); - lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree); + lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree); } - lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree); + lttv_attribute_recursive_add(process_modes_tree, cpu_tree); + lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree); } + lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree); + } +} + + +void +lttv_stats_sum_traceset(LttvTracesetStats *self) +{ + LttvTraceset *traceset = self->parent.parent.ts; + + LttvTraceStats *tcs; + + int i, nb_trace; + + LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree; + + LttvAttributeValue value; + + lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_SUMMED, + LTTV_UINT, &value); + if(*(value.v_uint) != 0) return; + *(value.v_uint) = 1; + + traceset_modes_tree = lttv_attribute_find_subdir(self->stats, + LTTV_STATS_MODES); + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)(self->parent.parent.traces[i]); + lttv_stats_sum_trace(tcs); + main_tree = tcs->stats; + trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree); } - return FALSE; } @@ -736,7 +818,6 @@ lttv_stats_add_event_hooks(LttvTracesetStats *self) LTTV_POINTER, &val); *(val.v_pointer) = after_hooks; } - lttv_hooks_add(self->parent.parent.after, sum_stats, NULL); } @@ -795,361 +876,6 @@ lttv_stats_remove_event_hooks(LttvTracesetStats *self) g_array_free(before_hooks, TRUE); g_array_free(after_hooks, TRUE); } - lttv_hooks_remove_data(self->parent.parent.after, sum_stats, NULL); -} - - -void lttv_stats_save_attribute(LttvAttribute *attr, char *indent, FILE * fp) -{ - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - char type_value[BUF_SIZE]; - int i, nb_attr, flag; - - nb_attr = lttv_attribute_get_number(attr); - for(i=0;itv_sec, - value.v_time->tv_nsec); - break; - case LTTV_POINTER: - sprintf(type_value, "POINTER\0"); - break; - case LTTV_STRING: - sprintf(type_value, "%s\0", *value.v_string); - break; - default: - flag = 0; - break; - } - if(flag == 0) continue; - fprintf(fp,"%s",indent,type,g_quark_to_string(name)); - fprintf(fp,"%s",type_value); - fprintf(fp," \n"); - } - -} - -void lttv_stats_save_statistics(LttvTracesetStats *self) -{ - LttvTracesetStats *tscs = self; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - - char filename[BUF_SIZE]; - FILE * fp; - char indent[10][24]= {" ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " - }; - - - int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode; - - LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, - *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, - *submode_tree, *event_types_tree; - - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - - filename[0] = '\0'; - strcat(filename,ltt_trace_name(tcs->parent.parent.t)); - strcat(filename,"/statistics.xml"); - fp = fopen(filename,"w"); - if(!fp){ - g_warning("can not open the file %s for saving statistics\n", filename); - exit(1); - } - - main_tree = tcs->stats; - processes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_PROCESSES); - nb_process = lttv_attribute_get_number(processes_tree); - - fprintf(fp, " \n",g_quark_to_string(LTTV_STATS_PROCESSES)); //root NODE - - for(j = 0 ; j < nb_process ; j++) { - type = lttv_attribute_get(processes_tree, j, &name, &value); - process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[0],g_quark_to_string(name)); //process NODE - lttv_stats_save_attribute(process_tree,indent[1], fp); - fprintf(fp,"%s \n", indent[1],g_quark_to_string(LTTV_STATS_CPU)); //cpus NODE - - cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); - nb_cpu = lttv_attribute_get_number(cpus_tree); - - for(k = 0 ; k < nb_cpu ; k++) { - type = lttv_attribute_get(cpus_tree, k, &name, &value); - cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[2],g_quark_to_string(name)); //cpu NODE - lttv_stats_save_attribute(cpu_tree,indent[3], fp); - fprintf(fp,"%s \n",indent[3],g_quark_to_string(LTTV_STATS_MODE_TYPES)); //mode_types NODE - - mode_types_tree = lttv_attribute_find_subdir(cpu_tree,LTTV_STATS_MODE_TYPES); - nb_mode_type = lttv_attribute_get_number(mode_types_tree); - - for(l = 0 ; l < nb_mode_type ; l++) { - type = lttv_attribute_get(mode_types_tree, l, &name, &value); - mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[4],g_quark_to_string(name)); //mode NODE - lttv_stats_save_attribute(mode_tree,indent[5], fp); - fprintf(fp,"%s \n",indent[5],g_quark_to_string(LTTV_STATS_SUBMODES)); //sub_modes NODE - - submodes_tree = lttv_attribute_find_subdir(mode_tree,LTTV_STATS_SUBMODES); - nb_submode = lttv_attribute_get_number(submodes_tree); - - for(m = 0 ; m < nb_submode ; m++) { - type = lttv_attribute_get(submodes_tree, m, &name, &value); - submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - fprintf(fp,"%s \n",indent[6],g_quark_to_string(name)); //sub_mode NODE - lttv_stats_save_attribute(submode_tree,indent[7], fp); - fprintf(fp,"%s \n",indent[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES)); //event_types NODE - - event_types_tree = lttv_attribute_find_subdir(submode_tree, LTTV_STATS_EVENT_TYPES); - lttv_stats_save_attribute(event_types_tree,indent[8], fp); - - fprintf(fp,"%s \n",indent[7]); //event_types NODE - fprintf(fp,"%s \n",indent[6]); //sub_mode NODE - } - fprintf(fp,"%s \n",indent[5]); //sub_modes NODE - fprintf(fp,"%s \n",indent[4]); //mode NODE - } - fprintf(fp,"%s \n",indent[3]); //mode_type NODE - fprintf(fp,"%s \n",indent[2]); //cpu NODE - } - fprintf(fp,"%s \n",indent[1]); //cpus NODE - fprintf(fp,"%s \n", indent[0]); //process NODE - } - fprintf(fp, "\n"); //root NODE - fclose(fp); - } -} - - -/* Functions to parse statistic.xml file (using glib xml parser) */ - -typedef struct _ParserStruct{ - GPtrArray * attribute; - LttvAttributeType type; - LttvAttributeName name; -} ParserStruct; - -static void stats_parser_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - int len; - LttvAttributeType type; - LttvAttributeName name; - LttvAttribute * parent_att, *new_att; - - len = parser->attribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - - if(strcmp("NODE", element_name) == 0){ - type = LTTV_GOBJECT; - name = g_quark_from_string(attribute_values[0]); - new_att = lttv_attribute_find_subdir(parent_att,name); - g_ptr_array_add(parser->attribute, (gpointer)new_att); - }else if(strcmp("VALUE", element_name) == 0){ - parser->type = (LttvAttributeType) atoi(attribute_values[0]); - parser->name = g_quark_from_string(attribute_values[1]); - }else{ - g_warning("This is not statistics.xml file\n"); - exit(1); - } -} - -static void stats_parser_end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - int len; - LttvAttribute * parent_att; - - len = parser->attribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - - if(strcmp("NODE", element_name) == 0){ - g_ptr_array_remove_index(parser->attribute, len-1); - }else if(strcmp("VALUE", element_name) == 0){ - }else{ - g_warning("This is not statistics.xml file\n"); - exit(1); - } - -} - -static void stats_parser_characters (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - LttvAttributeValue value; - int len; - LttvAttribute * parent_att; - char *pos; - - pos = (char*)text; - for(len=0;lenattribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - if(!lttv_attribute_find(parent_att,parser->name, parser->type, &value)){ - g_warning("can not find value\n"); - exit(1); - } - - switch(parser->type) { - case LTTV_INT: - *value.v_int = atoi(text); - break; - case LTTV_UINT: - *value.v_uint = (unsigned)atoi(text); - break; - case LTTV_LONG: - *value.v_long = atol(text); - break; - case LTTV_ULONG: - *value.v_ulong = (unsigned long)atol(text); - break; - case LTTV_FLOAT: - *value.v_float = atof(text); - break; - case LTTV_DOUBLE: - *value.v_float = atof(text); - break; - case LTTV_TIME: - pos = strrchr(text,'.'); - if(pos){ - *pos = '\0'; - pos++; - value.v_time->tv_sec = atol(text); - value.v_time->tv_nsec = atol(pos); - }else{ - g_warning("The time value format is wrong\n"); - exit(1); - } - break; - case LTTV_POINTER: - break; - case LTTV_STRING: - *value.v_string = g_strdup(text); - break; - default: - break; - } - -} - -gboolean lttv_stats_load_statistics(LttvTracesetStats *self) -{ - FILE * fp; - char buf[BUF_SIZE]; - LttvTracesetStats *tscs = self; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - char filename[BUF_SIZE]; - - GMarkupParseContext * context; - GError * error = NULL; - GMarkupParser markup_parser = - { - stats_parser_start_element, - stats_parser_end_element, - stats_parser_characters, - NULL, /* passthrough */ - NULL /* error */ - }; - - int i, nb_trace; - LttvAttribute *main_tree; - ParserStruct a_parser_struct; - a_parser_struct.attribute = g_ptr_array_new(); - - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - - filename[0] = '\0'; - strcat(filename,ltt_trace_name(tcs->parent.parent.t)); - strcat(filename,"/statistics.xml"); - fp = fopen(filename,"r"); - if(!fp){ - g_warning("can not open the file %s for reading statistics\n", filename); - return FALSE; - } - - main_tree = tcs->stats; - g_ptr_array_add(a_parser_struct.attribute,(gpointer)main_tree); - - context = g_markup_parse_context_new(&markup_parser, 0, (gpointer)&a_parser_struct, NULL); - - while(fgets(buf,BUF_SIZE, fp) != NULL){ - if(!g_markup_parse_context_parse(context, buf, BUF_SIZE, &error)){ - g_warning("Can not parse xml file: \n%s\n", error->message); - exit(1); - } - } - fclose(fp); - } - - sum_stats(NULL, (void *)self); - - return TRUE; } @@ -1168,6 +894,10 @@ static void module_init() LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count"); LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks"); LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks"); + LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count"); + LTTV_STATS = g_quark_from_string("statistics"); + LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics"); + LTTV_STATS_SUMMED = g_quark_from_string("statistics summed"); } static void module_destroy() @@ -1178,3 +908,9 @@ static void module_destroy() LTTV_MODULE("stats", "Compute processes statistics", \ "Accumulate statistics for event types, processes and CPUs", \ module_init, module_destroy, "state"); + +/* Change the places where stats are called (create/read/write stats) + + Check for options in batchtest.c to reduce writing and see what tests are + best candidates for performance analysis. Once OK, commit, move to main + and run tests. Update the gui for statistics. */ diff --git a/ltt/branches/poly/lttv/modules/gui/statistics/statistics.c b/ltt/branches/poly/lttv/modules/gui/statistics/statistics.c index 101f83e9..9dbd162c 100644 --- a/ltt/branches/poly/lttv/modules/gui/statistics/statistics.c +++ b/ltt/branches/poly/lttv/modules/gui/statistics/statistics.c @@ -277,8 +277,8 @@ gui_statistic(MainWindow *parent_window, LttvTracesetSelector * s, char* key) &statistic_viewer_data->time_span); if(statistic_viewer_data->calculate_stats){ - if(lttv_stats_load_statistics(statistic_viewer_data->stats)) - statistic_viewer_data->calculate_stats = FALSE; + //if(lttv_stats_load_statistics(statistic_viewer_data->stats)) + // statistic_viewer_data->calculate_stats = FALSE; } if(statistic_viewer_data->calculate_stats == FALSE){ @@ -528,7 +528,7 @@ gboolean statistic_show_viewer(void * hook_data, void * call_data) show_traceset_stats(statistic_viewer_data); if(statistic_viewer_data->calculate_stats){ statistic_remove_context_hooks(statistic_viewer_data,tsc); - lttv_stats_save_statistics((LttvTracesetStats*)tsc); + //lttv_stats_save_statistics((LttvTracesetStats*)tsc); } } diff --git a/ltt/branches/poly/lttv/modules/text/batchtest.c b/ltt/branches/poly/lttv/modules/text/batchtest.c index 35ece3f9..e57c4414 100644 --- a/ltt/branches/poly/lttv/modules/text/batchtest.c +++ b/ltt/branches/poly/lttv/modules/text/batchtest.c @@ -58,6 +58,8 @@ static int a_save_interval; static gboolean + a_trace_event, + a_save_state_copy, a_test1, a_test2, a_test3, @@ -67,6 +69,8 @@ static gboolean a_test7, a_test_all; +LttEventPosition *a_event_position; + typedef struct _save_state { guint count; FILE *fp; @@ -99,10 +103,16 @@ static double run_one_test(LttvTracesetState *ts, LttTime start, LttTime end) { double t0, t1; + int i; + lttv_traceset_context_add_hooks(&ts->parent, before_traceset, after_traceset, NULL, before_trace, after_trace, NULL, before_tracefile, after_tracefile, NULL, before_event, after_event); + for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) { + ((LttvTraceState *)(ts->parent.traces[i]))->save_interval =a_save_interval; + } + t0 = get_time(); lttv_state_traceset_seek_time_closest(ts, start); lttv_process_traceset(&ts->parent, end, G_MAXULONG); @@ -116,6 +126,24 @@ static double run_one_test(LttvTracesetState *ts, LttTime start, LttTime end) } +gboolean trace_event(void *hook_data, void *call_data) +{ + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + + guint nb_block, nb_event; + + LttTracefile *tf; + + ltt_event_position(tfs->parent.e, a_event_position); + ltt_event_position_get(a_event_position, &nb_block, &nb_event, &tf); + fprintf(stderr,"Event %s %lu.%09lu [%lu %lu]\n", + ltt_eventtype_name(ltt_event_eventtype(tfs->parent.e)), + tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec, + nb_block, nb_event); + return FALSE; +} + + gboolean count_event(void *hook_data, void *call_data) { guint *pcount = (guint *)hook_data; @@ -125,6 +153,35 @@ gboolean count_event(void *hook_data, void *call_data) } +gboolean save_state_copy_event(void *hook_data, void *call_data) +{ + SaveState *save_state = (SaveState *)hook_data; + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + + LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context; + + GString *filename; + + FILE *fp; + + if(ts->nb_event == 0 && strcmp(ltt_eventtype_name( + ltt_event_eventtype(tfs->parent.e)), "block_start") == 0) { + if(a_save_sample != NULL) { + filename = g_string_new(""); + g_string_printf(filename, "%s.copy.%lu.%09lu.xml", a_save_sample, + tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + fp = fopen(filename->str, "w"); + if(fp == NULL) g_error("Cannot open %s", filename->str); + g_string_free(filename, TRUE); + lttv_state_write(ts, tfs->parent.timestamp, fp); + fclose(fp); + } //else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp); + } + return FALSE; +} + + gboolean save_state_event(void *hook_data, void *call_data) { SaveState *save_state = (SaveState *)hook_data; @@ -149,7 +206,7 @@ gboolean save_state_event(void *hook_data, void *call_data) g_string_free(filename, TRUE); lttv_state_write(ts, tfs->parent.timestamp, fp); fclose(fp); - } else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp); + } //else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp); save_state->write_time[save_state->position] = tfs->parent.timestamp; save_state->position++; @@ -198,14 +255,13 @@ static gboolean process_traceset(void *hook_data, void *call_data) LttTime start_time; - LttEventPosition *event_position; - LttTime zero_time = ltt_time_zero; LttTime max_time = { G_MAXULONG, G_MAXULONG }; + a_event_position = ltt_event_position_new(); + if(a_dump_tracefiles != NULL) { - event_position = ltt_event_position_new(); for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) { trace = lttv_trace(lttv_traceset_get(traceset, i)); nb_control = ltt_trace_control_tracefile_number(trace); @@ -231,8 +287,8 @@ static gboolean process_traceset(void *hook_data, void *call_data) event_type = ltt_event_eventtype(event); time = ltt_event_time(event); cycle_count = ltt_event_cycle_count(event); - ltt_event_position(event, event_position); - ltt_event_position_get(event_position, &nb_block, &nb_event, &tf); + ltt_event_position(event, a_event_position); + ltt_event_position_get(a_event_position, &nb_block, &nb_event, &tf); fprintf(fp,"%s.%s: %llu %lu.%09lu position %u/%u\n", ltt_facility_name(facility), ltt_eventtype_name(event_type), cycle_count, (unsigned long)time.tv_sec, @@ -277,7 +333,6 @@ static gboolean process_traceset(void *hook_data, void *call_data) fclose(fp); } } - g_free(event_position); } tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL); @@ -285,9 +340,6 @@ static gboolean process_traceset(void *hook_data, void *call_data) tc = &tscs->parent.parent; lttv_context_init(tc, traceset); - for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) { - ((LttvTraceState *)(tc->traces[i]))->save_interval = a_save_interval; - } /* For each case compute and print the elapsed time. The first case is simply to run through all events with a @@ -354,6 +406,21 @@ static gboolean process_traceset(void *hook_data, void *call_data) g_message("Memory summary after computing stats"); g_mem_profile(); } + + lttv_stats_sum_traceset(tscs); + + if(lttv_profile_memory) { + g_message("Memory summary after summing stats"); + g_mem_profile(); + } + + lttv_context_fini(tc); + lttv_context_init(tc, traceset); + + if(lttv_profile_memory) { + g_message("Memory summary after cleaning up the stats"); + g_mem_profile(); + } } /* Run through all events computing the state and stats. */ @@ -376,10 +443,20 @@ static gboolean process_traceset(void *hook_data, void *call_data) g_message("Memory summary after computing and state and stats"); g_mem_profile(); } + + lttv_context_fini(tc); + lttv_context_init(tc, traceset); + + if(lttv_profile_memory) { + g_message("Memory summary after cleaning up the stats"); + g_mem_profile(); + } } /* Run through all events computing and saving the state. */ + if(a_trace_event) lttv_hooks_add(after_event, trace_event, NULL); + if(a_test6 || a_test_all) { if(lttv_profile_memory) { g_message("Memory summary before computing and saving state"); @@ -388,9 +465,14 @@ static gboolean process_traceset(void *hook_data, void *call_data) lttv_state_add_event_hooks(ts); lttv_state_save_add_event_hooks(ts); + if(a_save_state_copy) + lttv_hooks_add(after_event, save_state_copy_event, &save_state); t = run_one_test(ts, zero_time, max_time); lttv_state_remove_event_hooks(ts); lttv_state_save_remove_event_hooks(ts); + if(a_save_state_copy) + lttv_hooks_remove_data(after_event,save_state_copy_event, &save_state); + g_warning("Processing trace while updating/saving state (%g seconds)", t); if(lttv_profile_memory) { @@ -424,16 +506,24 @@ static gboolean process_traceset(void *hook_data, void *call_data) save_state.write_time[j], fp); fclose(fp); } - else lttv_state_write((LttvTraceState *)tc->traces[0], - save_state.write_time[j], save_state.fp); + //else lttv_state_write((LttvTraceState *)tc->traces[0], + // save_state.write_time[j], save_state.fp); } } } + if(a_trace_event) lttv_hooks_remove_data(after_event, trace_event, NULL); + g_free(save_state.write_time); + g_free(a_event_position); lttv_context_fini(tc); g_object_unref(tscs); + if(lttv_profile_memory) { + g_message("Memory summary at the end of batchtest"); + g_mem_profile(); + } + g_info("BatchTest end process traceset"); } @@ -451,6 +541,8 @@ static void init() "pathname of the directory containing the trace", LTTV_OPT_STRING, &a_trace, lttv_trace_option, NULL); + a_trace_event = FALSE; + a_dump_tracefiles = NULL; lttv_option_add("dump-tracefiles", 'D', "Write event by event the content of tracefiles", @@ -463,6 +555,10 @@ static void init() "basename for the files containing the state samples", LTTV_OPT_STRING, &a_save_sample, NULL, NULL); + a_save_state_copy = FALSE; + lttv_option_add("save-state-copy", 'S', "Write the state saved for seeking", + "", LTTV_OPT_NONE, &a_save_state_copy, NULL, NULL); + a_save_interval = 100000; lttv_option_add("save-interval", 'i', "Interval between saving state", @@ -567,6 +663,7 @@ static void destroy() lttv_option_remove("trace"); lttv_option_remove("dump-tracefiles"); lttv_option_remove("save-sample"); + lttv_option_remove("save-state-copy"); lttv_option_remove("sample-interval"); lttv_option_remove("sample-number"); lttv_option_remove("save-interval"); diff --git a/ltt/branches/poly/lttv/modules/text/textDump.c b/ltt/branches/poly/lttv/modules/text/textDump.c index c105a07c..cc400d92 100644 --- a/ltt/branches/poly/lttv/modules/text/textDump.c +++ b/ltt/branches/poly/lttv/modules/text/textDump.c @@ -283,6 +283,7 @@ static gboolean write_traceset_footer(void *hook_data, void *call_data) fprintf(a_file,"End trace set\n\n"); if(LTTV_IS_TRACESET_STATS(tc)) { + lttv_stats_sum_traceset((LttvTracesetStats *)tc); print_stats(a_file, (LttvTracesetStats *)tc); }