From 308711e5772586ce8ecc22ce04e571b175309b8e Mon Sep 17 00:00:00 2001 From: dagenais Date: Wed, 15 Oct 2003 02:56:59 +0000 Subject: [PATCH] Add state saving functions and update processTrace accordingly. Add time operators functions git-svn-id: http://ltt.polymtl.ca/svn@306 04897980-b3bd-0310-b5e0-8ef037075253 --- ltt/branches/poly/include/ltt/Makefile.am | 1 + ltt/branches/poly/include/ltt/ltt.h | 58 +- ltt/branches/poly/include/ltt/time.h | 94 +++ ltt/branches/poly/include/lttv/iattribute.h | 6 +- ltt/branches/poly/include/lttv/processTrace.h | 11 +- ltt/branches/poly/include/lttv/state.h | 40 +- ltt/branches/poly/include/lttv/traceset.h | 14 +- ltt/branches/poly/ltt/tracefile.c | 54 +- ltt/branches/poly/lttv/attribute.c | 4 +- ltt/branches/poly/lttv/batchAnalysis.c | 11 +- ltt/branches/poly/lttv/main.c | 38 +- .../poly/lttv/modules/gui/API/gtkTraceSet.c | 5 +- .../lttv/modules/gui/mainWin/src/gtkcustom.c | 33 +- .../modules/gui/mainWin/src/init_module.c | 11 +- .../lttv/modules/guiControlFlow/Drawing.c | 25 +- ltt/branches/poly/lttv/modules/guiEvents.c | 22 +- ltt/branches/poly/lttv/processTrace.c | 92 ++- ltt/branches/poly/lttv/state.c | 668 ++++++++++++++---- ltt/branches/poly/lttv/stats.c | 12 +- ltt/branches/poly/lttv/textDump.c | 2 + ltt/branches/poly/lttv/traceset.c | 65 +- 21 files changed, 908 insertions(+), 358 deletions(-) create mode 100644 ltt/branches/poly/include/ltt/time.h diff --git a/ltt/branches/poly/include/ltt/Makefile.am b/ltt/branches/poly/include/ltt/Makefile.am index f9453e73..be3e9f10 100644 --- a/ltt/branches/poly/include/ltt/Makefile.am +++ b/ltt/branches/poly/include/ltt/Makefile.am @@ -4,5 +4,6 @@ lttinclude_HEADERS = \ facility.h\ ltt-private.h\ ltt.h\ + time.h\ trace.h\ type.h diff --git a/ltt/branches/poly/include/ltt/ltt.h b/ltt/branches/poly/include/ltt/ltt.h index 15855362..a5f3fee0 100644 --- a/ltt/branches/poly/include/ltt/ltt.h +++ b/ltt/branches/poly/include/ltt/ltt.h @@ -1,6 +1,7 @@ #ifndef LTT_H #define LTT_H +#include #include /* A trace is associated with a tracing session run on a single, possibly @@ -70,16 +71,11 @@ 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, ltt_time, + 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 _LttTime { - unsigned long tv_sec; - unsigned long tv_nsec; -} LttTime; - typedef struct _TimeInterval{ LttTime startTime; @@ -89,7 +85,6 @@ typedef struct _TimeInterval{ typedef uint64_t LttCycleCount; -#define NANSECOND_CONST 1000000000 /* Event positions are used to seek within a tracefile based on the block number and event position within the block. */ @@ -111,55 +106,6 @@ typedef enum _LttArchEndian { LTT_LITTLE_ENDIAN, LTT_BIG_ENDIAN } LttArchEndian; -/* Time operation macros for LttTime (struct timespec) */ -/* (T3 = T2 - T1) */ -#define TimeSub(T3, T2, T1) \ -do \ -{\ - (T3).tv_sec = (T2).tv_sec - (T1).tv_sec; \ - if((T2).tv_nsec < (T1).tv_nsec)\ - {\ - (T3).tv_sec--;\ - (T3).tv_nsec = NANSECOND_CONST - (T1).tv_nsec + (T2).tv_nsec;\ - }\ - else\ - {\ - (T3).tv_nsec = (T2).tv_nsec - (T1).tv_nsec;\ - }\ -} while(0) - -/* (T3 = T2 + T1) */ -#define TimeAdd(T3, T2, T1) \ -do \ -{\ - (T3).tv_sec = (T2).tv_sec + (T1).tv_sec; \ - (T3).tv_nsec = (T2).tv_nsec + (T1).tv_nsec; \ - if((T3).tv_nsec >= NANSECOND_CONST)\ - {\ - (T3).tv_sec += (T3).tv_nsec / NANSECOND_CONST;\ - (T3).tv_nsec = (T3).tv_nsec % NANSECOND_CONST;\ - }\ -} while(0) - -/* (T2 = T1 * FLOAT) */ -/* WARNING : use this multiplicator carefully : on 32 bits, multiplying - * by more than 4 could overflow the tv_nsec. - */ -#define TimeMul(T2, T1, FLOAT) \ -do \ -{\ - (T2).tv_sec = (T1).tv_sec * (FLOAT); \ - (T2).tv_nsec = (T1).tv_nsec * (FLOAT); \ - if((T2).tv_nsec >= NANSECOND_CONST)\ - {\ - (T2).tv_sec += (T2).tv_nsec / NANSECOND_CONST;\ - (T2).tv_nsec = (T2).tv_nsec % NANSECOND_CONST;\ - }\ -} while(0) - - - - #include diff --git a/ltt/branches/poly/include/ltt/time.h b/ltt/branches/poly/include/ltt/time.h new file mode 100644 index 00000000..4f809433 --- /dev/null +++ b/ltt/branches/poly/include/ltt/time.h @@ -0,0 +1,94 @@ +#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) +{ + double nsec; + LttTime res; + + nsec = (double)t1.tv_nsec * f; + res.tv_sec = nsec / NANOSECONDS_PER_SECOND; + res.tv_nsec = nsec - res.tv_sec * NANOSECONDS_PER_SECOND; + res.tv_sec += t1.tv_sec * f; + 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; + 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/lttv/iattribute.h b/ltt/branches/poly/include/lttv/iattribute.h index 1613a451..24cbd57d 100644 --- a/ltt/branches/poly/include/lttv/iattribute.h +++ b/ltt/branches/poly/include/lttv/iattribute.h @@ -3,7 +3,7 @@ #include -#include +#include /* The content of a data structure may be seen as an array of pairs of attribute name and value. This simple model allows generic navigation @@ -12,8 +12,6 @@ typedef GQuark LttvAttributeName; -typedef struct timespec LttvTime; - typedef enum _LttvAttributeType { LTTV_INT, LTTV_UINT, LTTV_LONG, LTTV_ULONG, LTTV_FLOAT, LTTV_DOUBLE, LTTV_TIME, LTTV_POINTER, LTTV_STRING, LTTV_GOBJECT, LTTV_NONE @@ -26,7 +24,7 @@ typedef union LttvAttributeValue { unsigned long *v_ulong; float *v_float; double *v_double; - LttvTime *v_time; + LttTime *v_time; gpointer *v_pointer; char **v_string; GObject **v_gobject; diff --git a/ltt/branches/poly/include/lttv/processTrace.h b/ltt/branches/poly/include/lttv/processTrace.h index 610000cb..e8505b5d 100644 --- a/ltt/branches/poly/include/lttv/processTrace.h +++ b/ltt/branches/poly/include/lttv/processTrace.h @@ -71,6 +71,7 @@ struct _LttvTracesetContext { LttvHooks *after; LttvTraceContext **traces; LttvAttribute *a; + LttvAttribute *ts_a; TimeInterval *Time_Span; }; @@ -113,12 +114,14 @@ struct _LttvTraceContext { LttvTracesetContext *ts_context; guint index; /* in ts_context->traces */ LttTrace *t; + LttvTrace *vt; LttvHooks *check; LttvHooks *before; LttvHooks *after; LttvTracefileContext **control_tracefiles; LttvTracefileContext **per_cpu_tracefiles; LttvAttribute *a; + LttvAttribute *t_a; }; struct _LttvTraceContextClass { @@ -160,8 +163,12 @@ struct _LttvTracefileContextClass { GType lttv_tracefile_context_get_type (void); -void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, - LttvTracesetContext *context, unsigned maxNumEvents); +void lttv_process_traceset(LttvTracesetContext *self, LttTime end, + unsigned maxNumEvents); + +void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start); + +void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start); void lttv_traceset_context_add_hooks(LttvTracesetContext *self, LttvHooks *before_traceset, diff --git a/ltt/branches/poly/include/lttv/state.h b/ltt/branches/poly/include/lttv/state.h index f85847b4..b8f4be00 100644 --- a/ltt/branches/poly/include/lttv/state.h +++ b/ltt/branches/poly/include/lttv/state.h @@ -12,7 +12,22 @@ and LttvTracefileContext objects, used by processTrace, through subtyping. The context objects already reflect the multiple tracefiles (one per cpu) per trace and multiple traces per trace set. The state - objects defined here simply add fields to the relevant context objects. */ + objects defined here simply add fields to the relevant context objects. + + There is no traceset specific state yet. It may eventually contains such + things as clock differences over time. + + The trace state currently consists in a process table. + + The tracefile level state relates to the associated cpu. It contains the + position of the current event in the tracefile (since the state depends on + which events have been processed) and a pointer to the current process, + in the process table, being run on that cpu. + + For each process in the process table, various informations such as exec + file name, pid, ppid and creation time are stored. Each process state also + contains an execution mode stack (e.g. irq within system call, called + from user mode). */ typedef struct _LttvTracesetState LttvTracesetState; typedef struct _LttvTracesetStateClass LttvTracesetStateClass; @@ -23,9 +38,15 @@ typedef struct _LttvTraceStateClass LttvTraceStateClass; typedef struct _LttvTracefileState LttvTracefileState; typedef struct _LttvTracefileStateClass LttvTracefileStateClass; -gboolean lttv_state_add_event_hooks(LttvTracesetState *self); +void lttv_state_add_event_hooks(LttvTracesetState *self); + +void lttv_state_remove_event_hooks(LttvTracesetState *self); + +void lttv_state_save_add_event_hooks(LttvTracesetState *self); -gboolean lttv_state_remove_event_hooks(LttvTracesetState *self); +void lttv_state_save_remove_event_hooks(LttvTracesetState *self); + +void lttv_state_restore_closest_state(LttvTracesetState *self, LttTime t); /* The LttvProcessState structure defines the current state for each process. A process can make system calls (in some rare cases nested) and receive @@ -137,6 +158,7 @@ struct _LttvTraceState { LttvTraceContext parent; GHashTable *processes; /* LttvProcessState objects indexed by pid */ + guint nb_event, save_interval; /* Block/char devices, locks, memory pages... */ GQuark *eventtype_names; GQuark *syscall_names; @@ -146,10 +168,21 @@ struct _LttvTraceState { struct _LttvTraceStateClass { LttvTraceContextClass parent; + + void (*state_save) (LttvTraceState *self, LttvAttribute *container); + void (*state_restore) (LttvTraceState *self, LttvAttribute *container); + void (*state_saved_free) (LttvTraceState *self, LttvAttribute *container); }; GType lttv_trace_state_get_type (void); +void lttv_state_save(LttvTraceState *self, LttvAttribute *container); + +void lttv_state_restore(LttvTraceState *self, LttvAttribute *container); + +void lttv_state_saved_state_free(LttvTraceState *self, + LttvAttribute *container); + #define LTTV_TRACEFILE_STATE_TYPE (lttv_tracefile_state_get_type ()) #define LTTV_TRACEFILE_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileState)) @@ -163,6 +196,7 @@ struct _LttvTracefileState { LttvProcessState *process; GQuark cpu_name; + guint saved_position; }; struct _LttvTracefileStateClass { diff --git a/ltt/branches/poly/include/lttv/traceset.h b/ltt/branches/poly/include/lttv/traceset.h index ecf10461..4675e719 100644 --- a/ltt/branches/poly/include/lttv/traceset.h +++ b/ltt/branches/poly/include/lttv/traceset.h @@ -9,11 +9,14 @@ typedef struct _LttvTraceset LttvTraceset; +typedef struct _LttvTrace LttvTrace; /* Tracesets may be added to, removed from and their content listed. */ LttvTraceset *lttv_traceset_new(); +LttvTrace *lttv_trace_new(LttTrace *t); + LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig); LttvTraceset *lttv_traceset_load(const gchar *filename); @@ -22,11 +25,13 @@ gint lttv_traceset_save(LttvTraceset *s); void lttv_traceset_destroy(LttvTraceset *s); -void lttv_traceset_add(LttvTraceset *s, LttTrace *t); +void lttv_trace_destroy(LttvTrace *t); + +void lttv_traceset_add(LttvTraceset *s, LttvTrace *t); unsigned lttv_traceset_number(LttvTraceset *s); -LttTrace *lttv_traceset_get(LttvTraceset *s, unsigned i); +LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i); void lttv_traceset_remove(LttvTraceset *s, unsigned i); @@ -34,8 +39,9 @@ void lttv_traceset_remove(LttvTraceset *s, unsigned i); LttvAttribute *lttv_traceset_attribute(LttvTraceset *s); -LttvAttribute *lttv_traceset_trace_attribute(LttvTraceset *s, - unsigned i); +LttvAttribute *lttv_trace_attribute(LttvTrace *t); + +LttTrace *lttv_trace(LttvTrace *t); #endif // TRACESET_H diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index a2f7bbad..07b8ab3a 100644 --- a/ltt/branches/poly/ltt/tracefile.c +++ b/ltt/branches/poly/ltt/tracefile.c @@ -33,10 +33,6 @@ void updateTracefile(LttTracefile * tf); /* go to the next event */ int skipEvent(LttTracefile * t); -/* compare two time (LttTime), 0:t1=t2, -1:t1t2 */ -int timecmp(LttTime * t1, LttTime * t2); - - /***************************************************************************** *Function name @@ -693,8 +689,8 @@ void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end) j = 1; continue; } - if(timecmp(&startSmall,&startTmp) > 0) startSmall = startTmp; - if(timecmp(&endBig,&endTmp) < 0) endBig = endTmp; + if(ltt_time_compare(startSmall,startTmp) > 0) startSmall = startTmp; + if(ltt_time_compare(endBig,endTmp) < 0) endBig = endTmp; } for(i=0;iper_cpu_tracefile_number;i++){ @@ -708,8 +704,8 @@ void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end) endBig = endTmp; continue; } - if(timecmp(&startSmall,&startTmp) > 0) startSmall = startTmp; - if(timecmp(&endBig,&endTmp) < 0) endBig = endTmp; + if(ltt_time_compare(startSmall,startTmp) > 0) startSmall = startTmp; + if(ltt_time_compare(endBig,endTmp) < 0) endBig = endTmp; } *start = startSmall; @@ -748,16 +744,16 @@ void ltt_tracefile_seek_time(LttTracefile *t, LttTime time) { int err; LttTime lttTime; - int headTime = timecmp(&(t->a_block_start->time), &time); - int tailTime = timecmp(&(t->a_block_end->time), &time); + int headTime = ltt_time_compare(t->a_block_start->time, time); + int tailTime = ltt_time_compare(t->a_block_end->time, time); LttEvent * ev; if(headTime < 0 && tailTime > 0){ - if(timecmp(&(t->a_block_end->time),&(t->current_event_time)) !=0){ + if(ltt_time_compare(t->a_block_end->time, t->current_event_time) !=0) { lttTime = getEventTime(t); - err = timecmp(<tTime, &time); + err = ltt_time_compare(lttTime, time); if(err > 0){ - if(t->which_event==2 || timecmp(&t->prev_event_time,&time)<0){ + if(t->which_event==2 || (&t->prev_event_time,&time)<0){ return; }else{ updateTracefile(t); @@ -771,7 +767,7 @@ void ltt_tracefile_seek_time(LttTracefile *t, LttTime time) return; } lttTime = getEventTime(t); - err = timecmp(<tTime, &time); + err = ltt_time_compare(lttTime, time); if(err >= 0)return; } }else return; @@ -783,7 +779,7 @@ void ltt_tracefile_seek_time(LttTracefile *t, LttTime time) if(t->which_block == 1){ updateTracefile(t); }else{ - if(timecmp(&(t->prev_block_end_time),&time) >= 0 ){ + if(ltt_time_compare(t->prev_block_end_time, time) >= 0 ){ err=readBlock(t,t->which_block-1); if(err) g_error("Can not read tracefile: %s\n", t->name); return ltt_tracefile_seek_time(t, time) ; @@ -1038,7 +1034,7 @@ void getCyclePerNsec(LttTracefile * t) LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */ /* Calculate the total time for this buffer */ - TimeSub(lBufTotalTime,t->a_block_end->time, t->a_block_start->time); + lBufTotalTime = ltt_time_sub(t->a_block_end->time, t->a_block_start->time); /* Calculate the total cycles for this bufffer */ lBufTotalCycle = t->a_block_end->cycle_count; @@ -1046,7 +1042,7 @@ void getCyclePerNsec(LttTracefile * t) /* Convert the total time to nsecs */ lBufTotalNSec = lBufTotalTime.tv_sec; - lBufTotalNSec *= NANSECOND_CONST; + lBufTotalNSec *= NANOSECONDS_PER_SECOND; lBufTotalNSec += lBufTotalTime.tv_nsec; t->cycle_per_nsec = (double)lBufTotalCycle / (double)lBufTotalNSec; @@ -1106,10 +1102,10 @@ LttTime getEventTime(LttTracefile * tf) nanoSec = lEventNSec; // Determine offset in struct LttTime - lTimeOffset.tv_nsec = nanoSec % NANSECOND_CONST; - lTimeOffset.tv_sec = nanoSec / NANSECOND_CONST; + lTimeOffset.tv_nsec = nanoSec % NANOSECONDS_PER_SECOND; + lTimeOffset.tv_sec = nanoSec / NANOSECONDS_PER_SECOND; - TimeAdd(time, tf->a_block_start->time, lTimeOffset); + time = ltt_time_add(tf->a_block_start->time, lTimeOffset); return time; } @@ -1262,24 +1258,6 @@ int getFieldtypeSize(LttTracefile * t, LttEventType * evT, int offsetRoot, return size; } -/***************************************************************************** - *Function name - * timecmp : compare two time - *Input params - * t1 : first time - * t2 : second time - *Return value - * int : 0: t1 == t2; -1: t1 < t2; 1: t1 > t2 - ****************************************************************************/ - -int timecmp(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; -} /***************************************************************************** *Function name diff --git a/ltt/branches/poly/lttv/attribute.c b/ltt/branches/poly/lttv/attribute.c index 59241fb3..4b6938d7 100644 --- a/ltt/branches/poly/lttv/attribute.c +++ b/ltt/branches/poly/lttv/attribute.c @@ -9,7 +9,7 @@ typedef union _AttributeValue { unsigned long dv_ulong; float dv_float; double dv_double; - LttvTime dv_time; + LttTime dv_time; gpointer dv_pointer; char *dv_string; GObject *dv_gobject; @@ -274,7 +274,7 @@ void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src) *value.v_double += a->value.dv_double; break; case LTTV_TIME: - TimeAdd(*value.v_time, *value.v_time, a->value.dv_time); + *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time); break; case LTTV_POINTER: break; diff --git a/ltt/branches/poly/lttv/batchAnalysis.c b/ltt/branches/poly/lttv/batchAnalysis.c index 2db57830..98a686cd 100644 --- a/ltt/branches/poly/lttv/batchAnalysis.c +++ b/ltt/branches/poly/lttv/batchAnalysis.c @@ -34,7 +34,7 @@ void lttv_trace_option(void *hook_data) trace = ltt_trace_open(a_trace); if(trace == NULL) g_critical("cannot open trace %s", a_trace); - lttv_traceset_add(traceset, trace); + lttv_traceset_add(traceset, lttv_trace_new(trace)); } @@ -68,7 +68,8 @@ static gboolean process_traceset(void *hook_data, void *call_data) g_info("BatchAnalysis process traceset"); - lttv_process_trace(start, end, traceset, tc, G_MAXULONG); + lttv_process_traceset_seek_time(tc, start); + lttv_process_traceset(tc, end, G_MAXULONG); g_info("BatchAnalysis destroy context"); @@ -151,6 +152,8 @@ G_MODULE_EXPORT void destroy() { guint i, nb; + LttvTrace *trace; + g_info("Destroy batchAnalysis.c"); lttv_option_remove("trace"); @@ -168,7 +171,9 @@ G_MODULE_EXPORT void destroy() nb = lttv_traceset_number(traceset); for(i = 0 ; i < nb ; i++) { - ltt_trace_close(lttv_traceset_get(traceset, i)); + trace = lttv_traceset_get(traceset, i); + ltt_trace_close(lttv_trace(trace)); + lttv_trace_destroy(trace); } lttv_traceset_destroy(traceset); diff --git a/ltt/branches/poly/lttv/main.c b/ltt/branches/poly/lttv/main.c index de3c7709..7b6f7153 100644 --- a/ltt/branches/poly/lttv/main.c +++ b/ltt/branches/poly/lttv/main.c @@ -54,7 +54,7 @@ static void lttv_verbose(void *hook_data); static void lttv_debug(void *hook_data); -static void lttv_help(void); +static void lttv_help(void *hook_data); /* Since everything is done in modules, the main program only takes care of the infrastructure. */ @@ -182,7 +182,7 @@ void lttv_debug(void *hook_data) g_info("Logging set to include DEBUG level messages"); } -void lttv_help() +void lttv_help(void *hook_data) { printf("Linux Trace Toolkit Visualizer\n"); printf("\n"); @@ -190,8 +190,32 @@ void lttv_help() printf("\n"); } -/* remove countEvents.c, add alias to init to allow static/dynamic loading - MODULE_INFO(name, init, destroy, { require} ). This info could be used - by module_load and as a constructor function when not a module - -> check constructor functions versus dynamic loading and init section - -> have a list of available modules builtin as default or mandatory */ +/* + +- Make it easier to change modules from builtin to externally loaded. + + have: MODULE_INFO(name, init, destroy, { require} ) in each module. + Maintain the list of builtin modules and search these first (or + optionally last). Add the lib prefix if needed to avoid having to + specify libbatchAnalysis instead of batchAnalysis. + +- Define formally traceset/trace in the GUI for the user and decide how + trace/traceset sharing goes in the application. + +- Use appropriately the new functions in time.h + +- remove the separate tracefiles (control/per cpu) arrays/loops in context. + +- split processTrace into context.c and processTrace.c + +- check spelling conventions. + +- get all the copyright notices. + +- remove all the warnings. + +- get all the .h files properly doxygen commented to produce useful documents. + +- have an intro/architecture document. + +- write a tutorial */ diff --git a/ltt/branches/poly/lttv/modules/gui/API/gtkTraceSet.c b/ltt/branches/poly/lttv/modules/gui/API/gtkTraceSet.c index 3c681a97..8d0c4d35 100644 --- a/ltt/branches/poly/lttv/modules/gui/API/gtkTraceSet.c +++ b/ltt/branches/poly/lttv/modules/gui/API/gtkTraceSet.c @@ -598,9 +598,8 @@ void SetHPaneDividor(mainWindow *main_win, gint position) void processTraceset(mainWindow *main_win, LttTime start, LttTime end, unsigned maxNumEvents) { - lttv_process_trace(start, end, main_win->Traceset_Info->traceset, - LTTV_TRACESET_CONTEXT(main_win->Traceset_Info->TracesetContext), - maxNumEvents); + lttv_process_traceset_seek_time(main_win->Traceset_Info->TracesetContext, start); + lttv_process_trace(main_win->Traceset_Info->TracesetContext, end, maxNumEvents); } /** diff --git a/ltt/branches/poly/lttv/modules/gui/mainWin/src/gtkcustom.c b/ltt/branches/poly/lttv/modules/gui/mainWin/src/gtkcustom.c index 491e730c..806ac231 100644 --- a/ltt/branches/poly/lttv/modules/gui/mainWin/src/gtkcustom.c +++ b/ltt/branches/poly/lttv/modules/gui/mainWin/src/gtkcustom.c @@ -107,7 +107,6 @@ void gtk_custom_widget_add(GtkCustom * custom, GtkWidget * widget1) GtkWidget * w; TimeWindow Time_Window; LttTime time; - double tmpValue; TimeInterval *Time_Span; g_return_if_fail(GTK_IS_CUSTOM(custom)); @@ -126,30 +125,19 @@ void gtk_custom_widget_add(GtkCustom * custom, GtkWidget * widget1) GetCurrentTime(custom->mw,&time); Time_Span = LTTV_TRACESET_CONTEXT(custom->mw->Traceset_Info->TracesetContext)->Time_Span ; - tmpValue = Time_Span->startTime.tv_sec; - tmpValue *= NANSECOND_CONST; - tmpValue += Time_Span->startTime.tv_nsec; - custom->hAdjust->lower = tmpValue; - custom->hAdjust->value = tmpValue; - tmpValue = Time_Span->endTime.tv_sec; - tmpValue *= NANSECOND_CONST; - tmpValue += Time_Span->endTime.tv_nsec; - custom->hAdjust->upper = tmpValue; - //tmpValue = time.tv_sec; - //tmpValue *= NANSECOND_CONST; - //tmpValue += time.tv_nsec; - //custom->hAdjust->value = tmpValue; - /* Step increment to 1/10 of visible area */ - tmpValue = Time_Window.Time_Width.tv_sec; - tmpValue *= NANSECOND_CONST; - tmpValue += Time_Window.Time_Width.tv_nsec; - custom->hAdjust->step_increment = tmpValue / 10; + custom->hAdjust->lower = ltt_time_to_double(Time_Span->startTime) * + NANOSECONDS_PER_SECOND; + custom->hAdjust->value = custom->hAdjust->lower; + custom->hAdjust->upper = ltt_time_to_double(Time_Span->endTime) * + NANOSECONDS_PER_SECOND; /* Page increment of whole visible area */ - custom->hAdjust->page_increment = tmpValue; + custom->hAdjust->page_increment = ltt_time_to_double( + Time_Window.Time_Width) * NANOSECONDS_PER_SECOND; /* page_size to the whole visible area will take care that the * scroll value + the shown area will never be more than what is * in the trace. */ - custom->hAdjust->page_size = tmpValue; + custom->hAdjust->page_size = custom->hAdjust->page_increment; + custom->hAdjust->step_increment = custom->hAdjust->page_increment / 10; gtk_range_set_update_policy (GTK_RANGE(custom->hScrollbar), GTK_UPDATE_DISCONTINUOUS); @@ -320,8 +308,7 @@ void gtk_custom_scroll_value_changed(GtkRange *range, gpointer custom_arg) LttTime time; GtkCustom * custom = (GtkCustom*)custom_arg; gdouble value = gtk_range_get_value(range); - time.tv_sec = value / NANSECOND_CONST; - time.tv_nsec = (value / NANSECOND_CONST - time.tv_sec) * NANSECOND_CONST; + time = ltt_time_from_double(value / NANOSECONDS_PER_SECOND); SetCurrentTime(custom->mw, &time); g_warning("The current time is second :%d, nanosecond : %d\n", time.tv_sec, time.tv_nsec); } diff --git a/ltt/branches/poly/lttv/modules/gui/mainWin/src/init_module.c b/ltt/branches/poly/lttv/modules/gui/mainWin/src/init_module.c index f6f398ae..f8635a2d 100644 --- a/ltt/branches/poly/lttv/modules/gui/mainWin/src/init_module.c +++ b/ltt/branches/poly/lttv/modules/gui/mainWin/src/init_module.c @@ -37,15 +37,17 @@ LttvHooks *main_hooks; /* Initial trace from command line */ -LttTrace *gInit_Trace = NULL; +LttvTrace *gInit_Trace = NULL; static char *a_trace; void lttv_trace_option(void *hook_data) { - gInit_Trace = ltt_trace_open(a_trace); - if(gInit_Trace == NULL) g_critical("cannot open trace %s", a_trace); - g_critical("lttv_trace_option : Init_Trace is %p", gInit_Trace); + LttTrace *trace; + + trace = ltt_trace_open(a_trace); + if(trace == NULL) g_critical("cannot open trace %s", a_trace); + gInit_Trace = lttv_trace_new(trace); } /***************************************************************************** @@ -215,6 +217,7 @@ void destroy_walk(gpointer data, gpointer user_data) G_MODULE_EXPORT void destroy() { LttvAttributeValue value; + LttvTrace *trace; lttv_option_remove("trace"); diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c b/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c index cb2d049d..e2225a11 100644 --- a/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c @@ -244,9 +244,7 @@ GtkWidget *Drawing_getWidget(Drawing_t *Drawing) /* get_time_from_pixels * - * Get the time interval from window time and pixels, and pixels requested. This - * function uses TimeMul, which should only be used if the float value is lower - * that 4, and here it's always lower than 1, so it's ok. + * Get the time interval from window time and pixels, and pixels requested. */ void convert_pixels_to_time( Drawing_t *Drawing, @@ -257,13 +255,10 @@ void convert_pixels_to_time( { LttTime window_time_interval; - TimeSub(window_time_interval, *window_time_end, *window_time_begin); - - - TimeMul(*time, window_time_interval, - (x/(float)Drawing->width)); - TimeAdd(*time, *window_time_begin, *time); - + window_time_interval = ltt_time_sub(*window_time_end, + *window_time_begin); + *time = ltt_time_mul(window_time_interval, (x/(float)Drawing->width)); + *time = ltt_time_add(*window_time_begin, *time); } @@ -278,14 +273,12 @@ void convert_time_to_pixels( LttTime window_time_interval; float interval_float, time_float; - TimeSub(window_time_interval, window_time_end, window_time_begin); + window_time_interval = ltt_time_sub(window_time_end,window_time_begin); - TimeSub(time, time, window_time_begin); + time = ltt_time_sub(time, window_time_begin); - interval_float = (window_time_interval.tv_sec * NANSECOND_CONST) - + window_time_interval.tv_nsec; - time_float = (time.tv_sec * NANSECOND_CONST) - + time.tv_nsec; + interval_float = ltt_time_to_double(window_time_interval); + time_float = ltt_time_to_double(time); *x = (guint)(time_float/interval_float * Drawing->width); diff --git a/ltt/branches/poly/lttv/modules/guiEvents.c b/ltt/branches/poly/lttv/modules/guiEvents.c index 9b3e8641..183688a0 100644 --- a/ltt/branches/poly/lttv/modules/guiEvents.c +++ b/ltt/branches/poly/lttv/modules/guiEvents.c @@ -439,7 +439,7 @@ GuiEvents(mainWindow *pmParentWindow) getTracesetTimeSpan(Event_Viewer_Data->mw, &Event_Viewer_Data->time_span); time_value = Event_Viewer_Data->time_span.endTime.tv_sec - Event_Viewer_Data->time_span.startTime.tv_sec; - time_value *= NANSECOND_CONST; + time_value *= NANOSECONDS_PER_SECOND; time_value += (double)Event_Viewer_Data->time_span.endTime.tv_nsec - Event_Viewer_Data->time_span.startTime.tv_nsec; Event_Viewer_Data->VAdjust_C->upper = time_value; @@ -688,8 +688,8 @@ void Tree_V_cursor_changed_cb (GtkWidget *widget, gpointer data) gtk_tree_view_get_cursor(GTK_TREE_VIEW(Event_Viewer_Data->Tree_V), &path, NULL); if(gtk_tree_model_get_iter(model,&iter,path)){ gtk_tree_model_get(model, &iter, TIME_COLUMN, &time, -1); - ltt_time.tv_sec = time / NANSECOND_CONST; - ltt_time.tv_nsec = time % NANSECOND_CONST; + ltt_time.tv_sec = time / NANOSECONDS_PER_SECOND; + ltt_time.tv_nsec = time % NANOSECONDS_PER_SECOND; if(ltt_time.tv_sec != Event_Viewer_Data->current_time.tv_sec || ltt_time.tv_nsec != Event_Viewer_Data->current_time.tv_nsec) @@ -941,14 +941,14 @@ void get_test_data(double time_value, guint List_Height, end.tv_sec = G_MAXULONG; end.tv_nsec = G_MAXULONG; start = Event_Viewer_Data->time_span.startTime; - value = (int)(time_value / NANSECOND_CONST); + value = (int)(time_value / NANOSECONDS_PER_SECOND); start.tv_sec += value; - value = time_value / NANSECOND_CONST - value; - value *= NANSECOND_CONST; + value = time_value / NANOSECONDS_PER_SECOND - value; + value *= NANOSECONDS_PER_SECOND; start.tv_nsec += value; - if(start.tv_nsec > NANSECOND_CONST){ + if(start.tv_nsec > NANOSECONDS_PER_SECOND){ start.tv_sec++; - start.tv_nsec -= NANSECOND_CONST; + start.tv_nsec -= NANOSECONDS_PER_SECOND; } Event_Viewer_Data->previous_value = time_value; get_events(Event_Viewer_Data, start, end, RESERVE_SMALL_SIZE,&size); @@ -990,7 +990,7 @@ void get_test_data(double time_value, guint List_Height, raw_data = (RawTraceData*)g_list_nth_data(first,Event_Number); value = raw_data->time.tv_sec; value -= Event_Viewer_Data->time_span.startTime.tv_sec; - value *= NANSECOND_CONST; + value *= NANOSECONDS_PER_SECOND; value -= Event_Viewer_Data->time_span.startTime.tv_nsec; value += raw_data->time.tv_nsec; Event_Viewer_Data->VAdjust_C->value = value; @@ -1014,7 +1014,7 @@ void get_test_data(double time_value, guint List_Height, // Add a new row to the model real_data = raw_data->time.tv_sec; - real_data *= NANSECOND_CONST; + real_data *= NANOSECONDS_PER_SECOND; real_data += raw_data->time.tv_nsec; gtk_list_store_append (Event_Viewer_Data->Store_M, &iter); gtk_list_store_set (Event_Viewer_Data->Store_M, &iter, @@ -1215,7 +1215,7 @@ gboolean updateCurrentTime(void * hook_data, void * call_data) { EventViewerData *Event_Viewer_Data = (EventViewerData*) hook_data; Event_Viewer_Data->current_time = *(LttTime*)call_data; - uint64_t nsec = Event_Viewer_Data->current_time.tv_sec * NANSECOND_CONST + uint64_t nsec = Event_Viewer_Data->current_time.tv_sec * NANOSECONDS_PER_SECOND + Event_Viewer_Data->current_time.tv_nsec; GtkTreeIter iter; uint64_t time; diff --git a/ltt/branches/poly/lttv/processTrace.c b/ltt/branches/poly/lttv/processTrace.c index 339bc1af..cb933556 100644 --- a/ltt/branches/poly/lttv/processTrace.c +++ b/ltt/branches/poly/lttv/processTrace.c @@ -92,23 +92,28 @@ init(LttvTracesetContext *self, LttvTraceset *ts) LttvTracefileContext *tfc; + LttTime null_time = {0, 0}; + nb_trace = lttv_traceset_number(ts); self->ts = ts; self->traces = g_new(LttvTraceContext *, nb_trace); self->before = lttv_hooks_new(); self->after = lttv_hooks_new(); self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + self->ts_a = lttv_traceset_attribute(ts); for(i = 0 ; i < nb_trace ; i++) { tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); self->traces[i] = tc; tc->ts_context = self; tc->index = i; - tc->t = lttv_traceset_get(ts, i); + tc->vt = lttv_traceset_get(ts, i); + tc->t = lttv_trace(tc->vt); tc->check = lttv_hooks_new(); tc->before = lttv_hooks_new(); tc->after = lttv_hooks_new(); tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + tc->t_a = lttv_trace_attribute(tc->vt); nb_control = ltt_trace_control_tracefile_number(tc->t); nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); nb_tracefile = nb_control + nb_per_cpu; @@ -141,6 +146,8 @@ init(LttvTracesetContext *self, LttvTraceset *ts) tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); } } + lttv_process_traceset_seek_time(self, null_time); + /*CHECK why dynamically allocate the time span... and the casing is wroNg*/ self->Time_Span = g_new(TimeInterval,1); lttv_traceset_context_compute_time_span(self, self->Time_Span); } @@ -480,11 +487,7 @@ lttv_tracefile_context_get_type(void) gint compare_tracefile(gconstpointer a, gconstpointer b) { - if(((LttvTime *)a)->tv_sec > ((LttvTime *)b)->tv_sec) return 1; - if(((LttvTime *)a)->tv_sec < ((LttvTime *)b)->tv_sec) return -1; - if(((LttvTime *)a)->tv_nsec > ((LttvTime *)b)->tv_nsec) return 1; - if(((LttvTime *)a)->tv_nsec < ((LttvTime *)b)->tv_nsec) return -1; - return 0; + return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); } @@ -494,8 +497,8 @@ gboolean get_first(gpointer key, gpointer value, gpointer user_data) { } -void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, - LttvTracesetContext *context, unsigned maxNumEvents) +void lttv_process_traceset(LttvTracesetContext *self, LttTime end, + unsigned maxNumEvents) { GPtrArray *traces = g_ptr_array_new(); @@ -514,19 +517,20 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, LttvTracefileContext *tfc; LttEvent *event; + unsigned count = 0; - LttTime preTimestamp; + + LttTime previous_timestamp = {0, 0}; /* Call all before_traceset, before_trace, and before_tracefile hooks. For all qualifying tracefiles, seek to the start time, create a context, read one event and insert in the pqueue based on the event time. */ - lttv_hooks_call(context->before, context); - nbi = lttv_traceset_number(traceset); - // nbi = ltt_trace_set_number(traceset); + lttv_hooks_call(self->before, self); + nbi = lttv_traceset_number(self->ts); for(i = 0 ; i < nbi ; i++) { - tc = context->traces[i]; + tc = self->traces[i]; trace = tc->t; if(!lttv_hooks_call_check(tc->check, tc)) { @@ -550,12 +554,7 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, g_ptr_array_add(tracefiles, tfc); lttv_hooks_call(tfc->before, tfc); - ltt_tracefile_seek_time(tracefile, start); - event = ltt_tracefile_read(tracefile); - tfc->e = event; - if(event != NULL) { - tfc->timestamp = ltt_event_time(event); g_tree_insert(pqueue, &(tfc->timestamp), tfc); } } @@ -573,14 +572,14 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, g_tree_foreach(pqueue, get_first, &tfc); if(tfc == NULL) break; - /* Get the tracefile with an event for the smallest time found. If two - or more tracefiles have events for the same time, hope that lookup - and remove are consistent. */ + /* Have we reached the maximum number of events specified? However, + continue for all the events with the same time stamp (CHECK?). Then, + empty the queue and break from the loop. */ count++; if(count > maxNumEvents){ - if(tfc->timestamp.tv_sec == preTimestamp.tv_sec && - tfc->timestamp.tv_nsec == preTimestamp.tv_nsec) { + if(tfc->timestamp.tv_sec == previous_timestamp.tv_sec && + tfc->timestamp.tv_nsec == previous_timestamp.tv_nsec) { count--; }else{ while(TRUE){ @@ -592,7 +591,12 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, break; } } - preTimestamp = tfc->timestamp; + previous_timestamp = tfc->timestamp; + + + /* Get the tracefile with an event for the smallest time found. If two + 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)); @@ -632,7 +636,7 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, } g_assert(j == tracefiles->len); - lttv_hooks_call(context->after, context); + lttv_hooks_call(self->after, self); /* Free the traces, tracefiles and pqueue */ @@ -641,6 +645,44 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, g_tree_destroy(pqueue); } + +void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileContext *tfc; + + LttEvent *event; + + nb_control = ltt_trace_control_tracefile_number(self->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->t); + nb_tracefile = nb_control + nb_per_cpu; + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfc = self->control_tracefiles[i]; + else tfc = self->per_cpu_tracefiles[i - nb_control]; + + ltt_tracefile_seek_time(tfc->tf, start); + event = ltt_tracefile_read(tfc->tf); + tfc->e = event; + if(event != NULL) tfc->timestamp = ltt_event_time(event); + } +} + + +void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start) +{ + guint i, nb_trace; + + LttvTraceContext *tc; + + nb_trace = lttv_traceset_number(self->ts); + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + lttv_process_trace_seek_time(tc, start); + } +} + + static LttField * find_field(LttEventType *et, const char *field) { diff --git a/ltt/branches/poly/lttv/state.c b/ltt/branches/poly/lttv/state.c index d53aef72..4176313c 100644 --- a/ltt/branches/poly/lttv/state.c +++ b/ltt/branches/poly/lttv/state.c @@ -2,6 +2,7 @@ #include #include #include +#include LttvExecutionMode LTTV_STATE_MODE_UNKNOWN, @@ -23,6 +24,12 @@ LttvProcessStatus LTTV_STATE_RUN; static GQuark + LTTV_STATE_TRACEFILES, + LTTV_STATE_PROCESSES, + LTTV_STATE_PROCESS, + LTTV_STATE_EVENT, + LTTV_STATE_SAVED_STATES, + LTTV_STATE_TIME, LTTV_STATE_HOOKS; @@ -30,11 +37,61 @@ static void fill_name_tables(LttvTraceState *tcs); static void free_name_tables(LttvTraceState *tcs); -static void remove_all_processes(GHashTable *processes); +static void lttv_state_free_process_table(GHashTable *processes); -LttvProcessState *create_process(LttvTracefileState *tfs, +static LttvProcessState *create_process(LttvTracefileState *tfs, LttvProcessState *parent, guint pid); +void lttv_state_save(LttvTraceState *self, LttvAttribute *container) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container); +} + + +void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); +} + + +void lttv_state_saved_state_free(LttvTraceState *self, + LttvAttribute *container) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); +} + + +static void +restore_init_state(LttvTraceState *self) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + LttTime null_time = {0,0}; + + if(self->processes != NULL) lttv_state_free_process_table(self->processes); + self->processes = g_hash_table_new(g_direct_hash, g_direct_equal); + self->nb_event = 0; + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) { + tfcs = LTTV_TRACEFILE_STATE(self->parent.control_tracefiles[i]); + } + else { + tfcs = LTTV_TRACEFILE_STATE(self->parent.per_cpu_tracefiles[i - nb_control]); + } + + tfcs->parent.timestamp = null_time; + tfcs->saved_position = 0; + tfcs->process = create_process(tfcs, NULL,0); + } +} + + static void init(LttvTracesetState *self, LttvTraceset *ts) { @@ -46,8 +103,6 @@ init(LttvTracesetState *self, LttvTraceset *ts) LttvTracefileState *tfcs; - LttTime timestamp = {0,0}; - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> init((LttvTracesetContext *)self, ts); @@ -55,7 +110,7 @@ init(LttvTracesetState *self, LttvTraceset *ts) for(i = 0 ; i < nb_trace ; i++) { tc = self->parent.traces[i]; tcs = (LttvTraceState *)tc; - tcs->processes = g_hash_table_new(g_direct_hash, g_direct_equal); + tcs->save_interval = 100000; fill_name_tables(tcs); nb_control = ltt_trace_control_tracefile_number(tc->t); @@ -68,11 +123,10 @@ init(LttvTracesetState *self, LttvTraceset *ts) else { tfcs = LTTV_TRACEFILE_STATE(tc->per_cpu_tracefiles[j - nb_control]); } - - tfcs->parent.timestamp = timestamp; - tfcs->process = create_process(tfcs, NULL,0); tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf)); } + tcs->processes = NULL; + restore_init_state(tcs); } } @@ -89,8 +143,8 @@ fini(LttvTracesetState *self) 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]); - remove_all_processes(tcs->processes); - g_hash_table_destroy(tcs->processes); + 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))-> @@ -119,149 +173,202 @@ new_tracefile_context(LttvTracesetContext *self) } -static void -traceset_state_instance_init (GTypeInstance *instance, gpointer g_class) +static void copy_process_state(gpointer key, gpointer value,gpointer user_data) { -} + LttvProcessState *process, *new_process; + GHashTable *new_processes = (GHashTable *)user_data; -static void -traceset_state_finalize (LttvTracesetState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); + guint i; + + process = (LttvProcessState *)value; + new_process = g_new(LttvProcessState, 1); + *new_process = *process; + new_process->execution_stack = g_array_new(FALSE, FALSE, + sizeof(LttvExecutionState)); + g_array_set_size(new_process->execution_stack,process->execution_stack->len); + for(i = 0 ; i < process->execution_stack->len; i++) { + g_array_index(new_process->execution_stack, LttvExecutionState, i) = + g_array_index(process->execution_stack, LttvExecutionState, i); + } + new_process->state = &g_array_index(new_process->execution_stack, + LttvExecutionState, new_process->execution_stack->len - 1); + g_hash_table_insert(new_processes, GUINT_TO_POINTER(new_process->pid), + new_process); } -static void -traceset_state_class_init (LttvTracesetContextClass *klass) +static GHashTable *lttv_state_copy_process_table(GHashTable *processes) { - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + GHashTable *new_processes = g_hash_table_new(g_direct_hash, g_direct_equal); - gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize; - klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; - klass->fini = (void (*)(LttvTracesetContext *self))fini; - klass->new_traceset_context = new_traceset_context; - klass->new_trace_context = new_trace_context; - klass->new_tracefile_context = new_tracefile_context; + g_hash_table_foreach(processes, copy_process_state, new_processes); + return new_processes; } -GType -lttv_traceset_state_get_type(void) +/* The saved state for each trace contains a member "processes", which + stores a copy of the process table, and a member "tracefiles" with + one entry per tracefile. Each tracefile has a "process" member pointing + to the current process and a "position" member storing the tracefile + position (needed to seek to the current "next" event. */ + +static void state_save(LttvTraceState *self, LttvAttribute *container) { - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracesetStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) traceset_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracesetContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) traceset_state_instance_init /* instance_init */ - }; + guint i, nb_control, nb_per_cpu, nb_tracefile; - type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType", - &info, 0); + LttvTracefileState *tfcs; + + LttvAttribute *tracefiles_tree, *tracefile_tree; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttEventPosition *ep; + + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); + + value = lttv_attribute_add(container, LTTV_STATE_PROCESSES, + LTTV_POINTER); + *(value.v_pointer) = lttv_state_copy_process_table(self->processes); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) + tfcs = (LttvTracefileState *)self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + value = lttv_attribute_add(tracefiles_tree, i, + LTTV_GOBJECT); + *(value.v_gobject) = (GObject *)tracefile_tree; + value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS, + LTTV_UINT); + *(value.v_uint) = tfcs->process->pid; + value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT, + LTTV_POINTER); + if(tfcs->parent.e == NULL) *(value.v_pointer) = NULL; + else { + ep = g_new(LttEventPosition, 1); + ltt_event_position(tfcs->parent.e, ep); + *(value.v_pointer) = ep; + } } - return type; } -static void -trace_state_instance_init (GTypeInstance *instance, gpointer g_class) +static void state_restore(LttvTraceState *self, LttvAttribute *container) { -} + guint i, nb_control, nb_per_cpu, nb_tracefile; + LttvTracefileState *tfcs; -static void -trace_state_finalize (LttvTraceState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); -} + LttvAttribute *tracefiles_tree, *tracefile_tree; + LttvAttributeType type; -static void -trace_state_class_init (LttvTraceContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + LttvAttributeValue value; - gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize; -} + LttvAttributeName name; + LttEventPosition *ep; -GType -lttv_trace_state_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTraceStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) trace_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTraceState), - 0, /* n_preallocs */ - (GInstanceInitFunc) trace_state_instance_init /* instance_init */ - }; + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); - type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE, - "LttvTraceStateType", &info, 0); + type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, + &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_process_table(self->processes); + self->processes = lttv_state_copy_process_table(*(value.v_pointer)); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfcs = (LttvTracefileState *) + self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + type = lttv_attribute_get(tracefiles_tree, i, &name, &value); + g_assert(type == LTTV_GOBJECT); + tracefile_tree = *((LttvAttribute **)(value.v_gobject)); + + type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS, + &value); + g_assert(type == LTTV_UINT); + tfcs->process = lttv_state_find_process(tfcs, *(value.v_uint)); + type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, + &value); + g_assert(type == LTTV_POINTER); + if(*(value.v_pointer) == NULL) tfcs->parent.e = NULL; + else { + ep = *(value.v_pointer); + ltt_tracefile_seek_position(tfcs->parent.tf, ep); + tfcs->parent.e = ltt_tracefile_read(tfcs->parent.tf); + tfcs->parent.timestamp = ltt_event_time(tfcs->parent.e); + } } - return type; } -static void -tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class) +static void state_saved_free(LttvTraceState *self, LttvAttribute *container) { -} + guint i, nb_control, nb_per_cpu, nb_tracefile; + LttvTracefileState *tfcs; -static void -tracefile_state_finalize (LttvTracefileState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); -} + LttvAttribute *tracefiles_tree, *tracefile_tree; + LttvAttributeType type; -static void -tracefile_state_class_init (LttvTracefileStateClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + LttvAttributeValue value; - gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize; -} + LttvAttributeName name; + LttEventPosition *ep; -GType -lttv_tracefile_state_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracefileStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) tracefile_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracefileState), - 0, /* n_preallocs */ - (GInstanceInitFunc) tracefile_state_instance_init /* instance_init */ - }; + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); + lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES); - type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE, - "LttvTracefileStateType", &info, 0); + type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, + &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_process_table(*(value.v_pointer)); + *(value.v_pointer) = NULL; + lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfcs = (LttvTracefileState *) + self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + type = lttv_attribute_get(tracefiles_tree, i, &name, &value); + g_assert(type == LTTV_GOBJECT); + tracefile_tree = *((LttvAttribute **)(value.v_gobject)); + + type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, + &value); + g_assert(type == LTTV_POINTER); + if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer)); } - return type; + lttv_attribute_recursive_free(tracefiles_tree); } @@ -412,7 +519,7 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) } -LttvProcessState *create_process(LttvTracefileState *tfs, +static LttvProcessState *create_process(LttvTracefileState *tfs, LttvProcessState *parent, guint pid) { LttvProcessState *process = g_new(LttvProcessState, 1); @@ -458,7 +565,8 @@ LttvProcessState *create_process(LttvTracefileState *tfs, } -LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, guint pid) +LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, + guint pid) { LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context; LttvProcessState *process = g_hash_table_lookup(ts->processes, @@ -485,9 +593,10 @@ static void free_process_state(gpointer key, gpointer value,gpointer user_data) } -static void remove_all_processes(GHashTable *processes) +static void lttv_state_free_process_table(GHashTable *processes) { g_hash_table_foreach(processes, free_process_state, NULL); + g_hash_table_destroy(processes); } @@ -621,22 +730,16 @@ static gboolean process_exit(void *hook_data, void *call_data) } -lttv_state_add_event_hooks(LttvTracesetState *self) +void lttv_state_add_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - LttFacility *f; - - LttEventType *et; - LttvTraceState *ts; LttvTracefileState *tfs; - void *hook_data; - GArray *hooks; LttvTraceHook hook; @@ -705,7 +808,7 @@ lttv_state_add_event_hooks(LttvTracesetState *self) } -lttv_state_remove_event_hooks(LttvTracesetState *self) +void lttv_state_remove_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; @@ -715,8 +818,6 @@ lttv_state_remove_event_hooks(LttvTracesetState *self) LttvTracefileState *tfs; - void *hook_data; - GArray *hooks; LttvTraceHook hook; @@ -754,6 +855,315 @@ lttv_state_remove_event_hooks(LttvTracesetState *self) } +static gboolean block_end(void *hook_data, void *call_data) +{ + LttvTracefileState *tfcs = (LttvTracefileState *)call_data; + + LttvTraceState *tcs = (LttvTraceState *)(tfcs->parent.t_context); + + LttEventPosition ep; + + guint nb_block, nb_event; + + LttTracefile *tf; + + LttvAttribute *saved_states_tree, *saved_state_tree; + + LttvAttributeValue value; + + ltt_event_position(tfcs->parent.e, &ep); + + ltt_event_position_get(&ep, &nb_block, &nb_event, &tf); + tcs->nb_event += nb_event - tfcs->saved_position; + tfcs->saved_position = 0; + if(tcs->nb_event >= tcs->save_interval) { + saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, + LTTV_STATE_SAVED_STATES); + saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + value = lttv_attribute_add(saved_states_tree, + lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT); + *(value.v_gobject) = (GObject *)saved_state_tree; + value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME); + *(value.v_time) = tfcs->parent.timestamp; + lttv_state_save(tcs, saved_state_tree); + tcs->nb_event = 0; + } + return FALSE; +} + + +void lttv_state_save_add_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + LttvTraceHook hook; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = (LttvTraceState *)self->parent.traces[i]; + lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, + NULL, NULL, block_end, &hook); + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, + hook.id), hook.h, NULL); + } + } +} + + +void lttv_state_save_remove_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + LttvTraceHook hook; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = LTTV_TRACE_STATE(self->parent.traces[i]); + lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, + NULL, NULL, block_end, &hook); + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + lttv_hooks_remove_data(lttv_hooks_by_id_find( + tfs->parent.after_event_by_id, hook.id), hook.h, NULL); + } + } +} + + +void lttv_state_restore_closest_state(LttvTracesetState *self, LttTime t) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, nb_trace, nb_saved_state; + + int min_pos, mid_pos, max_pos; + + LttvTraceState *tcs; + + LttvAttributeValue value; + + LttvAttributeType type; + + LttvAttributeName name; + + LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceState *)self->parent.traces[i]; + + saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, + LTTV_STATE_SAVED_STATES); + min_pos = -1; + max_pos = lttv_attribute_get_number(saved_states_tree) - 1; + mid_pos = max_pos / 2; + while(min_pos < max_pos) { + type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value); + g_assert(type == LTTV_GOBJECT); + saved_state_tree = *((LttvAttribute **)(value.v_gobject)); + type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME, + &value); + g_assert(type == LTTV_TIME); + if(ltt_time_compare(*(value.v_time), t) < 0) { + min_pos = mid_pos; + closest_tree = saved_state_tree; + } + else max_pos = mid_pos - 1; + + mid_pos = (min_pos + max_pos + 1) / 2; + } + if(min_pos == -1) { + restore_init_state(tcs); + lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero); + } + else lttv_state_restore(tcs, closest_tree); + } +} + + +static void +traceset_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +traceset_state_finalize (LttvTracesetState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +traceset_state_class_init (LttvTracesetContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize; + klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; + klass->fini = (void (*)(LttvTracesetContext *self))fini; + klass->new_traceset_context = new_traceset_context; + klass->new_trace_context = new_trace_context; + klass->new_tracefile_context = new_tracefile_context; +} + + +GType +lttv_traceset_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracesetStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) traceset_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracesetContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) traceset_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType", + &info, 0); + } + return type; +} + + +static void +trace_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +trace_state_finalize (LttvTraceState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +trace_state_class_init (LttvTraceStateClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize; + klass->state_save = state_save; + klass->state_restore = state_restore; + klass->state_saved_free = state_saved_free; +} + + +GType +lttv_trace_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTraceStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) trace_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTraceState), + 0, /* n_preallocs */ + (GInstanceInitFunc) trace_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE, + "LttvTraceStateType", &info, 0); + } + return type; +} + + +static void +tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +tracefile_state_finalize (LttvTracefileState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +tracefile_state_class_init (LttvTracefileStateClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize; +} + + +GType +lttv_tracefile_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracefileStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) tracefile_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracefileState), + 0, /* n_preallocs */ + (GInstanceInitFunc) tracefile_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE, + "LttvTracefileStateType", &info, 0); + } + return type; +} + + void lttv_state_init(int argc, char **argv) { LTTV_STATE_UNNAMED = g_quark_from_string("unnamed"); @@ -769,6 +1179,12 @@ void lttv_state_init(int argc, char **argv) LTTV_STATE_EXIT = g_quark_from_string("exiting"); LTTV_STATE_WAIT = g_quark_from_string("wait for I/O"); LTTV_STATE_RUN = g_quark_from_string("running"); + LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles"); + LTTV_STATE_PROCESSES = g_quark_from_string("processes"); + LTTV_STATE_PROCESS = g_quark_from_string("process"); + LTTV_STATE_EVENT = g_quark_from_string("event"); + LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states"); + LTTV_STATE_TIME = g_quark_from_string("time"); LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks"); } diff --git a/ltt/branches/poly/lttv/stats.c b/ltt/branches/poly/lttv/stats.c index 311658c1..eaa2041c 100644 --- a/ltt/branches/poly/lttv/stats.c +++ b/ltt/branches/poly/lttv/stats.c @@ -327,9 +327,9 @@ static void mode_change(LttvTracefileStats *tfcs) lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, LTTV_TIME, &cpu_time); - TimeSub(delta, tfcs->parent.parent.timestamp, + delta = ltt_time_sub(tfcs->parent.parent.timestamp, tfcs->parent.process->state->change); - TimeAdd(*(cpu_time.v_time), *(cpu_time.v_time), delta); + *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); } @@ -341,15 +341,15 @@ static void mode_end(LttvTracefileStats *tfcs) lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME, LTTV_TIME, &elapsed_time); - TimeSub(delta, tfcs->parent.parent.timestamp, + delta = ltt_time_sub(tfcs->parent.parent.timestamp, tfcs->parent.process->state->entry); - TimeAdd(*(elapsed_time.v_time), *(elapsed_time.v_time), delta); + *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta); lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, LTTV_TIME, &cpu_time); - TimeSub(delta, tfcs->parent.parent.timestamp, + delta = ltt_time_sub(tfcs->parent.parent.timestamp, tfcs->parent.process->state->change); - TimeAdd(*(cpu_time.v_time), *(cpu_time.v_time), delta); + *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); } diff --git a/ltt/branches/poly/lttv/textDump.c b/ltt/branches/poly/lttv/textDump.c index 73cd5b90..dbdd2536 100644 --- a/ltt/branches/poly/lttv/textDump.c +++ b/ltt/branches/poly/lttv/textDump.c @@ -316,6 +316,8 @@ G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv) g_info("Init textDump.c"); + lttv_module_require(self, "libbatchAnalysis", argc, argv); + a_string = g_string_new(""); a_file_name = NULL; diff --git a/ltt/branches/poly/lttv/traceset.c b/ltt/branches/poly/lttv/traceset.c index aee03471..2192d212 100644 --- a/ltt/branches/poly/lttv/traceset.c +++ b/ltt/branches/poly/lttv/traceset.c @@ -11,7 +11,12 @@ struct _LttvTraceset { char * filename; GPtrArray *traces; - GPtrArray *attributes; + LttvAttribute *a; +}; + + +struct _LttvTrace { + LttTrace *t; LttvAttribute *a; }; @@ -23,11 +28,21 @@ LttvTraceset *lttv_traceset_new() s = g_new(LttvTraceset, 1); s->filename = NULL; s->traces = g_ptr_array_new(); - s->attributes = g_ptr_array_new(); s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); return s; } +LttvTrace *lttv_trace_new(LttTrace *t) +{ + LttvTrace *new_trace; + + new_trace = g_new(LttvTrace, 1); + new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + new_trace->t = t; + return new_trace; +} + + LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) { int i; @@ -38,18 +53,12 @@ LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) s->traces = g_ptr_array_new(); for(i=0;itraces->len;i++) { + /*CHECK this used ltt_trace_copy while it may not be needed. Need to + define how traces and tracesets are shared */ g_ptr_array_add( s->traces, - ltt_trace_copy(g_ptr_array_index(s_orig->traces, i))); - } - s->attributes = g_ptr_array_new(); - for(i=0;iattributes->len;i++) - { - g_ptr_array_add( - s->attributes, - lttv_iattribute_deep_copy(g_ptr_array_index(s_orig->attributes, i))); + g_ptr_array_index(s_orig->traces, i)); } - s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a))); return s; } @@ -80,23 +89,24 @@ gint lttv_traceset_save(LttvTraceset *s) fclose(tf); return 0; } + void lttv_traceset_destroy(LttvTraceset *s) { - int i, nb; - - for(i = 0 ; i < s->attributes->len ; i++) { - g_object_unref((LttvAttribute *)s->attributes->pdata[i]); - } - g_ptr_array_free(s->attributes, TRUE); g_ptr_array_free(s->traces, TRUE); g_object_unref(s->a); g_free(s); } -void lttv_traceset_add(LttvTraceset *s, LttTrace *t) +void lttv_trace_destroy(LttvTrace *t) +{ + g_object_unref(t->a); + g_free(t); +} + + +void lttv_traceset_add(LttvTraceset *s, LttvTrace *t) { g_ptr_array_add(s->traces, t); - g_ptr_array_add(s->attributes, g_object_new(LTTV_ATTRIBUTE_TYPE, NULL)); } @@ -106,18 +116,16 @@ unsigned lttv_traceset_number(LttvTraceset *s) } -LttTrace *lttv_traceset_get(LttvTraceset *s, unsigned i) +LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i) { g_assert(s->traces->len > i); - return ((LttTrace *)s->traces->pdata[i]); + return ((LttvTrace *)s->traces->pdata[i]); } void lttv_traceset_remove(LttvTraceset *s, unsigned i) { g_ptr_array_remove_index(s->traces, i); - g_object_unref(s->attributes->pdata[i]); - g_ptr_array_remove_index(s->attributes,i); } @@ -130,7 +138,14 @@ LttvAttribute *lttv_traceset_attribute(LttvTraceset *s) } -LttvAttribute *lttv_traceset_trace_attribute(LttvTraceset *s, unsigned i) +LttvAttribute *lttv_trace_attribute(LttvTrace *t) +{ + return t->a; +} + + +LttTrace *lttv_trace(LttvTrace *t) { - return (LttvAttribute *)s->attributes->pdata[i]; + return t->t; } + -- 2.34.1