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