Enable support for opening multiple trace
[lttv.git] / lttv / modules / gui / controlflow / eventhooks.c
CommitLineData
ce0214a6 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19
f0d936c0 20/*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
f0d936c0 24
b9a010a2 25/* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
27 *
e92eabaf 28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
b9a010a2 31 *
e92eabaf 32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
b9a010a2 34 *
e92eabaf 35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
b9a010a2 37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
e92eabaf 40 * corresponding to it is over, which happens to be at the next before_schedchange
b9a010a2 41 * hook.
42 *
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
45 * line/background.
46 */
47
4e4d11b3 48#ifdef HAVE_CONFIG_H
49#include <config.h>
50#endif
b9a010a2 51
cf6cb7e0 52//#define PANGO_ENABLE_BACKEND
558aa013 53#include <gtk/gtk.h>
54#include <gdk/gdk.h>
5f16133f 55#include <glib.h>
80a52ff8 56#include <assert.h>
50439712 57#include <string.h>
319e9d81 58#include <stdio.h>
5f16133f 59
cf6cb7e0 60//#include <pango/pango.h>
61
80a52ff8 62#include <ltt/event.h>
4ba42155 63#include <ltt/time.h>
2c82c4dc 64#include <ltt/trace.h>
80a52ff8 65
2a2fa4f0 66#include <lttv/lttv.h>
558aa013 67#include <lttv/hook.h>
80a52ff8 68#include <lttv/state.h>
2d262115 69#include <lttvwindow/lttvwindow.h>
6395d57c 70#include <lttvwindow/lttvwindowtraces.h>
0de51231 71#include <lttvwindow/support.h>
80a52ff8 72
f0d936c0 73
a117e3f7 74#include "eventhooks.h"
75#include "cfv.h"
76#include "processlist.h"
77#include "drawing.h"
5f16133f 78
80a52ff8 79
1a31868c 80#define MAX_PATH_LEN 256
98dfb302 81#define STATE_LINE_WIDTH 8
5bb606ce 82#define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
1a31868c 83
0de51231 84extern GSList *g_legend_list;
85
b9a010a2 86
6395d57c 87/* Action to do when background computation completed.
88 *
e800cf84 89 * Wait for all the awaited computations to be over.
6395d57c 90 */
91
703b25fa 92static gint background_ready(void *hook_data, void *call_data)
6395d57c 93{
94 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
6395d57c 95
e800cf84 96 control_flow_data->background_info_waiting--;
97
98 if(control_flow_data->background_info_waiting == 0) {
4a24fa1f 99 g_message("control flow viewer : background computation data ready.");
6395d57c 100
e800cf84 101 drawing_clear(control_flow_data->drawing);
102 processlist_clear(control_flow_data->process_list);
07390ec1 103 gtk_widget_set_size_request(
104 control_flow_data->drawing->drawing_area,
105 -1, processlist_get_height(control_flow_data->process_list));
e800cf84 106 redraw_notify(control_flow_data, NULL);
b9a010a2 107 }
6395d57c 108
109 return 0;
110}
111
112
113/* Request background computation. Verify if it is in progress or ready first.
e800cf84 114 * Only for each trace in the tab's traceset.
6395d57c 115 */
88bf15f0 116
3f7f592e 117static void request_background_data(ControlFlowData *control_flow_data)
6395d57c 118{
88bf15f0
FD
119
120 LttvTraceset *ts = lttvwindow_get_traceset(control_flow_data->tab);
121 gint num_traces = lttv_traceset_number(ts);
6395d57c 122 gint i;
123 LttvTrace *trace;
7df20ca4 124 LttvTraceState *tstate;
6395d57c 125
88bf15f0 126 LttvHooks *background_ready_hook = lttv_hooks_new();
6395d57c 127 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
128 LTTV_PRIO_DEFAULT);
e800cf84 129 control_flow_data->background_info_waiting = 0;
6395d57c 130
131 for(i=0;i<num_traces;i++) {
88bf15f0 132 trace = lttv_traceset_get(ts, i);
dd47d0d8 133
7df20ca4 134 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE
88bf15f0 135 && !ts->has_precomputed_states) {
6395d57c 136
137 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
138 trace) == FALSE) {
139 /* We first remove requests that could have been done for the same
140 * information. Happens when two viewers ask for it before servicing
141 * starts.
142 */
93ac601b 143 if(!lttvwindowtraces_background_request_find(trace, "state"))
b5e17af5 144 lttvwindowtraces_background_request_queue(
145 main_window_get_widget(control_flow_data->tab), trace, "state");
6395d57c 146 lttvwindowtraces_background_notify_queue(control_flow_data,
147 trace,
148 ltt_time_infinite,
149 NULL,
150 background_ready_hook);
e800cf84 151 control_flow_data->background_info_waiting++;
6395d57c 152 } else { /* in progress */
153
154 lttvwindowtraces_background_notify_current(control_flow_data,
155 trace,
156 ltt_time_infinite,
157 NULL,
158 background_ready_hook);
e800cf84 159 control_flow_data->background_info_waiting++;
6395d57c 160 }
4368b993 161 } else {
7df20ca4 162 /* Data ready. By its nature, this viewer doesn't need to have
618fbcc1 163 * its data ready hook called there, because a background
4368b993 164 * request is always linked with a redraw.
165 */
6395d57c 166 }
4368b993 167
6395d57c 168 }
169
170 lttv_hooks_destroy(background_ready_hook);
171}
172
173
174
175
f0d936c0 176/**
177 * Event Viewer's constructor hook
178 *
179 * This constructor is given as a parameter to the menuitem and toolbar button
180 * registration. It creates the list.
ca0f8a8e 181 * @param tab A pointer to the parent tab.
f0d936c0 182 * @return The widget created.
183 */
184GtkWidget *
e433e6d6 185h_guicontrolflow(LttvPlugin *plugin)
f0d936c0 186{
e433e6d6 187 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
188 Tab *tab = ptab->tab;
d47b33d2 189 g_info("h_guicontrolflow, %p", tab);
e433e6d6 190 ControlFlowData *control_flow_data = guicontrolflow(ptab);
a56a1ba4 191
ca0f8a8e 192 control_flow_data->tab = tab;
a56a1ba4 193
a56a1ba4 194 // Unreg done in the GuiControlFlow_Destructor
6395d57c 195 lttvwindow_register_traceset_notify(tab,
196 traceset_notify,
197 control_flow_data);
198
ca0f8a8e 199 lttvwindow_register_time_window_notify(tab,
224446ce 200 update_time_window_hook,
201 control_flow_data);
ca0f8a8e 202 lttvwindow_register_current_time_notify(tab,
224446ce 203 update_current_time_hook,
204 control_flow_data);
ca0f8a8e 205 lttvwindow_register_redraw_notify(tab,
206 redraw_notify,
207 control_flow_data);
208 lttvwindow_register_continue_notify(tab,
209 continue_notify,
210 control_flow_data);
667ca2a0 211 request_background_data(control_flow_data);
6395d57c 212
ca0f8a8e 213
68997a22 214 return guicontrolflow_get_widget(control_flow_data) ;
a56a1ba4 215
f0d936c0 216}
217
3cff8cc1 218int event_selected_hook(void *hook_data, void *call_data)
f0d936c0 219{
14963be0 220 guint *event_number = (guint*) call_data;
f0d936c0 221
2a2fa4f0 222 g_debug("DEBUG : event selected by main window : %u", *event_number);
a56a1ba4 223
2eef04b5 224 return 0;
f0d936c0 225}
226
9a1ec01b 227/* Function that selects the color of status&exemode line */
6550d711 228static inline PropertiesLine prepare_s_e_line(LttvProcessState *process)
9a1ec01b 229{
230 PropertiesLine prop_line;
5bb606ce 231 prop_line.line_width = STATE_LINE_WIDTH;
9a1ec01b 232 prop_line.style = GDK_LINE_SOLID;
233 prop_line.y = MIDDLE;
234 //GdkColormap *colormap = gdk_colormap_get_system();
235
9a1ec01b 236 if(process->state->s == LTTV_STATE_RUN) {
237 if(process->state->t == LTTV_STATE_USER_MODE)
238 prop_line.color = drawing_colors[COL_RUN_USER_MODE];
239 else if(process->state->t == LTTV_STATE_SYSCALL)
240 prop_line.color = drawing_colors[COL_RUN_SYSCALL];
241 else if(process->state->t == LTTV_STATE_TRAP)
242 prop_line.color = drawing_colors[COL_RUN_TRAP];
243 else if(process->state->t == LTTV_STATE_IRQ)
244 prop_line.color = drawing_colors[COL_RUN_IRQ];
faf074a3 245 else if(process->state->t == LTTV_STATE_SOFT_IRQ)
246 prop_line.color = drawing_colors[COL_RUN_SOFT_IRQ];
f044974e
MD
247 else if(process->state->t == LTTV_STATE_MAYBE_SYSCALL)
248 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
249 else if(process->state->t == LTTV_STATE_MAYBE_USER_MODE)
250 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
251 else if(process->state->t == LTTV_STATE_MAYBE_TRAP)
252 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
9a1ec01b 253 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
254 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
255 else
256 g_assert(FALSE); /* RUNNING MODE UNKNOWN */
257 } else if(process->state->s == LTTV_STATE_WAIT) {
258 /* We don't show if we wait while in user mode, trap, irq or syscall */
259 prop_line.color = drawing_colors[COL_WAIT];
260 } else if(process->state->s == LTTV_STATE_WAIT_CPU) {
261 /* We don't show if we wait for CPU while in user mode, trap, irq
262 * or syscall */
263 prop_line.color = drawing_colors[COL_WAIT_CPU];
264 } else if(process->state->s == LTTV_STATE_ZOMBIE) {
265 prop_line.color = drawing_colors[COL_ZOMBIE];
266 } else if(process->state->s == LTTV_STATE_WAIT_FORK) {
267 prop_line.color = drawing_colors[COL_WAIT_FORK];
268 } else if(process->state->s == LTTV_STATE_EXIT) {
269 prop_line.color = drawing_colors[COL_EXIT];
270 } else if(process->state->s == LTTV_STATE_UNNAMED) {
271 prop_line.color = drawing_colors[COL_UNNAMED];
c7620c79 272 } else if(process->state->s == LTTV_STATE_DEAD) {
273 prop_line.color = drawing_colors[COL_DEAD];
b3fd4c02 274 } else {
275 g_critical("unknown state : %s", g_quark_to_string(process->state->s));
9a1ec01b 276 g_assert(FALSE); /* UNKNOWN STATE */
b3fd4c02 277 }
9a1ec01b 278
279 return prop_line;
280
281}
282
98dfb302
YB
283HashedProcessData *get_hashed_process_data(ControlFlowData *control_flow_data,
284 LttvProcessState *process,
285 guint pid,
286 guint trace_num)
287{
288 HashedProcessData *hashed_process_data = NULL;
289 ProcessList *process_list = control_flow_data->process_list;
290 LttTime birth = process->creation_time;
291 guint pl_height = 0;
292
293 hashed_process_data = processlist_get_process_data(process_list,
294 pid,
295 process->cpu,
296 &birth,
297 trace_num);
298 if(hashed_process_data == NULL)
299 {
300 g_assert(pid == 0 || pid != process->ppid);
301 ProcessInfo *process_info;
302 Drawing_t *drawing = control_flow_data->drawing;
303 /* Process not present */
304 processlist_add(process_list,
305 drawing,
306 pid,
307 process->tgid,
308 process->cpu,
309 process->ppid,
310 &birth,
311 trace_num,
312 process->name,
313 process->brand,
314 &pl_height,
315 &process_info,
316 &hashed_process_data);
317 gtk_widget_set_size_request(drawing->drawing_area,
318 -1,
319 pl_height);
320 gtk_widget_queue_draw(drawing->drawing_area);
321 }
322 return hashed_process_data;
323}
324
325void init_drawing_context(DrawContext *draw_context,
326 HashedProcessData *hashed_process_data,
327 Drawing_t *drawing,
328 guint x
329 )
330{
331 draw_context->drawable = hashed_process_data->pixmap;
332 draw_context->gc = drawing->gc;
333 draw_context->pango_layout = drawing->pango_layout;
334 draw_context->drawinfo.start.x = hashed_process_data->x.middle;
335 draw_context->drawinfo.end.x = x;
336
337 draw_context->drawinfo.y.over = 1;
338 draw_context->drawinfo.y.middle = (hashed_process_data->height/2);
339 draw_context->drawinfo.y.under = hashed_process_data->height;
340
341 draw_context->drawinfo.start.offset.over = 0;
342 draw_context->drawinfo.start.offset.middle = 0;
343 draw_context->drawinfo.start.offset.under = 0;
344 draw_context->drawinfo.end.offset.over = 0;
345 draw_context->drawinfo.end.offset.middle = 0;
346 draw_context->drawinfo.end.offset.under = 0;
347
348}
349
350void draw_state_line(HashedProcessData *hashed_process_data,
351 LttvProcessState *process,
352 Drawing_t *drawing,
353 guint x,
354 TimeWindow time_window)
355{
356 DrawContext draw_context;
357 guint width = drawing->width;
358
359 init_drawing_context(&draw_context,
360 hashed_process_data,
361 drawing,
362 x);
363
364
365 /* Draw the line */
366 PropertiesLine prop_line = prepare_s_e_line(process);
367 draw_line((void*)&prop_line, (void*)&draw_context);
368
369 /* become the last x position */
370 hashed_process_data->x.middle = x;
371 hashed_process_data->x.middle_used = TRUE;
372 hashed_process_data->x.middle_marked = FALSE;
373
374 /* Calculate the next good time */
375 convert_pixels_to_time(width, x+1, time_window,
376 &hashed_process_data->next_good_time);
377}
378
379
380void draw_state_items(ControlFlowData *control_flow_data,
381 HashedProcessData *hashed_process_data,
382 LttvProcessState *process,
383 LttTime evtime )
384{
385
386
387 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
388 evtime) > 0))
389 {
390 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
391 TimeWindow time_window =
392 lttvwindow_get_time_window(control_flow_data->tab);
393
394#ifdef EXTRA_CHECK
395 if(ltt_time_compare(evtime, time_window.start_time) == -1
396 || ltt_time_compare(evtime, time_window.end_time) == 1)
397 return FALSE;
398#endif //EXTRA_CHECK
399 Drawing_t *drawing = control_flow_data->drawing;
400 guint width = drawing->width;
401 guint x;
402 convert_time_to_pixels(
403 time_window,
404 evtime,
405 width,
406 &x);
407
408 /* Draw collision indicator */
409 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
410 gdk_draw_point(hashed_process_data->pixmap,
411 drawing->gc,
412 x,
413 COLLISION_POSITION(hashed_process_data->height));
414 hashed_process_data->x.middle_marked = TRUE;
415 }
416 } else {
417 TimeWindow time_window =
418 lttvwindow_get_time_window(control_flow_data->tab);
419
420#ifdef EXTRA_CHECK
421 if(ltt_time_compare(evtime, time_window.start_time) == -1
422 || ltt_time_compare(evtime, time_window.end_time) == 1)
423 return FALSE;
424#endif //EXTRA_CHECK
425 Drawing_t *drawing = control_flow_data->drawing;
426 guint width = drawing->width;
427 guint x;
428
429 convert_time_to_pixels(
430 time_window,
431 evtime,
432 width,
433 &x);
434
435
436 /* Jump over draw if we are at the same x position */
437 if(unlikely(x == hashed_process_data->x.middle &&
438 hashed_process_data->x.middle_used))
439 {
440 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
441 /* Draw collision indicator */
442 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
443 gdk_draw_point(hashed_process_data->pixmap,
444 drawing->gc,
445 x,
446 COLLISION_POSITION(hashed_process_data->height));
447 hashed_process_data->x.middle_marked = TRUE;
448 }
449 /* jump */
450 } else {
451
452 draw_state_line(hashed_process_data,
453 process,
454 drawing,
455 x,
456 time_window);
457 }
458 }
459}
460
461
068572ab
CS
462/* Before try-wake-up hook. A process is being woken; we need to draw its line up to this point in time
463 in that colour. This is basically like exec-state, but the change applies to a process other than that
464 which is currently running. */
465
466int before_trywakeup_hook(void *hook_data, void *call_data)
467{
88bf15f0 468
7b20eed1 469 LttvEvent *event;
068572ab 470
7b20eed1
YB
471 event = (LttvEvent *) call_data;
472 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_wakeup") != 0)
473 return FALSE;
068572ab 474
7b20eed1 475 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
068572ab 476
7b20eed1 477 LttvTraceState *ts = event->state;;
068572ab 478
7b20eed1
YB
479
480 LttTime evtime = lttv_event_get_timestamp(event);
481#ifdef BABEL_CLEANUP
068572ab 482 LttvFilter *filter = control_flow_data->filter;
7b20eed1 483#endif
068572ab
CS
484
485 guint woken_pid;
486 gint woken_cpu;
487
7b20eed1
YB
488 woken_pid = lttv_event_get_long(event, "tid");
489 woken_cpu = lttv_event_get_long(event, "target_cpu");
490
491#ifdef BABEL_CLEANUP
068572ab
CS
492 if(!filter || !filter->head ||
493 lttv_filter_tree_parse(filter->head,e,tfc->tf,
494 tfc->t_context->t,tfc,NULL,NULL)) {
7b20eed1
YB
495#else
496 {
497#endif
068572ab
CS
498 /* First, check if the woken process is in the state computation
499 * process list. If it is there, that means we must add it right now and
500 * draw items from the beginning of the read for it. If it is not
501 * present, it's a new process and it was not present : it will
502 * be added after the state update. TOCHECK: What does that last para mean? */
8284135e 503 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
7b20eed1 504 LttvProcessState *process = lttv_state_find_process(ts, woken_cpu, woken_pid);
068572ab
CS
505
506 if(process != NULL) {
507 /* Well, the woken process existed : we must get it in the process hash
508 * or add it, and draw its items.
509 */
510 /* Add process to process list (if not present) */
068572ab 511
98dfb302 512 HashedProcessData *hashed_process_data = get_hashed_process_data(control_flow_data, process, woken_pid, trace_num);
068572ab
CS
513
514 /* Now, the process is in the state hash and our own process hash.
515 * We definitely can draw the items related to the ending state.
516 */
068572ab 517
98dfb302
YB
518 draw_state_items(control_flow_data,
519 hashed_process_data,
520 process,
521 evtime );
068572ab 522
068572ab
CS
523 }
524 }
525
068572ab 526
7b20eed1
YB
527
528
10599fb9 529 return 0;
068572ab
CS
530
531}
c8bba5fa 532
e92eabaf 533/* before_schedchange_hook
b9a010a2 534 *
f0d936c0 535 * This function basically draw lines and icons. Two types of lines are drawn :
536 * one small (3 pixels?) representing the state of the process and the second
537 * type is thicker (10 pixels?) representing on which CPU a process is running
538 * (and this only in running state).
539 *
540 * Extremums of the lines :
541 * x_min : time of the last event context for this process kept in memory.
542 * x_max : time of the current event.
543 * y : middle of the process in the process list. The process is found in the
544 * list, therefore is it's position in pixels.
545 *
546 * The choice of lines'color is defined by the context of the last event for this
547 * process.
548 */
b9a010a2 549
550
e92eabaf 551int before_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 552{
88bf15f0
FD
553 LttvEvent *event;
554 guint cpu;
555 LttvTraceState *ts;
556 LttvProcessState *process;
557
558 //LttvProcessState *old_process = ts->running_process[cpu];
559
560 guint pid_in, pid_out;
561 gint64 state_out;
98dfb302 562 LttTime evtime;
88bf15f0 563 event = (LttvEvent *) call_data;
8924e3e4
FD
564 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_switch") != 0)
565 return FALSE;
566
88bf15f0 567 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
b9a010a2 568
fd22065b 569
10a1069a 570 /* we are in a schedchange, before the state update. We must draw the
571 * items corresponding to the state before it changes : now is the right
572 * time to do it.
573 */
88bf15f0
FD
574 cpu = lttv_traceset_get_cpuid_from_event(event);
575 ts = event->state;
8924e3e4 576
88bf15f0
FD
577 pid_out = lttv_event_get_long(event, "prev_tid");
578 pid_in = lttv_event_get_long(event, "next_tid");
579 state_out = lttv_event_get_long(event, "prev_state");
8284135e 580 guint trace_number = lttv_traceset_get_trace_index_from_event(event);
88bf15f0 581
8924e3e4 582 process = lttv_state_find_process(ts,cpu,pid_out);
98dfb302 583 evtime = lttv_event_get_timestamp(event);
10a1069a 584 /* For the pid_out */
585 /* First, check if the current process is in the state computation
586 * process list. If it is there, that means we must add it right now and
587 * draw items from the beginning of the read for it. If it is not
588 * present, it's a new process and it was not present : it will
589 * be added after the state update. */
b9a010a2 590
88bf15f0
FD
591 /* unknown state, bad current pid */
592
10a1069a 593 if(process != NULL) {
594 /* Well, the process_out existed : we must get it in the process hash
595 * or add it, and draw its items.
596 */
597 /* Add process to process list (if not present) */
1c736ed5 598
98dfb302
YB
599 HashedProcessData *hashed_process_data = get_hashed_process_data(control_flow_data, process, pid_out, trace_number);
600
10a1069a 601 /* Now, the process is in the state hash and our own process hash.
602 * We definitely can draw the items related to the ending state.
603 */
e800cf84 604
98dfb302
YB
605 draw_state_items(control_flow_data,
606 hashed_process_data,
607 process,
608 evtime );
e800cf84 609 }
610
10a1069a 611 /* For the pid_in */
612 /* First, check if the current process is in the state computation
613 * process list. If it is there, that means we must add it right now and
614 * draw items from the beginning of the read for it. If it is not
615 * present, it's a new process and it was not present : it will
616 * be added after the state update. */
8924e3e4 617 process = lttv_state_find_process(ts,cpu,pid_in);
10a1069a 618
619 if(process != NULL) {
800aa029 620 /* Well, the process existed : we must get it in the process hash
10a1069a 621 * or add it, and draw its items.
622 */
623 /* Add process to process list (if not present) */
1c736ed5 624
98dfb302
YB
625 HashedProcessData *hashed_process_data = get_hashed_process_data(control_flow_data, process, pid_in, trace_number);
626
40debf7b 627 //We could set the current process and hash here, but will be done
628 //by after schedchange hook
10a1069a 629
630 /* Now, the process is in the state hash and our own process hash.
631 * We definitely can draw the items related to the ending state.
632 */
98dfb302
YB
633 draw_state_items(control_flow_data,
634 hashed_process_data,
635 process,
636 evtime );
10a1069a 637
8e680509 638 } else
433e7ba0 639 g_warning("Cannot find pid_in in schedchange %u at %u.%u", pid_in, evtime.tv_sec, evtime.tv_nsec);
88bf15f0 640#ifdef BABEL_CLEANUP
e38d9ea0 641 tfc->target_pid = target_pid_saved;
88bf15f0 642#endif //babel_cleanup
b9a010a2 643 return 0;
644
645
b9a010a2 646
a56a1ba4 647
51705146 648 /* Text dump */
80a52ff8 649#ifdef DONTSHOW
a56a1ba4 650 GString *string = g_string_new("");;
651 gboolean field_names = TRUE, state = TRUE;
80a52ff8 652
e9a9c513 653 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
654 g_string_append_printf(string,"\n");
655
656 if(state) {
657 g_string_append_printf(string, " %s",
658 g_quark_to_string(tfs->process->state->s));
659 }
660
661 g_info("%s",string->str);
662
a56a1ba4 663 g_string_free(string, TRUE);
664
665 /* End of text dump */
80a52ff8 666#endif //DONTSHOW
50439712 667
f0d936c0 668}
669
e92eabaf 670/* after_schedchange_hook
b9a010a2 671 *
672 * The draw after hook is called by the reading API to have a
673 * particular event drawn on the screen.
674 * @param hook_data ControlFlowData structure of the viewer.
675 * @param call_data Event context.
676 *
677 * This function adds items to be drawn in a queue for each process.
678 *
679 */
e92eabaf 680int after_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 681{
7b20eed1 682 LttvEvent *event;
50439712 683
7b20eed1
YB
684 event = (LttvEvent *) call_data;
685
686 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_switch") != 0)
687 return FALSE;
50439712 688
7b20eed1 689 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
50439712 690
348c6ba8 691
7b20eed1 692 LttvTraceState *ts = event->state;
b9a010a2 693
7b20eed1 694#ifdef BABEL_CLEANUP
e38d9ea0 695 LttvFilter *filter = control_flow_data->filter;
7b20eed1
YB
696#endif
697 LttTime evtime = lttv_event_get_timestamp(event);
b9a010a2 698
10a1069a 699 /* Add process to process list (if not present) */
2eef04b5 700 LttvProcessState *process_in;
10a1069a 701 HashedProcessData *hashed_process_data_in = NULL;
b9a010a2 702
5c230fc4 703 ProcessList *process_list = control_flow_data->process_list;
10a1069a 704
705 guint pid_in;
706 {
7b20eed1 707 pid_in = lttv_event_get_long(event, "next_tid");
10a1069a 708 }
b9a010a2 709
7b20eed1 710#ifdef BABEL_CLEANUP
c7620c79 711 if(!filter || !filter->head ||
712 lttv_filter_tree_parse(filter->head,e,tfc->tf,
713 tfc->t_context->t,tfc,NULL,NULL)) {
7b20eed1
YB
714#else
715 {
716#endif
c7620c79 717 /* Find process pid_in in the list... */
718 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
719 //process_in = tfs->process;
7b20eed1 720 guint cpu = lttv_traceset_get_cpuid_from_event(event);
8284135e 721 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
c7620c79 722 process_in = ts->running_process[cpu];
723 /* It should exist, because we are after the state update. */
96947fcf 724#ifdef EXTRA_CHECK
c7620c79 725 g_assert(process_in != NULL);
96947fcf 726#endif //EXTRA_CHECK
98dfb302
YB
727 hashed_process_data_in = get_hashed_process_data(control_flow_data, process_in, pid_in, trace_num);
728
c7620c79 729 /* Set the current process */
730 process_list->current_hash_data[trace_num][process_in->cpu] =
731 hashed_process_data_in;
732
733 if(ltt_time_compare(hashed_process_data_in->next_good_time,
734 evtime) <= 0)
735 {
736 TimeWindow time_window =
737 lttvwindow_get_time_window(control_flow_data->tab);
738
fd22065b 739#ifdef EXTRA_CHECK
c7620c79 740 if(ltt_time_compare(evtime, time_window.start_time) == -1
741 || ltt_time_compare(evtime, time_window.end_time) == 1)
742 return FALSE;
fd22065b 743#endif //EXTRA_CHECK
c7620c79 744 Drawing_t *drawing = control_flow_data->drawing;
745 guint width = drawing->width;
746 guint new_x;
747
748 convert_time_to_pixels(
749 time_window,
750 evtime,
751 width,
752 &new_x);
753
754 if(hashed_process_data_in->x.middle != new_x) {
755 hashed_process_data_in->x.middle = new_x;
756 hashed_process_data_in->x.middle_used = FALSE;
757 hashed_process_data_in->x.middle_marked = FALSE;
758 }
b2743953 759 }
760 }
c7620c79 761
10599fb9 762 return 0;
4a24fa1f 763}
b9a010a2 764
765
766
e72908ed 767
4a24fa1f 768/* before_execmode_hook
769 *
770 * This function basically draw lines and icons. Two types of lines are drawn :
771 * one small (3 pixels?) representing the state of the process and the second
772 * type is thicker (10 pixels?) representing on which CPU a process is running
773 * (and this only in running state).
774 *
775 * Extremums of the lines :
776 * x_min : time of the last event context for this process kept in memory.
777 * x_max : time of the current event.
778 * y : middle of the process in the process list. The process is found in the
779 * list, therefore is it's position in pixels.
780 *
781 * The choice of lines'color is defined by the context of the last event for this
782 * process.
783 */
784
e72908ed 785
4a24fa1f 786int before_execmode_hook(void *hook_data, void *call_data)
787{
88bf15f0
FD
788 LttvEvent *event;
789 guint cpu;
10599fb9 790 guint pid = 0;
88bf15f0
FD
791 LttvTraceState *ts;
792 LttvProcessState *process;
793
4a24fa1f 794 /* we are in a execmode, before the state update. We must draw the
795 * items corresponding to the state before it changes : now is the right
796 * time to do it.
797 */
88bf15f0
FD
798
799 event = (LttvEvent *) call_data;
8924e3e4
FD
800 if ((strncmp(lttv_traceset_get_name_from_event(event),"sys_", sizeof("sys_") - 1) == 0)
801 ||(strcmp(lttv_traceset_get_name_from_event(event),"exit_syscall") == 0)
d940a891
YB
802 ||(strncmp(lttv_traceset_get_name_from_event(event),"irq_handler_",sizeof("irq_handler_") -1) == 0)
803 ||(strncmp(lttv_traceset_get_name_from_event(event),"softirq_", sizeof("softirq_") - 1) == 0)) {
8924e3e4 804
88bf15f0
FD
805 LttTime evtime = lttv_event_get_timestamp(event);
806 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
4a24fa1f 807 /* For the pid */
88bf15f0
FD
808 LttvTraceset *traceSet = lttvwindow_get_traceset(control_flow_data->tab);
809
810 cpu = lttv_traceset_get_cpuid_from_event(event);
811 ts = event->state;
812
8284135e 813 guint trace_number = lttv_traceset_get_trace_index_from_event(event);
d940a891
YB
814
815 //TODO ybrosseau 2013-04-09 validate that using the running process is the right choice
816 //process = lttv_state_find_process(ts ,cpu ,pid);
817 process = ts->running_process[cpu];
818
4a24fa1f 819 g_assert(process != NULL);
23093869 820
10a1069a 821 guint pid = process->pid;
23093869 822
10a1069a 823 /* Well, the process_out existed : we must get it in the process hash
824 * or add it, and draw its items.
825 */
826 /* Add process to process list (if not present) */
10a1069a 827 HashedProcessData *hashed_process_data = NULL;
5c230fc4 828 ProcessList *process_list = control_flow_data->process_list;
88bf15f0
FD
829 if(process_list->current_hash_data == NULL){//TODO fdeslauriers 2012-07-17 : should not be necessary
830 return 0;
831 }
832
88bf15f0
FD
833 if(likely(process_list->current_hash_data[trace_number][cpu] != NULL)) {
834 hashed_process_data = process_list->current_hash_data[trace_number][cpu];
40debf7b 835 } else {
98dfb302
YB
836 hashed_process_data = get_hashed_process_data(control_flow_data,
837 process, pid, trace_number);
838
40debf7b 839 /* Set the current process */
88bf15f0 840 process_list->current_hash_data[trace_number][process->cpu] =
40debf7b 841 hashed_process_data;
10a1069a 842 }
23093869 843
10a1069a 844 /* Now, the process is in the state hash and our own process hash.
845 * We definitely can draw the items related to the ending state.
846 */
98dfb302
YB
847
848 draw_state_items(control_flow_data,
849 hashed_process_data,
850 process,
851 evtime );
8924e3e4 852 }
98dfb302 853
23093869 854 return 0;
98dfb302 855
23093869 856}
857
4a24fa1f 858/* before_process_exit_hook
23093869 859 *
4a24fa1f 860 * Draw lines for process event.
861 *
23093869 862 * @param hook_data ControlFlowData structure of the viewer.
863 * @param call_data Event context.
864 *
865 * This function adds items to be drawn in a queue for each process.
866 *
867 */
8869ac08 868
869
4a24fa1f 870int before_process_exit_hook(void *hook_data, void *call_data)
871{
23093869 872
7b20eed1 873 LttvEvent *event;
23093869 874
7b20eed1
YB
875 event = (LttvEvent *) call_data;
876 if (strcmp(lttv_traceset_get_name_from_event(event),
877 "sched_process_exit") != 0)
878 return FALSE;
4a24fa1f 879
7b20eed1
YB
880
881 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
882 LttvTraceState *ts = event->state;
23093869 883
7b20eed1 884#ifdef BABEL_CLEANUP
e38d9ea0 885 LttvFilter *filter = control_flow_data->filter;
886 if(filter != NULL && filter->head != NULL)
98dfb302
YB
887 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
888 tfc->t_context->t,tfc,NULL,NULL))
889 return FALSE;
890#endif
dbd243b1 891
98dfb302 892 LttTime evtime = lttv_event_get_timestamp(event);
dbd243b1 893
98dfb302
YB
894 /* Add process to process list (if not present) */
895 //LttvProcessState *process = tfs->process;
896 guint cpu = lttv_traceset_get_cpuid_from_event(event);
8284135e 897 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
dbd243b1 898
98dfb302
YB
899 LttvProcessState *process = ts->running_process[cpu];
900 guint pid = process->pid;
901 HashedProcessData *hashed_process_data = NULL;
902
903 ProcessList *process_list = control_flow_data->process_list;
904
905 g_assert(process != NULL);
906
907 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
908 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
909 } else {
910 hashed_process_data = get_hashed_process_data(control_flow_data,
911 process, pid, trace_num);
2c82c4dc 912 }
7b20eed1 913
98dfb302
YB
914 /* Now, the process is in the state hash and our own process hash.
915 * We definitely can draw the items related to the ending state.
916 */
917
918 draw_state_items(control_flow_data,
919 hashed_process_data,
920 process,
921 evtime);
922
10599fb9 923 return 0;
2c82c4dc 924
925}
926
927
928
929/* before_process_release_hook
930 *
931 * Draw lines for process event.
932 *
933 * @param hook_data ControlFlowData structure of the viewer.
934 * @param call_data Event context.
935 *
936 * This function adds items to be drawn in a queue for each process.
937 *
938 */
939
940
941int before_process_release_hook(void *hook_data, void *call_data)
942{
2c82c4dc 943
7b20eed1 944 LttvEvent *event;
2c82c4dc 945
7b20eed1
YB
946 event = (LttvEvent *) call_data;
947
948 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_free") != 0)
949 return FALSE;
2c82c4dc 950
7b20eed1 951 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 952
2c82c4dc 953
7b20eed1
YB
954 LttvTraceState *ts = event->state;
955
956#ifdef BABEL_CLEANUP
e38d9ea0 957 LttvFilter *filter = control_flow_data->filter;
958 if(filter != NULL && filter->head != NULL)
959 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 960 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 961 return FALSE;
7b20eed1
YB
962#endif
963 LttTime evtime = lttv_event_get_timestamp(event);
e38d9ea0 964
2c82c4dc 965
8284135e 966 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
2c82c4dc 967
968 guint pid;
969 {
7b20eed1 970 pid = lttv_event_get_long(event, "tid");
2c82c4dc 971 }
972
973 /* Add process to process list (if not present) */
974 /* Don't care about the process if it's not in the state hash already :
975 * that means a process that has never done anything in the trace and
976 * unknown suddently gets destroyed : no state meaningful to show. */
348c6ba8 977 LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
2c82c4dc 978
979 if(process != NULL) {
980 LttTime birth;
2c82c4dc 981 HashedProcessData *hashed_process_data = NULL;
982
983 ProcessList *process_list = control_flow_data->process_list;
984
985 birth = process->creation_time;
986
987 /* Cannot use current process : this event happens on another process,
988 * action done by the parent. */
989 hashed_process_data = processlist_get_process_data(process_list,
990 pid,
348c6ba8 991 process->cpu,
2c82c4dc 992 &birth,
0f090e21 993 trace_num);
2c82c4dc 994 if(unlikely(hashed_process_data == NULL))
3311444c 995 /*
996 * Process already been scheduled out EXIT_DEAD, not in the process list
997 * anymore. Just return.
998 */
999 return FALSE;
2c82c4dc 1000
1001 /* Now, the process is in the state hash and our own process hash.
1002 * We definitely can draw the items related to the ending state.
1003 */
1004
98dfb302
YB
1005 draw_state_items(control_flow_data,
1006 hashed_process_data,
1007 process,
1008 evtime);
dbd243b1 1009 }
10599fb9 1010 return 0;
dbd243b1 1011}
1012
4a24fa1f 1013
2c82c4dc 1014
1015
1016
1017/* after_process_fork_hook
1018 *
1019 * Create the processlist entry for the child process. Put the last
1020 * position in x at the current time value.
1021 *
1022 * @param hook_data ControlFlowData structure of the viewer.
1023 * @param call_data Event context.
1024 *
1025 * This function adds items to be drawn in a queue for each process.
1026 *
1027 */
1028int after_process_fork_hook(void *hook_data, void *call_data)
1029{
7b20eed1 1030 LttvEvent *event;
2c82c4dc 1031
7b20eed1
YB
1032 event = (LttvEvent *) call_data;
1033
1034 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_fork") != 0)
1035 return FALSE;
2c82c4dc 1036
7b20eed1 1037 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 1038
2c82c4dc 1039
7b20eed1
YB
1040 LttvTraceState *ts = event->state;
1041
1042#ifdef BABEL_CLEANUP
e38d9ea0 1043 LttvFilter *filter = control_flow_data->filter;
1044 if(filter != NULL && filter->head != NULL)
1045 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1046 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1047 return FALSE;
7b20eed1 1048#endif
e38d9ea0 1049
7b20eed1 1050 LttTime evtime = lttv_event_get_timestamp(event);
2c82c4dc 1051
1052 guint child_pid;
1053 {
7b20eed1 1054 child_pid = lttv_event_get_long(event, "child_tid");
2c82c4dc 1055 }
1056
1057 /* Add process to process list (if not present) */
1058 LttvProcessState *process_child;
2c82c4dc 1059 HashedProcessData *hashed_process_data_child = NULL;
1060
1061 ProcessList *process_list = control_flow_data->process_list;
1062
1063 /* Find child in the list... */
348c6ba8 1064 process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
2c82c4dc 1065 /* It should exist, because we are after the state update. */
1066 g_assert(process_child != NULL);
1067
8284135e 1068 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
2c82c4dc 1069
1070 /* Cannot use current process, because this action is done by the parent
1071 * on its child. */
98dfb302
YB
1072 hashed_process_data_child = get_hashed_process_data(control_flow_data,
1073 process_child, child_pid, trace_num);
1074
1075
fcc08e1e 1076 processlist_set_ppid(process_list, process_child->ppid,
1077 hashed_process_data_child);
1078 processlist_set_tgid(process_list, process_child->tgid,
1079 hashed_process_data_child);
98dfb302 1080
2c82c4dc 1081
1082
1083 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
1084 evtime) <= 0))
1085 {
1086 TimeWindow time_window =
1087 lttvwindow_get_time_window(control_flow_data->tab);
1088
1089#ifdef EXTRA_CHECK
1090 if(ltt_time_compare(evtime, time_window.start_time) == -1
1091 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1092 return FALSE;
2c82c4dc 1093#endif //EXTRA_CHECK
1094 Drawing_t *drawing = control_flow_data->drawing;
1095 guint width = drawing->width;
1096 guint new_x;
1097 convert_time_to_pixels(
1098 time_window,
1099 evtime,
1100 width,
1101 &new_x);
1102
1103 if(likely(hashed_process_data_child->x.over != new_x)) {
1104 hashed_process_data_child->x.over = new_x;
1105 hashed_process_data_child->x.over_used = FALSE;
1106 hashed_process_data_child->x.over_marked = FALSE;
1107 }
1108 if(likely(hashed_process_data_child->x.middle != new_x)) {
1109 hashed_process_data_child->x.middle = new_x;
1110 hashed_process_data_child->x.middle_used = FALSE;
1111 hashed_process_data_child->x.middle_marked = FALSE;
1112 }
1113 if(likely(hashed_process_data_child->x.under != new_x)) {
1114 hashed_process_data_child->x.under = new_x;
1115 hashed_process_data_child->x.under_used = FALSE;
1116 hashed_process_data_child->x.under_marked = FALSE;
1117 }
1118 }
10599fb9 1119 return FALSE;
2c82c4dc 1120}
1121
1122
1123
1124/* after_process_exit_hook
1125 *
1126 * Create the processlist entry for the child process. Put the last
1127 * position in x at the current time value.
1128 *
1129 * @param hook_data ControlFlowData structure of the viewer.
1130 * @param call_data Event context.
1131 *
1132 * This function adds items to be drawn in a queue for each process.
1133 *
1134 */
1135int after_process_exit_hook(void *hook_data, void *call_data)
1136{
31799520 1137
7b20eed1 1138 LttvEvent *event;
2c82c4dc 1139
7b20eed1
YB
1140 event = (LttvEvent *) call_data;
1141
1142 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_exit") != 0)
1143 return FALSE;
2c82c4dc 1144
7b20eed1 1145 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 1146
7b20eed1 1147 LttvTraceState *ts = event->state;
2c82c4dc 1148
7b20eed1 1149#ifdef BABEL_CLEANUP
e38d9ea0 1150 LttvFilter *filter = control_flow_data->filter;
1151 if(filter != NULL && filter->head != NULL)
1152 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1153 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1154 return FALSE;
7b20eed1 1155#endif
e38d9ea0 1156
7b20eed1 1157 LttTime evtime = lttv_event_get_timestamp(event);
2c82c4dc 1158
1159 /* Add process to process list (if not present) */
348c6ba8 1160 //LttvProcessState *process = tfs->process;
7b20eed1 1161 guint cpu = lttv_traceset_get_cpuid_from_event(event);
8284135e 1162 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
348c6ba8 1163 LttvProcessState *process = ts->running_process[cpu];
1164
1165 /* It should exist, because we are after the state update. */
1166 g_assert(process != NULL);
1167
2c82c4dc 1168 guint pid = process->pid;
31799520
YB
1169 //LttTime birth;
1170 //guint pl_height = 0;
2c82c4dc 1171 HashedProcessData *hashed_process_data = NULL;
1172
1173 ProcessList *process_list = control_flow_data->process_list;
1174
31799520 1175 //birth = process->creation_time;
2c82c4dc 1176
0f090e21 1177 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){
1178 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
2c82c4dc 1179 } else {
98dfb302 1180 hashed_process_data = get_hashed_process_data(control_flow_data,
31799520 1181 process, pid, trace_num);
98dfb302 1182
2c82c4dc 1183
1184 /* Set the current process */
0f090e21 1185 process_list->current_hash_data[trace_num][process->cpu] =
2c82c4dc 1186 hashed_process_data;
1187 }
1188
1189 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1190 evtime) <= 0))
1191 {
1192 TimeWindow time_window =
1193 lttvwindow_get_time_window(control_flow_data->tab);
dbd243b1 1194
2c82c4dc 1195#ifdef EXTRA_CHECK
1196 if(ltt_time_compare(evtime, time_window.start_time) == -1
1197 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1198 return FALSE;
2c82c4dc 1199#endif //EXTRA_CHECK
1200 Drawing_t *drawing = control_flow_data->drawing;
1201 guint width = drawing->width;
1202 guint new_x;
1203 convert_time_to_pixels(
1204 time_window,
1205 evtime,
1206 width,
1207 &new_x);
1208 if(unlikely(hashed_process_data->x.middle != new_x)) {
1209 hashed_process_data->x.middle = new_x;
1210 hashed_process_data->x.middle_used = FALSE;
1211 hashed_process_data->x.middle_marked = FALSE;
1212 }
1213 }
31799520 1214
10599fb9 1215 return FALSE;
2c82c4dc 1216}
dbd243b1 1217
1218
f4b88a7d 1219/* Get the filename of the process to print */
1220int after_fs_exec_hook(void *hook_data, void *call_data)
1221{
88bf15f0 1222#ifdef BABEL_CLEANUP
dd455fb8 1223 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1224 EventsRequest *events_request = (EventsRequest*)th->hook_data;
f4b88a7d 1225 ControlFlowData *control_flow_data = events_request->viewer_data;
1226
1227 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1228
1229 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1230
1231 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1232
e38d9ea0 1233 LttEvent *e;
1234 e = ltt_tracefile_get_event(tfc->tf);
1235
1236 LttvFilter *filter = control_flow_data->filter;
1237 if(filter != NULL && filter->head != NULL)
1238 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1239 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1240 return FALSE;
1241
ae3d0f50 1242 guint cpu = tfs->cpu;
0f090e21 1243 guint trace_num = ts->parent.index;
f4b88a7d 1244 LttvProcessState *process = ts->running_process[cpu];
1245 g_assert(process != NULL);
1246
1247 guint pid = process->pid;
1248
1249 /* Well, the process_out existed : we must get it in the process hash
1250 * or add it, and draw its items.
1251 */
1252 /* Add process to process list (if not present) */
1253 guint pl_height = 0;
1254 HashedProcessData *hashed_process_data = NULL;
1255 ProcessList *process_list = control_flow_data->process_list;
1256 LttTime birth = process->creation_time;
1257
0f090e21 1258 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1259 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
f4b88a7d 1260 } else {
98dfb302
YB
1261 hashed_process_data = get_hashed_process_data(control_flow_data,
1262 process, pid, trace_num);
f4b88a7d 1263 /* Set the current process */
0f090e21 1264 process_list->current_hash_data[trace_num][process->cpu] =
f4b88a7d 1265 hashed_process_data;
1266 }
1267
1268 processlist_set_name(process_list, process->name, hashed_process_data);
1269
88bf15f0 1270#endif //babel_cleanup
10599fb9 1271 return 0;
f4b88a7d 1272
1273}
1274
b3fd4c02 1275/* after_event_enum_process_hook
1276 *
b3fd4c02 1277 * Create the processlist entry for the child process. Put the last
1278 * position in x at the current time value.
1279 *
1280 * @param hook_data ControlFlowData structure of the viewer.
1281 * @param call_data Event context.
1282 *
1283 * This function adds items to be drawn in a queue for each process.
1284 *
1285 */
1286int after_event_enum_process_hook(void *hook_data, void *call_data)
1287{
7b20eed1 1288 LttvEvent *event;
b3fd4c02 1289
7b20eed1
YB
1290 event = (LttvEvent *) call_data;
1291
1292 if (strcmp(lttv_traceset_get_name_from_event(event),"lttng_statedump_process_state") != 0)
1293 return FALSE;
b3fd4c02 1294
7b20eed1 1295 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
b3fd4c02 1296
c4a72569 1297
7b20eed1 1298 LttvTraceState *ts = event->state;
b3fd4c02 1299
7b20eed1
YB
1300 guint first_cpu, nb_cpus, cpu;
1301
1302#ifdef BABEL_CLEANUP
e38d9ea0 1303 LttvFilter *filter = control_flow_data->filter;
1304 if(filter != NULL && filter->head != NULL)
1305 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1306 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1307 return FALSE;
7b20eed1 1308#endif
b3fd4c02 1309 /* Add process to process list (if not present) */
1310 LttvProcessState *process_in;
b3fd4c02 1311 HashedProcessData *hashed_process_data_in = NULL;
1312
1313 ProcessList *process_list = control_flow_data->process_list;
8284135e 1314 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
b3fd4c02 1315
1316 guint pid_in;
1317 {
7b20eed1 1318 pid_in = lttv_event_get_long(event, "tid");
b3fd4c02 1319 }
c4a72569 1320
1321 if(pid_in == 0) {
1322 first_cpu = 0;
7b20eed1 1323 nb_cpus = lttv_trace_get_num_cpu(ts->trace);
c4a72569 1324 } else {
1325 first_cpu = ANY_CPU;
1326 nb_cpus = ANY_CPU+1;
1327 }
b3fd4c02 1328
c4a72569 1329 for(cpu = first_cpu; cpu < nb_cpus; cpu++) {
1330 /* Find process pid_in in the list... */
1331 process_in = lttv_state_find_process(ts, cpu, pid_in);
1332 //process_in = tfs->process;
1333 //guint cpu = tfs->cpu;
1334 //guint trace_num = ts->parent.index;
1335 //process_in = ts->running_process[cpu];
1336 /* It should exist, because we are after the state update. */
1337 #ifdef EXTRA_CHECK
1338 //g_assert(process_in != NULL);
1339 #endif //EXTRA_CHECK
c4a72569 1340
98dfb302
YB
1341 hashed_process_data_in = get_hashed_process_data(control_flow_data,
1342 process_in, pid_in, trace_num);
1343
c4a72569 1344 processlist_set_name(process_list, process_in->name,
1345 hashed_process_data_in);
1346 processlist_set_ppid(process_list, process_in->ppid,
1347 hashed_process_data_in);
1348 processlist_set_tgid(process_list, process_in->tgid,
1349 hashed_process_data_in);
98dfb302 1350
c4a72569 1351 }
10599fb9 1352 return 0;
b3fd4c02 1353}
f4b88a7d 1354
1355
1b238973 1356gint update_time_window_hook(void *hook_data, void *call_data)
f7afe191 1357{
a56a1ba4 1358 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
98dfb302 1359
a43d67ba 1360 Drawing_t *drawing = control_flow_data->drawing;
1c736ed5 1361 ProcessList *process_list = control_flow_data->process_list;
a43d67ba 1362
224446ce 1363 const TimeWindowNotifyData *time_window_nofify_data =
1364 ((const TimeWindowNotifyData *)call_data);
1365
14963be0 1366 TimeWindow *old_time_window =
224446ce 1367 time_window_nofify_data->old_time_window;
1368 TimeWindow *new_time_window =
1369 time_window_nofify_data->new_time_window;
a56a1ba4 1370
3cb8b205 1371 /* Update the ruler */
1372 drawing_update_ruler(control_flow_data->drawing,
1373 new_time_window);
1374
1375
a56a1ba4 1376 /* Two cases : zoom in/out or scrolling */
1377
1378 /* In order to make sure we can reuse the old drawing, the scale must
1379 * be the same and the new time interval being partly located in the
1380 * currently shown time interval. (reuse is only for scrolling)
1381 */
1382
2eef04b5 1383 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
14963be0 1384 old_time_window->start_time.tv_sec,
1385 old_time_window->start_time.tv_nsec,
1386 old_time_window->time_width.tv_sec,
1387 old_time_window->time_width.tv_nsec);
a56a1ba4 1388
2eef04b5 1389 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
14963be0 1390 new_time_window->start_time.tv_sec,
1391 new_time_window->start_time.tv_nsec,
1392 new_time_window->time_width.tv_sec,
1393 new_time_window->time_width.tv_nsec);
a56a1ba4 1394
14963be0 1395 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1396 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
a56a1ba4 1397 {
1398 /* Same scale (scrolling) */
1399 g_info("scrolling");
14963be0 1400 LttTime *ns = &new_time_window->start_time;
1401 LttTime *os = &old_time_window->start_time;
6f26fc38 1402 LttTime old_end = old_time_window->end_time;
1403 LttTime new_end = new_time_window->end_time;
a56a1ba4 1404 //if(ns<os+w<ns+w)
1405 //if(ns<os+w && os+w<ns+w)
1406 //if(ns<old_end && os<ns)
1407 if(ltt_time_compare(*ns, old_end) == -1
1408 && ltt_time_compare(*os, *ns) == -1)
1409 {
1410 g_info("scrolling near right");
1411 /* Scroll right, keep right part of the screen */
1412 guint x = 0;
51705146 1413 guint width = control_flow_data->drawing->width;
a56a1ba4 1414 convert_time_to_pixels(
a18124ff 1415 *old_time_window,
a56a1ba4 1416 *ns,
1417 width,
1418 &x);
1419
1420 /* Copy old data to new location */
1c736ed5 1421 copy_pixmap_region(process_list,
1422 NULL,
1423 control_flow_data->drawing->drawing_area->style->black_gc,
1424 NULL,
1425 x, 0,
1426 0, 0,
1427 control_flow_data->drawing->width-x+SAFETY, -1);
1428
6395d57c 1429 if(drawing->damage_begin == drawing->damage_end)
1430 drawing->damage_begin = control_flow_data->drawing->width-x;
1431 else
1432 drawing->damage_begin = 0;
1433
1434 drawing->damage_end = control_flow_data->drawing->width;
1435
a56a1ba4 1436 /* Clear the data request background, but not SAFETY */
1c736ed5 1437 rectangle_pixmap(process_list,
cfe526b1 1438 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 1439 TRUE,
6395d57c 1440 drawing->damage_begin+SAFETY, 0,
1441 drawing->damage_end - drawing->damage_begin, // do not overlap
1c736ed5 1442 -1);
7abb23ad 1443 gtk_widget_queue_draw(drawing->drawing_area);
1444 //gtk_widget_queue_draw_area (drawing->drawing_area,
1445 // 0,0,
1446 // control_flow_data->drawing->width,
1447 // control_flow_data->drawing->height);
a43d67ba 1448
a56a1ba4 1449 /* Get new data for the rest. */
501d5405 1450 drawing_data_request(control_flow_data->drawing,
6395d57c 1451 drawing->damage_begin, 0,
1452 drawing->damage_end - drawing->damage_begin,
501d5405 1453 control_flow_data->drawing->height);
a56a1ba4 1454 } else {
1455 //if(ns<os<ns+w)
1456 //if(ns<os && os<ns+w)
1457 //if(ns<os && os<new_end)
1458 if(ltt_time_compare(*ns,*os) == -1
1459 && ltt_time_compare(*os,new_end) == -1)
1460 {
1461 g_info("scrolling near left");
1462 /* Scroll left, keep left part of the screen */
1463 guint x = 0;
51705146 1464 guint width = control_flow_data->drawing->width;
a56a1ba4 1465 convert_time_to_pixels(
a18124ff 1466 *new_time_window,
a56a1ba4 1467 *os,
1468 width,
1469 &x);
6395d57c 1470
a56a1ba4 1471 /* Copy old data to new location */
1c736ed5 1472 copy_pixmap_region (process_list,
1473 NULL,
cfe526b1 1474 control_flow_data->drawing->drawing_area->style->black_gc,
1c736ed5 1475 NULL,
a56a1ba4 1476 0, 0,
1477 x, 0,
1478 -1, -1);
1479
6395d57c 1480 if(drawing->damage_begin == drawing->damage_end)
1481 drawing->damage_end = x;
1482 else
1483 drawing->damage_end =
51705146 1484 control_flow_data->drawing->width;
6395d57c 1485
1486 drawing->damage_begin = 0;
1487
1c736ed5 1488 rectangle_pixmap (process_list,
cfe526b1 1489 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 1490 TRUE,
6395d57c 1491 drawing->damage_begin, 0,
1492 drawing->damage_end - drawing->damage_begin, // do not overlap
1c736ed5 1493 -1);
a43d67ba 1494
7abb23ad 1495 gtk_widget_queue_draw(drawing->drawing_area);
1496 //gtk_widget_queue_draw_area (drawing->drawing_area,
1497 // 0,0,
1498 // control_flow_data->drawing->width,
1499 // control_flow_data->drawing->height);
a43d67ba 1500
6395d57c 1501
a56a1ba4 1502 /* Get new data for the rest. */
501d5405 1503 drawing_data_request(control_flow_data->drawing,
6395d57c 1504 drawing->damage_begin, 0,
1505 drawing->damage_end - drawing->damage_begin,
501d5405 1506 control_flow_data->drawing->height);
a56a1ba4 1507
a56a1ba4 1508 } else {
a43d67ba 1509 if(ltt_time_compare(*ns,*os) == 0)
1510 {
1511 g_info("not scrolling");
1512 } else {
1513 g_info("scrolling far");
1514 /* Cannot reuse any part of the screen : far jump */
1515
1516
1c736ed5 1517 rectangle_pixmap (process_list,
a43d67ba 1518 control_flow_data->drawing->drawing_area->style->black_gc,
1519 TRUE,
a56a1ba4 1520 0, 0,
a43d67ba 1521 control_flow_data->drawing->width+SAFETY, // do not overlap
1c736ed5 1522 -1);
a43d67ba 1523
7abb23ad 1524 //gtk_widget_queue_draw_area (drawing->drawing_area,
1525 // 0,0,
1526 // control_flow_data->drawing->width,
1527 // control_flow_data->drawing->height);
1528 gtk_widget_queue_draw(drawing->drawing_area);
a43d67ba 1529
6395d57c 1530 drawing->damage_begin = 0;
1531 drawing->damage_end = control_flow_data->drawing->width;
1532
a43d67ba 1533 drawing_data_request(control_flow_data->drawing,
a43d67ba 1534 0, 0,
1535 control_flow_data->drawing->width,
1536 control_flow_data->drawing->height);
1537
1538 }
a56a1ba4 1539 }
1540 }
1541 } else {
1542 /* Different scale (zoom) */
1543 g_info("zoom");
1544
1c736ed5 1545 rectangle_pixmap (process_list,
cfe526b1 1546 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 1547 TRUE,
1548 0, 0,
501d5405 1549 control_flow_data->drawing->width+SAFETY, // do not overlap
1c736ed5 1550 -1);
a56a1ba4 1551
7abb23ad 1552 //gtk_widget_queue_draw_area (drawing->drawing_area,
1553 // 0,0,
1554 // control_flow_data->drawing->width,
1555 // control_flow_data->drawing->height);
1556 gtk_widget_queue_draw(drawing->drawing_area);
a56a1ba4 1557
6395d57c 1558 drawing->damage_begin = 0;
1559 drawing->damage_end = control_flow_data->drawing->width;
1560
501d5405 1561 drawing_data_request(control_flow_data->drawing,
a56a1ba4 1562 0, 0,
501d5405 1563 control_flow_data->drawing->width,
1564 control_flow_data->drawing->height);
a56a1ba4 1565 }
1566
15f77e3b 1567 /* Update directly when scrolling */
1568 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
1569 TRUE);
3cb8b205 1570
a56a1ba4 1571 return 0;
f7afe191 1572}
1573
6395d57c 1574gint traceset_notify(void *hook_data, void *call_data)
1575{
1576 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1577 Drawing_t *drawing = control_flow_data->drawing;
6395d57c 1578
6cec4cd2 1579 if(unlikely(drawing->gc == NULL)) {
1580 return FALSE;
1581 }
1582 if(drawing->dotted_gc == NULL) {
1583 return FALSE;
1584 }
6395d57c 1585
b9a010a2 1586 drawing_clear(control_flow_data->drawing);
1587 processlist_clear(control_flow_data->process_list);
07390ec1 1588 gtk_widget_set_size_request(
1589 control_flow_data->drawing->drawing_area,
1590 -1, processlist_get_height(control_flow_data->process_list));
d9267eec 1591 redraw_notify(control_flow_data, NULL);
6395d57c 1592
d9267eec 1593 request_background_data(control_flow_data);
6395d57c 1594
1595 return FALSE;
1596}
1597
ca0f8a8e 1598gint redraw_notify(void *hook_data, void *call_data)
1599{
1600 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1601 Drawing_t *drawing = control_flow_data->drawing;
1602 GtkWidget *widget = drawing->drawing_area;
1603
1604 drawing->damage_begin = 0;
51705146 1605 drawing->damage_end = drawing->width;
ca0f8a8e 1606
49217bd4 1607 /* fun feature, to be separated someday... */
1608 drawing_clear(control_flow_data->drawing);
1609 processlist_clear(control_flow_data->process_list);
07390ec1 1610 gtk_widget_set_size_request(
1611 control_flow_data->drawing->drawing_area,
1612 -1, processlist_get_height(control_flow_data->process_list));
1c736ed5 1613 // Clear the images
1614 rectangle_pixmap (control_flow_data->process_list,
ca0f8a8e 1615 widget->style->black_gc,
1616 TRUE,
1617 0, 0,
f3b7430d 1618 drawing->alloc_width,
1c736ed5 1619 -1);
ca0f8a8e 1620
f3b7430d 1621 gtk_widget_queue_draw(drawing->drawing_area);
4a24fa1f 1622
ca0f8a8e 1623 if(drawing->damage_begin < drawing->damage_end)
1624 {
1625 drawing_data_request(drawing,
ca0f8a8e 1626 drawing->damage_begin,
1627 0,
1628 drawing->damage_end-drawing->damage_begin,
51705146 1629 drawing->height);
ca0f8a8e 1630 }
1631
7abb23ad 1632 //gtk_widget_queue_draw_area(drawing->drawing_area,
1633 // 0,0,
1634 // drawing->width,
1635 // drawing->height);
ca0f8a8e 1636 return FALSE;
1637
1638}
1639
1640
1641gint continue_notify(void *hook_data, void *call_data)
a43d67ba 1642{
1643 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
ca0f8a8e 1644 Drawing_t *drawing = control_flow_data->drawing;
a43d67ba 1645
6395d57c 1646 //g_assert(widget->allocation.width == drawing->damage_end);
ca0f8a8e 1647
1648 if(drawing->damage_begin < drawing->damage_end)
1649 {
1650 drawing_data_request(drawing,
ca0f8a8e 1651 drawing->damage_begin,
1652 0,
1653 drawing->damage_end-drawing->damage_begin,
51705146 1654 drawing->height);
ca0f8a8e 1655 }
1656
1657 return FALSE;
1658}
1659
1660
1b238973 1661gint update_current_time_hook(void *hook_data, void *call_data)
f7afe191 1662{
88bf15f0 1663
14963be0 1664 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
a56a1ba4 1665
224446ce 1666 LttTime current_time = *((LttTime*)call_data);
88bf15f0 1667
ca0f8a8e 1668 TimeWindow time_window =
1669 lttvwindow_get_time_window(control_flow_data->tab);
a56a1ba4 1670
ca0f8a8e 1671 LttTime time_begin = time_window.start_time;
1672 LttTime width = time_window.time_width;
90ef7e4a 1673 LttTime half_width;
1674 {
1675 guint64 time_ll = ltt_time_to_uint64(width);
1676 time_ll = time_ll >> 1; /* divide by two */
1677 half_width = ltt_time_from_uint64(time_ll);
1678 }
a56a1ba4 1679 LttTime time_end = ltt_time_add(time_begin, width);
1680
88bf15f0 1681 LttvTraceset * ts = lttvwindow_get_traceset(control_flow_data->tab);
a56a1ba4 1682
88bf15f0
FD
1683 TimeInterval time_span = lttv_traceset_get_time_span_real(ts);
1684 LttTime trace_start = time_span.start_time;
1685 LttTime trace_end = time_span.end_time;
a56a1ba4 1686
2eef04b5 1687 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
224446ce 1688 current_time.tv_nsec);
a56a1ba4 1689
1690
1691
1692 /* If current time is inside time interval, just move the highlight
1693 * bar */
1694
1695 /* Else, we have to change the time interval. We have to tell it
1696 * to the main window. */
1697 /* The time interval change will take care of placing the current
1698 * time at the center of the visible area, or nearest possible if we are
1699 * at one end of the trace. */
1700
1701
dbc0ef8a 1702 if(ltt_time_compare(current_time, time_begin) < 0)
a56a1ba4 1703 {
224446ce 1704 TimeWindow new_time_window;
1705
1706 if(ltt_time_compare(current_time,
dbc0ef8a 1707 ltt_time_add(trace_start,half_width)) < 0)
a56a1ba4 1708 time_begin = trace_start;
1709 else
224446ce 1710 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 1711
224446ce 1712 new_time_window.start_time = time_begin;
1713 new_time_window.time_width = width;
a18124ff 1714 new_time_window.time_width_double = ltt_time_to_double(width);
6f26fc38 1715 new_time_window.end_time = ltt_time_add(time_begin, width);
a56a1ba4 1716
e800cf84 1717 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 1718 }
dbc0ef8a 1719 else if(ltt_time_compare(current_time, time_end) > 0)
a56a1ba4 1720 {
224446ce 1721 TimeWindow new_time_window;
1722
dbc0ef8a 1723 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
a56a1ba4 1724 time_begin = ltt_time_sub(trace_end,width);
1725 else
224446ce 1726 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 1727
224446ce 1728 new_time_window.start_time = time_begin;
1729 new_time_window.time_width = width;
a18124ff 1730 new_time_window.time_width_double = ltt_time_to_double(width);
6f26fc38 1731 new_time_window.end_time = ltt_time_add(time_begin, width);
a56a1ba4 1732
e800cf84 1733 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 1734
1735 }
7abb23ad 1736 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
a56a1ba4 1737
15f77e3b 1738 /* Update directly when scrolling */
1739 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
1740 TRUE);
1741
a56a1ba4 1742 return 0;
88bf15f0 1743
f7afe191 1744}
1745
8b90e648 1746typedef struct _ClosureData {
ca0f8a8e 1747 EventsRequest *events_request;
b9a010a2 1748 LttTime end_time;
bc8d270b 1749 guint x_end;
8b90e648 1750} ClosureData;
a56a1ba4 1751
8b90e648 1752
e800cf84 1753void draw_closure(gpointer key, gpointer value, gpointer user_data)
1754{
88bf15f0 1755
a56a1ba4 1756 ProcessInfo *process_info = (ProcessInfo*)key;
1757 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
1758 ClosureData *closure_data = (ClosureData*)user_data;
88bf15f0 1759
e800cf84 1760 EventsRequest *events_request = closure_data->events_request;
1761 ControlFlowData *control_flow_data = events_request->viewer_data;
88bf15f0 1762 LttvTraceset *ts = lttvwindow_get_traceset(control_flow_data->tab);
a56a1ba4 1763
a56a1ba4 1764
e800cf84 1765 LttTime evtime = closure_data->end_time;
d0cd7f09 1766
e3162168 1767 gboolean dodraw = TRUE;
1768
e800cf84 1769 {
1770 /* For the process */
1771 /* First, check if the current process is in the state computation
1772 * process list. If it is there, that means we must add it right now and
1773 * draw items from the beginning of the read for it. If it is not
1774 * present, it's a new process and it was not present : it will
1775 * be added after the state update. */
31b6868d 1776#ifdef EXTRA_CHECK
e800cf84 1777 g_assert(lttv_traceset_number(tsc->ts) > 0);
31b6868d 1778#endif //EXTRA_CHECK
8284135e
YB
1779
1780 LttvTrace *trace = lttv_traceset_get(ts, process_info->trace_num);
88bf15f0 1781 LttvTraceState *trace_state = trace->state;
2c82c4dc 1782
348c6ba8 1783#if 0
2c82c4dc 1784 //FIXME : optimize data structures.
1785 LttvTracefileState *tfs;
1786 LttvTracefileContext *tfc;
1787 guint i;
1788 for(i=0;i<tc->tracefiles->len;i++) {
1789 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
1790 if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
ae3d0f50 1791 && tfs->cpu == process_info->cpu)
2c82c4dc 1792 break;
1793
1794 }
1795 g_assert(i<tc->tracefiles->len);
1796 tfs = LTTV_TRACEFILE_STATE(tfc);
348c6ba8 1797#endif //0
88bf15f0 1798 // LttvTracefileState *tfs =ts
2c82c4dc 1799 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
1800 // tracefiles[process_info->cpu];
2da61677 1801
e800cf84 1802 LttvProcessState *process;
88bf15f0 1803 process = lttv_state_find_process(trace_state, process_info->cpu,
e025a729 1804 process_info->pid);
a56a1ba4 1805
1d1df11d 1806 if(unlikely(process != NULL)) {
88bf15f0 1807#ifdef BABEL_CLEANUP
b6ef18af 1808 LttvFilter *filter = control_flow_data->filter;
1809 if(filter != NULL && filter->head != NULL)
1810 if(!lttv_filter_tree_parse(filter->head,NULL,NULL,
1811 tc->t,NULL,process,tc))
e3162168 1812 dodraw = FALSE;
88bf15f0 1813#endif //babel_cleanup
e800cf84 1814 /* Only draw for processes that are currently in the trace states */
ad2e83ba 1815
1d1df11d 1816#ifdef EXTRA_CHECK
e800cf84 1817 /* Should be alike when background info is ready */
1818 if(control_flow_data->background_info_waiting==0)
1819 g_assert(ltt_time_compare(process->creation_time,
1820 process_info->birth) == 0);
1d1df11d 1821#endif //EXTRA_CHECK
e800cf84 1822
1823 /* Now, the process is in the state hash and our own process hash.
1824 * We definitely can draw the items related to the ending state.
1825 */
1826
1d1df11d 1827 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1828 evtime) <= 0))
e800cf84 1829 {
fd22065b 1830 TimeWindow time_window =
1831 lttvwindow_get_time_window(control_flow_data->tab);
1832
1833#ifdef EXTRA_CHECK
1834 if(ltt_time_compare(evtime, time_window.start_time) == -1
1835 || ltt_time_compare(evtime, time_window.end_time) == 1)
1836 return;
1837#endif //EXTRA_CHECK
d6fef890 1838 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 1839 guint width = drawing->width;
a56a1ba4 1840
bc8d270b 1841 guint x = closure_data->x_end;
8b90e648 1842
4b7dc462 1843 DrawContext draw_context;
1844
98dfb302
YB
1845 init_drawing_context(&draw_context,
1846 hashed_process_data,
1847 drawing,
1848 x);
1849
9a1ec01b 1850#if 0
4b7dc462 1851 /* Jump over draw if we are at the same x position */
1852 if(x == hashed_process_data->x.over)
e800cf84 1853 {
4b7dc462 1854 /* jump */
1855 } else {
23093869 1856 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1857 /* Draw the line */
1858 PropertiesLine prop_line = prepare_execmode_line(process);
1859 draw_line((void*)&prop_line, (void*)&draw_context);
1860
4b7dc462 1861 hashed_process_data->x.over = x;
23093869 1862 }
9a1ec01b 1863#endif //0
4b7dc462 1864
1d1df11d 1865 if(unlikely(x == hashed_process_data->x.middle &&
1866 hashed_process_data->x.middle_used)) {
b2743953 1867#if 0 /* do not mark closure : not missing information */
e72908ed 1868 if(hashed_process_data->x.middle_marked == FALSE) {
1869 /* Draw collision indicator */
1870 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1871 gdk_draw_point(drawing->pixmap,
1872 drawing->gc,
1873 x,
2c6618bc 1874 y+(height/2)-3);
de4ea1ad 1875 hashed_process_data->x.middle_marked = TRUE;
e72908ed 1876 }
b2743953 1877#endif //0
4b7dc462 1878 /* Jump */
1879 } else {
23093869 1880 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
e800cf84 1881 /* Draw the line */
c4a72569 1882 if(dodraw) {
1883 PropertiesLine prop_line = prepare_s_e_line(process);
1884 draw_line((void*)&prop_line, (void*)&draw_context);
1885 }
e800cf84 1886
4b7dc462 1887 /* become the last x position */
1d1df11d 1888 if(likely(x != hashed_process_data->x.middle)) {
e72908ed 1889 hashed_process_data->x.middle = x;
1890 /* but don't use the pixel */
1891 hashed_process_data->x.middle_used = FALSE;
b2743953 1892
1893 /* Calculate the next good time */
1894 convert_pixels_to_time(width, x+1, time_window,
1895 &hashed_process_data->next_good_time);
e72908ed 1896 }
e800cf84 1897 }
e800cf84 1898 }
1899 }
1900 }
1901 return;
8b90e648 1902}
1903
b9a010a2 1904int before_chunk(void *hook_data, void *call_data)
1905{
88bf15f0 1906
b9a010a2 1907 EventsRequest *events_request = (EventsRequest*)hook_data;
88bf15f0 1908 LttvTraceset *ts = (LttvTraceset*)call_data;
cd3892fe 1909#if 0
7c0125e0 1910 /* Desactivate sort */
1911 gtk_tree_sortable_set_sort_column_id(
1912 GTK_TREE_SORTABLE(cfd->process_list->list_store),
1913 TRACE_COLUMN,
1914 GTK_SORT_ASCENDING);
cd3892fe 1915#endif //0
88bf15f0 1916 drawing_chunk_begin(events_request, ts);
b9a010a2 1917
1918 return 0;
1919}
1920
1921int before_request(void *hook_data, void *call_data)
ca0f8a8e 1922{
88bf15f0 1923
ca0f8a8e 1924 EventsRequest *events_request = (EventsRequest*)hook_data;
7c0125e0 1925
88bf15f0 1926 drawing_data_request_begin(events_request);
ca0f8a8e 1927
1928 return 0;
88bf15f0 1929
ca0f8a8e 1930}
1931
1932
98dfb302
YB
1933void draw_closing_lines(ControlFlowData *control_flow_data,
1934 EventsRequest* events_request)
8b90e648 1935{
98dfb302 1936 ProcessList *process_list = control_flow_data->process_list;
88bf15f0 1937
b9a010a2 1938
1939 ClosureData closure_data;
98dfb302
YB
1940 closure_data.events_request = events_request;
1941 closure_data.end_time = events_request->end_time;
b9a010a2 1942
bc8d270b 1943 TimeWindow time_window =
1944 lttvwindow_get_time_window(control_flow_data->tab);
1945 guint width = control_flow_data->drawing->width;
1946 convert_time_to_pixels(
1947 time_window,
98dfb302 1948 events_request->end_time,
bc8d270b 1949 width,
1950 &closure_data.x_end);
1951
1952
b9a010a2 1953 /* Draw last items */
1954 g_hash_table_foreach(process_list->process_hash, draw_closure,
1955 (void*)&closure_data);
7c0125e0 1956
b9a010a2 1957
1958 /* Request expose */
98dfb302
YB
1959 drawing_request_expose(events_request, events_request->end_time);
1960}
1961
1962/*
1963 * after request is necessary in addition of after chunk in order to draw
1964 * lines until the end of the screen. after chunk just draws lines until
1965 * the last event.
1966 *
1967 * for each process
1968 * draw closing line
1969 * expose
1970 */
1971int after_request(void *hook_data, void *call_data)
1972{
1973
1974 EventsRequest *events_request = (EventsRequest*)hook_data;
1975 ControlFlowData *control_flow_data = events_request->viewer_data;
1976
1977 draw_closing_lines(control_flow_data, events_request);
1978
b9a010a2 1979 return 0;
1980}
1981
1982/*
1983 * for each process
1984 * draw closing line
e800cf84 1985 * expose
b9a010a2 1986 */
1987int after_chunk(void *hook_data, void *call_data)
1988{
88bf15f0 1989
b9a010a2 1990 EventsRequest *events_request = (EventsRequest*)hook_data;
1991 ControlFlowData *control_flow_data = events_request->viewer_data;
88bf15f0
FD
1992 LttvTraceset *ts = (LttvTraceset*)call_data;
1993
b9a010a2 1994
5c230fc4 1995 ProcessList *process_list = control_flow_data->process_list;
0f090e21 1996 guint i;
88bf15f0 1997 guint nb_trace = lttv_traceset_number(ts);
b9a010a2 1998
0f090e21 1999 /* Only execute when called for the first trace's events request */
43ed82b5 2000 if(!process_list->current_hash_data)
2001 return 0;
0f090e21 2002
2003 for(i = 0 ; i < nb_trace ; i++) {
2004 g_free(process_list->current_hash_data[i]);
2005 }
40debf7b 2006 g_free(process_list->current_hash_data);
2007 process_list->current_hash_data = NULL;
0f090e21 2008
98dfb302 2009 draw_closing_lines(control_flow_data, events_request);
ca0f8a8e 2010
2011 return 0;
8b90e648 2012}
2013
b70ceef8 2014/* after_statedump_end
2015 *
2016 * @param hook_data ControlFlowData structure of the viewer.
2017 * @param call_data Event context.
2018 *
2019 * This function adds items to be drawn in a queue for each process.
2020 *
2021 */
2022int before_statedump_end(void *hook_data, void *call_data)
2023{
7b20eed1 2024 LttvEvent *event;
b70ceef8 2025
7b20eed1
YB
2026 event = (LttvEvent *) call_data;
2027
2028 if (strcmp(lttv_traceset_get_name_from_event(event),"lttng_statedump_end") != 0)
2029 return FALSE;
b70ceef8 2030
7b20eed1 2031 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
b70ceef8 2032
b70ceef8 2033
7b20eed1
YB
2034 LttvTraceState *ts = event->state;
2035
2036
2037 ProcessList *process_list = control_flow_data->process_list;
2038
2039#ifdef BABEL_CLEANUP
b70ceef8 2040 LttvFilter *filter = control_flow_data->filter;
2041 if(filter != NULL && filter->head != NULL)
2042 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 2043 tfc->t_context->t,tfc,NULL,NULL))
b70ceef8 2044 return FALSE;
7b20eed1 2045#endif
b70ceef8 2046
7b20eed1 2047 LttTime evtime = lttv_event_get_timestamp(event);
3dc97878 2048
b70ceef8 2049 ClosureData closure_data;
3dc97878
YB
2050 //TODO ybrosseau 2013-03-27: Fake and event_request.
2051 // We need to change the API of drawing_request_expose to ask
2052 // For and control flow data only.
2053 EventsRequest events_request;
2054 events_request.viewer_data = control_flow_data;
2055 closure_data.events_request = &events_request;
b70ceef8 2056 closure_data.end_time = evtime;
2057
2058 TimeWindow time_window =
2059 lttvwindow_get_time_window(control_flow_data->tab);
2060 guint width = control_flow_data->drawing->width;
2061 convert_time_to_pixels(
2062 time_window,
2063 evtime,
2064 width,
2065 &closure_data.x_end);
2066
2067 /* Draw last items */
2068 g_hash_table_foreach(process_list->process_hash, draw_closure,
2069 (void*)&closure_data);
7b20eed1 2070
b70ceef8 2071#if 0
2072 /* Reactivate sort */
2073 gtk_tree_sortable_set_sort_column_id(
2074 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
2075 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2076 GTK_SORT_ASCENDING);
2077
2078 update_index_to_pixmap(control_flow_data->process_list);
2079 /* Request a full expose : drawing scrambled */
2080 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2081#endif //0
2082 /* Request expose (updates damages zone also) */
3dc97878
YB
2083 drawing_request_expose(&events_request, evtime);
2084
10599fb9 2085 return 0;
b70ceef8 2086}
This page took 0.208598 seconds and 4 git commands to generate.