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