facility.h\
ltt-private.h\
ltt.h\
+ time.h\
trace.h\
type.h
#ifndef LTT_H
#define LTT_H
+#include <ltt/time.h>
#include <ltt/LTTTypes.h>
/* A trace is associated with a tracing session run on a single, possibly
/* 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;
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. */
{ 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 <ltt/ltt-private.h>
--- /dev/null
+#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
#include <glib-object.h>
-#include <time.h>
+#include <ltt/time.h>
/* 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
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
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;
LttvHooks *after;
LttvTraceContext **traces;
LttvAttribute *a;
+ LttvAttribute *ts_a;
TimeInterval *Time_Span;
};
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 {
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,
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;
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
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;
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))
LttvProcessState *process;
GQuark cpu_name;
+ guint saved_position;
};
struct _LttvTracefileStateClass {
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);
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);
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
/* go to the next event */
int skipEvent(LttTracefile * t);
-/* compare two time (LttTime), 0:t1=t2, -1:t1<t2, 1:t1>t2 */
-int timecmp(LttTime * t1, LttTime * t2);
-
-
/*****************************************************************************
*Function name
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;i<t->per_cpu_tracefile_number;i++){
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;
{
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);
return;
}
lttTime = getEventTime(t);
- err = timecmp(<tTime, &time);
+ err = ltt_time_compare(lttTime, time);
if(err >= 0)return;
}
}else return;
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) ;
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;
/* 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;
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;
}
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
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;
*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;
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));
}
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");
{
guint i, nb;
+ LttvTrace *trace;
+
g_info("Destroy batchAnalysis.c");
lttv_option_remove("trace");
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);
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. */
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");
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 */
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);
}
/**
GtkWidget * w;
TimeWindow Time_Window;
LttTime time;
- double tmpValue;
TimeInterval *Time_Span;
g_return_if_fail(GTK_IS_CUSTOM(custom));
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);
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);
}
*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);
}
/*****************************************************************************
G_MODULE_EXPORT void destroy() {
LttvAttributeValue value;
+ LttvTrace *trace;
lttv_option_remove("trace");
/* 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,
{
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);
}
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);
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;
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)
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);
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;
// 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,
{
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;
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;
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);
}
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));
}
}
-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();
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)) {
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);
}
}
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){
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));
}
g_assert(j == tracefiles->len);
- lttv_hooks_call(context->after, context);
+ lttv_hooks_call(self->after, self);
/* Free the traces, tracefiles and pqueue */
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)
{
#include <lttv/state.h>
#include <ltt/facility.h>
#include <ltt/trace.h>
+#include <ltt/event.h>
LttvExecutionMode
LTTV_STATE_MODE_UNKNOWN,
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;
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)
{
LttvTracefileState *tfcs;
- LttTime timestamp = {0,0};
-
LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
init((LttvTracesetContext *)self, 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);
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);
}
}
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))->
}
-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);
}
}
-LttvProcessState *create_process(LttvTracefileState *tfs,
+static LttvProcessState *create_process(LttvTracefileState *tfs,
LttvProcessState *parent, guint pid)
{
LttvProcessState *process = g_new(LttvProcessState, 1);
}
-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,
}
-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);
}
}
-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;
}
-lttv_state_remove_event_hooks(LttvTracesetState *self)
+void lttv_state_remove_event_hooks(LttvTracesetState *self)
{
LttvTraceset *traceset = self->parent.ts;
LttvTracefileState *tfs;
- void *hook_data;
-
GArray *hooks;
LttvTraceHook hook;
}
+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");
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");
}
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);
}
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);
}
g_info("Init textDump.c");
+ lttv_module_require(self, "libbatchAnalysis", argc, argv);
+
a_string = g_string_new("");
a_file_name = NULL;
struct _LttvTraceset {
char * filename;
GPtrArray *traces;
- GPtrArray *attributes;
+ LttvAttribute *a;
+};
+
+
+struct _LttvTrace {
+ LttTrace *t;
LttvAttribute *a;
};
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;
s->traces = g_ptr_array_new();
for(i=0;i<s_orig->traces->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;i<s_orig->attributes->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;
}
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));
}
}
-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);
}
}
-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;
}
+