2 #include "ltt_module.h"
4 /* This module dumps all events in a simple ascii format */
10 static gchar
*dump_file
= NULL
;
12 static FILE *dump_fp
= stdout
;
15 ascii_dump_option
= { "ascii-dump", 'd', POPT_ARG_NONE
, &ascii_dump
, 0},
16 ascii_dump_option
= { "dump-file", 'f', POPT_ARG_STRING
, &dump_file
, 0},
17 syscall_stats_option
= { "syscall-stats", 's', POPT_ARG_NONE
,
20 static void after_options_hook(gpointer hook_data
, gpointer call_data
);
22 static void before_trace_hook(gpointer hook_data
, gpointer call_data
);
24 static void after_trace_hook(gpointer hook_data
, gpointer call_data
);
26 static void events_hook(gpointer hook_data
, gpointer call_data
);
28 void init(int argc
, char **argv
)
30 ltt_add_command_option(&ascii_dump_option
);
31 ltt_add_command_option(&syscall_stats_option
);
32 ltt_add_hook(ltt_after_options_hooks
,after_options_hook
,NULL
)
35 /* Check the command line options and insert hooks to do the work */
37 static void after_options_hook(gpointer hook_data
, gpointer call_data
)
39 if(ascii_dump_option
|| syscall_stats
) {
40 ltt_add_hook(ltt_before_process_each_trace_hooks
,before_trace_hook
,NULL
);
41 if(dump_file
!= NULL
) {
42 dump_fp
= fopen(dump_file
,"w");
43 if(dump_fp
== NULL
) g_critical("cannot open output file %s",dump_file
);
45 ltt_add_hook(ltt_after_process_each_trace_hooks
,after_trace_hook
,NULL
);
49 /* Insert the hooks to print the events and compute and print the statistics */
51 static unsigned *eventsCounters
;
54 lttProcess
*current_process
;
59 static void before_trace_hook(gpointer hook_data
, gpointer call_data
) {
60 ltt_add_hook(ltt_trace_events_hooks
,events_hooks
,NULL
);
61 fprintf(dump_fp
,"Trace %s\n",(struct trace
*)call_data
->name
);
63 if(ascii_dump
) fprintf(dump_fp
,"\nEvents\n");
65 /* To gather stats, register a few hooks */
68 eventsCounters
= g_new0(unsigned,nbEventType
);
69 CPUStates
= g_new0(struct CPUState
, nbCPU
);
70 /* initialize the state of each CPU and associated process */
75 /* Print the events */
77 static void events_hook(gpointer hook_data
, gpointer call_data
)
83 event
= (struct_event
*)call_data
;
86 fprintf(dump_fp
,"\n%s.%s t=%d.%d CPU%d",event
->facility_handle
->name
,
87 event
->event_handle
->name
, event
->time
.tv_seconds
,
88 event
->time
.tv_nanoseconds
,event
->CPU_id
);
90 for(i
= 0 ; i
< event
->base_field
->nb_elements
; i
++) {
91 field
= event
->base_field
->fields
+ i
;
92 fprintf(dump_fp
," %s=",field
->name
);
95 fprintf(dump_fp
,"%d",ltt_get_integer(field
,event
->data
));
98 fprintf(dump_fp
,"%u",ltt_get_uinteger(field
,event
->data
));
101 fprintf(dump_fp
,"%lg",ltt_get_float(field
,event
->data
));
104 fprintf(dump_fp
,"%g",ltt_get_double(field
,event
->data
));
107 fprintf(dump_fp
,"%s",ltt_get_string(field
,event
->data
));
110 fprintf(dump_fp
,"%d",ltt_get_integer(field
,event
->data
));
113 fprintf(dump_fp
,"<nested array>");
116 fprintf(dump_fp
,"<nested sequence>");
119 fprintf(dump_fp
,"<nested struct>");
125 /* Collect statistics about each event type */
128 /* Get the key for the corresponding CPU. It already contains the
129 path components for the ip, CPU, process, state, subState.
130 We add the event id and increment the statistic with that key. */
132 key
= (GQuark
*)CPUStates
[event
->CPUid
]->key1
;
134 path
[5] = eventsQuark
[event
->id
];
135 pval
= ltt_get_integer(currentStats
,key
);
138 /* Count the time spent in the current state. Could be done only
139 at state changes to optimize. */
141 key
= (GQuark
*)CPUStates
[event
->CPUid
]->key2
;
143 ptime
= ltt_get_time(currentStats
,key
);
144 (*ptime
) = ltt_add_time((*ptime
),ltt_sub_time(lastTime
,event
->time
));
148 /* Specific hooks to note process and state changes, compute the following values: number of bytes read/written,
149 time elapsed, user, system, waiting, time spent in each system call,
150 name for each process. */
152 maintain the process table
, process state
, last time
... what we are waiting
for
160 sched_change_hook
-> not waiting
161 fork_hook
-> wait fork
163 wakeup_hook
-> not waiting add up waiting time
165 exec_hook
-> note file name
166 open_hook
-> keep track of fd
/name
167 close_hook
-> keep track of fd
168 read_hook
-> bytes read
, if server CPU
for client
...
169 write_hook
-> bytes written
170 select_hook
-> wait reason
171 poll_hook
-> wait reason
172 mmap_hook
-> keep track of fd
173 munmap_hook
-> keep track of fd
174 setitimer_hook
-> wait reason
175 settimeout_hook
-> wait reason
176 sockcreate_hook
-> client
/server
177 sockbind_hook
-> client
/server
178 sockaccept_hook
-> client
/server
179 sockconnect_hook
-> client
/server
180 /* Close the output file and print the statistics, globally for all CPUs and
181 processes, per CPU, per process. */
183 static void after_trace_hook(gpointer hook_data
, gpointer call_data
)
187 unsigned nbEvents
= 0;
189 t
= (lttTrace
*)call_data
;
191 fprintf(dump_fp
,"\n");
195 fprintf(dump_fp
,"\n\nStatistics\n\n");
197 /* Trace start, end and duration */
199 fprintf(dump_fp
,"Trace started %s, ended %s, duration %s",
200 ltt_format_time(t
->startTime
),ltt_format_time(t
->endTime
),
201 ltt_format_time(ltt_sub_time(t
->endTime
,t
->startTime
)));
203 /* Number of events of each type */
205 for(i
= 0 ; i
< t
->nbEventTypes
; i
++) {
206 nbEvents
+= eventsCounters
[i
];
207 if(eventsCounters
[i
] > 0)
208 fprintf(dump_fp
,"%s: %u\n",t
->types
[i
]->name
,eventsCounters
[i
]);
210 fprintf(dump_fp
,"\n\nTotal number of events: %u\n",nbEvents
);
212 /* Print the details for each process */