Add before and after hook to the control flow computing
[lttv.git] / lttv / modules / gui / controlflow / eventhooks.c
CommitLineData
ce0214a6 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19
f0d936c0 20/*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
f0d936c0 24
b9a010a2 25/* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
27 *
e92eabaf 28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
b9a010a2 31 *
e92eabaf 32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
b9a010a2 34 *
e92eabaf 35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
b9a010a2 37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
e92eabaf 40 * corresponding to it is over, which happens to be at the next before_schedchange
b9a010a2 41 * hook.
42 *
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
45 * line/background.
46 */
47
4e4d11b3 48#ifdef HAVE_CONFIG_H
49#include <config.h>
50#endif
b9a010a2 51
cf6cb7e0 52//#define PANGO_ENABLE_BACKEND
558aa013 53#include <gtk/gtk.h>
54#include <gdk/gdk.h>
5f16133f 55#include <glib.h>
80a52ff8 56#include <assert.h>
50439712 57#include <string.h>
319e9d81 58#include <stdio.h>
5f16133f 59
cf6cb7e0 60//#include <pango/pango.h>
61
80a52ff8 62#include <ltt/event.h>
4ba42155 63#include <ltt/time.h>
2c82c4dc 64#include <ltt/trace.h>
80a52ff8 65
2a2fa4f0 66#include <lttv/lttv.h>
558aa013 67#include <lttv/hook.h>
80a52ff8 68#include <lttv/state.h>
2d262115 69#include <lttvwindow/lttvwindow.h>
6395d57c 70#include <lttvwindow/lttvwindowtraces.h>
0de51231 71#include <lttvwindow/support.h>
80a52ff8 72
f0d936c0 73
a117e3f7 74#include "eventhooks.h"
75#include "cfv.h"
76#include "processlist.h"
77#include "drawing.h"
5f16133f 78
80a52ff8 79
1a31868c 80#define MAX_PATH_LEN 256
3d27be8a 81#define STATE_LINE_WIDTH 6
5bb606ce 82#define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
1a31868c 83
0de51231 84extern GSList *g_legend_list;
85
b9a010a2 86
6395d57c 87/* Action to do when background computation completed.
88 *
e800cf84 89 * Wait for all the awaited computations to be over.
6395d57c 90 */
91
703b25fa 92static gint background_ready(void *hook_data, void *call_data)
6395d57c 93{
94 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
6395d57c 95
e800cf84 96 control_flow_data->background_info_waiting--;
97
98 if(control_flow_data->background_info_waiting == 0) {
4a24fa1f 99 g_message("control flow viewer : background computation data ready.");
6395d57c 100
e800cf84 101 drawing_clear(control_flow_data->drawing);
102 processlist_clear(control_flow_data->process_list);
07390ec1 103 gtk_widget_set_size_request(
104 control_flow_data->drawing->drawing_area,
105 -1, processlist_get_height(control_flow_data->process_list));
e800cf84 106 redraw_notify(control_flow_data, NULL);
b9a010a2 107 }
6395d57c 108
109 return 0;
110}
111
112
113/* Request background computation. Verify if it is in progress or ready first.
e800cf84 114 * Only for each trace in the tab's traceset.
6395d57c 115 */
88bf15f0 116
3f7f592e 117static void request_background_data(ControlFlowData *control_flow_data)
6395d57c 118{
88bf15f0
FD
119
120 LttvTraceset *ts = lttvwindow_get_traceset(control_flow_data->tab);
121 gint num_traces = lttv_traceset_number(ts);
6395d57c 122 gint i;
123 LttvTrace *trace;
7df20ca4 124 LttvTraceState *tstate;
6395d57c 125
88bf15f0 126 LttvHooks *background_ready_hook = lttv_hooks_new();
6395d57c 127 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
128 LTTV_PRIO_DEFAULT);
e800cf84 129 control_flow_data->background_info_waiting = 0;
6395d57c 130
131 for(i=0;i<num_traces;i++) {
88bf15f0
FD
132 trace = lttv_traceset_get(ts, i);
133 tstate = trace->state;
6395d57c 134
7df20ca4 135 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE
88bf15f0 136 && !ts->has_precomputed_states) {
6395d57c 137
138 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
139 trace) == FALSE) {
140 /* We first remove requests that could have been done for the same
141 * information. Happens when two viewers ask for it before servicing
142 * starts.
143 */
93ac601b 144 if(!lttvwindowtraces_background_request_find(trace, "state"))
b5e17af5 145 lttvwindowtraces_background_request_queue(
146 main_window_get_widget(control_flow_data->tab), trace, "state");
6395d57c 147 lttvwindowtraces_background_notify_queue(control_flow_data,
148 trace,
149 ltt_time_infinite,
150 NULL,
151 background_ready_hook);
e800cf84 152 control_flow_data->background_info_waiting++;
6395d57c 153 } else { /* in progress */
154
155 lttvwindowtraces_background_notify_current(control_flow_data,
156 trace,
157 ltt_time_infinite,
158 NULL,
159 background_ready_hook);
e800cf84 160 control_flow_data->background_info_waiting++;
6395d57c 161 }
4368b993 162 } else {
7df20ca4 163 /* Data ready. By its nature, this viewer doesn't need to have
618fbcc1 164 * its data ready hook called there, because a background
4368b993 165 * request is always linked with a redraw.
166 */
6395d57c 167 }
4368b993 168
6395d57c 169 }
170
171 lttv_hooks_destroy(background_ready_hook);
172}
173
174
175
176
f0d936c0 177/**
178 * Event Viewer's constructor hook
179 *
180 * This constructor is given as a parameter to the menuitem and toolbar button
181 * registration. It creates the list.
ca0f8a8e 182 * @param tab A pointer to the parent tab.
f0d936c0 183 * @return The widget created.
184 */
185GtkWidget *
e433e6d6 186h_guicontrolflow(LttvPlugin *plugin)
f0d936c0 187{
e433e6d6 188 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
189 Tab *tab = ptab->tab;
d47b33d2 190 g_info("h_guicontrolflow, %p", tab);
e433e6d6 191 ControlFlowData *control_flow_data = guicontrolflow(ptab);
a56a1ba4 192
ca0f8a8e 193 control_flow_data->tab = tab;
a56a1ba4 194
a56a1ba4 195 // Unreg done in the GuiControlFlow_Destructor
6395d57c 196 lttvwindow_register_traceset_notify(tab,
197 traceset_notify,
198 control_flow_data);
199
ca0f8a8e 200 lttvwindow_register_time_window_notify(tab,
224446ce 201 update_time_window_hook,
202 control_flow_data);
ca0f8a8e 203 lttvwindow_register_current_time_notify(tab,
224446ce 204 update_current_time_hook,
205 control_flow_data);
ca0f8a8e 206 lttvwindow_register_redraw_notify(tab,
207 redraw_notify,
208 control_flow_data);
209 lttvwindow_register_continue_notify(tab,
210 continue_notify,
211 control_flow_data);
667ca2a0 212 request_background_data(control_flow_data);
6395d57c 213
ca0f8a8e 214
68997a22 215 return guicontrolflow_get_widget(control_flow_data) ;
a56a1ba4 216
f0d936c0 217}
218
3cff8cc1 219int event_selected_hook(void *hook_data, void *call_data)
f0d936c0 220{
14963be0 221 guint *event_number = (guint*) call_data;
f0d936c0 222
2a2fa4f0 223 g_debug("DEBUG : event selected by main window : %u", *event_number);
a56a1ba4 224
2eef04b5 225 return 0;
f0d936c0 226}
227
9a1ec01b 228/* Function that selects the color of status&exemode line */
6550d711 229static inline PropertiesLine prepare_s_e_line(LttvProcessState *process)
9a1ec01b 230{
231 PropertiesLine prop_line;
5bb606ce 232 prop_line.line_width = STATE_LINE_WIDTH;
9a1ec01b 233 prop_line.style = GDK_LINE_SOLID;
234 prop_line.y = MIDDLE;
235 //GdkColormap *colormap = gdk_colormap_get_system();
236
9a1ec01b 237 if(process->state->s == LTTV_STATE_RUN) {
238 if(process->state->t == LTTV_STATE_USER_MODE)
239 prop_line.color = drawing_colors[COL_RUN_USER_MODE];
240 else if(process->state->t == LTTV_STATE_SYSCALL)
241 prop_line.color = drawing_colors[COL_RUN_SYSCALL];
242 else if(process->state->t == LTTV_STATE_TRAP)
243 prop_line.color = drawing_colors[COL_RUN_TRAP];
244 else if(process->state->t == LTTV_STATE_IRQ)
245 prop_line.color = drawing_colors[COL_RUN_IRQ];
faf074a3 246 else if(process->state->t == LTTV_STATE_SOFT_IRQ)
247 prop_line.color = drawing_colors[COL_RUN_SOFT_IRQ];
f044974e
MD
248 else if(process->state->t == LTTV_STATE_MAYBE_SYSCALL)
249 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
250 else if(process->state->t == LTTV_STATE_MAYBE_USER_MODE)
251 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
252 else if(process->state->t == LTTV_STATE_MAYBE_TRAP)
253 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
9a1ec01b 254 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
255 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
256 else
257 g_assert(FALSE); /* RUNNING MODE UNKNOWN */
258 } else if(process->state->s == LTTV_STATE_WAIT) {
259 /* We don't show if we wait while in user mode, trap, irq or syscall */
260 prop_line.color = drawing_colors[COL_WAIT];
261 } else if(process->state->s == LTTV_STATE_WAIT_CPU) {
262 /* We don't show if we wait for CPU while in user mode, trap, irq
263 * or syscall */
264 prop_line.color = drawing_colors[COL_WAIT_CPU];
265 } else if(process->state->s == LTTV_STATE_ZOMBIE) {
266 prop_line.color = drawing_colors[COL_ZOMBIE];
267 } else if(process->state->s == LTTV_STATE_WAIT_FORK) {
268 prop_line.color = drawing_colors[COL_WAIT_FORK];
269 } else if(process->state->s == LTTV_STATE_EXIT) {
270 prop_line.color = drawing_colors[COL_EXIT];
271 } else if(process->state->s == LTTV_STATE_UNNAMED) {
272 prop_line.color = drawing_colors[COL_UNNAMED];
c7620c79 273 } else if(process->state->s == LTTV_STATE_DEAD) {
274 prop_line.color = drawing_colors[COL_DEAD];
b3fd4c02 275 } else {
276 g_critical("unknown state : %s", g_quark_to_string(process->state->s));
9a1ec01b 277 g_assert(FALSE); /* UNKNOWN STATE */
b3fd4c02 278 }
9a1ec01b 279
280 return prop_line;
281
282}
283
068572ab
CS
284/* Before try-wake-up hook. A process is being woken; we need to draw its line up to this point in time
285 in that colour. This is basically like exec-state, but the change applies to a process other than that
286 which is currently running. */
287
288int before_trywakeup_hook(void *hook_data, void *call_data)
289{
88bf15f0 290
7b20eed1 291 LttvEvent *event;
068572ab 292
7b20eed1
YB
293 event = (LttvEvent *) call_data;
294 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_wakeup") != 0)
295 return FALSE;
068572ab 296
7b20eed1 297 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
068572ab 298
7b20eed1 299 LttvTraceState *ts = event->state;;
068572ab 300
7b20eed1
YB
301
302 LttTime evtime = lttv_event_get_timestamp(event);
303#ifdef BABEL_CLEANUP
068572ab 304 LttvFilter *filter = control_flow_data->filter;
7b20eed1 305#endif
068572ab
CS
306
307 guint woken_pid;
308 gint woken_cpu;
309
7b20eed1
YB
310 woken_pid = lttv_event_get_long(event, "tid");
311 woken_cpu = lttv_event_get_long(event, "target_cpu");
312
313#ifdef BABEL_CLEANUP
068572ab
CS
314 if(!filter || !filter->head ||
315 lttv_filter_tree_parse(filter->head,e,tfc->tf,
316 tfc->t_context->t,tfc,NULL,NULL)) {
7b20eed1
YB
317#else
318 {
319#endif
068572ab
CS
320 /* First, check if the woken process is in the state computation
321 * process list. If it is there, that means we must add it right now and
322 * draw items from the beginning of the read for it. If it is not
323 * present, it's a new process and it was not present : it will
324 * be added after the state update. TOCHECK: What does that last para mean? */
7b20eed1
YB
325 guint trace_num = 0; /*TODO ybrosseau 2012-08-23: use right number */
326 LttvProcessState *process = lttv_state_find_process(ts, woken_cpu, woken_pid);
068572ab
CS
327
328 if(process != NULL) {
329 /* Well, the woken process existed : we must get it in the process hash
330 * or add it, and draw its items.
331 */
332 /* Add process to process list (if not present) */
333 guint pl_height = 0;
334 HashedProcessData *hashed_process_data = NULL;
335 ProcessList *process_list = control_flow_data->process_list;
336 LttTime birth = process->creation_time;
337
338 hashed_process_data = processlist_get_process_data(process_list,
339 woken_pid,
340 process->cpu,
341 &birth,
342 trace_num);
343 if(hashed_process_data == NULL)
344 {
345 g_assert(woken_pid != process->ppid);
346 /* Process not present */
347 ProcessInfo *process_info;
348 Drawing_t *drawing = control_flow_data->drawing;
349 processlist_add(process_list,
350 drawing,
351 woken_pid,
352 process->tgid,
353 process->cpu,
354 process->ppid,
355 &birth,
356 trace_num,
357 process->name,
358 process->brand,
359 &pl_height,
360 &process_info,
361 &hashed_process_data);
362 gtk_widget_set_size_request(drawing->drawing_area,
363 -1,
364 pl_height);
365 gtk_widget_queue_draw(drawing->drawing_area);
366
367 }
368
369 /* Now, the process is in the state hash and our own process hash.
370 * We definitely can draw the items related to the ending state.
371 */
372
373 if(ltt_time_compare(hashed_process_data->next_good_time,
374 evtime) > 0)
375 {
376 if(hashed_process_data->x.middle_marked == FALSE) {
377
378 TimeWindow time_window =
379 lttvwindow_get_time_window(control_flow_data->tab);
380#ifdef EXTRA_CHECK
381 if(ltt_time_compare(evtime, time_window.start_time) == -1
382 || ltt_time_compare(evtime, time_window.end_time) == 1)
383 return FALSE;
384#endif //EXTRA_CHECK
385 Drawing_t *drawing = control_flow_data->drawing;
386 guint width = drawing->width;
387 guint x;
388 convert_time_to_pixels(
389 time_window,
390 evtime,
391 width,
392 &x);
393
394 /* Draw collision indicator */
395 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
396 gdk_draw_point(hashed_process_data->pixmap,
397 drawing->gc,
398 x,
399 COLLISION_POSITION(hashed_process_data->height));
400 hashed_process_data->x.middle_marked = TRUE;
401 }
402 } else {
403 TimeWindow time_window =
404 lttvwindow_get_time_window(control_flow_data->tab);
405#ifdef EXTRA_CHECK
406 if(ltt_time_compare(evtime, time_window.start_time) == -1
407 || ltt_time_compare(evtime, time_window.end_time) == 1)
408 return FALSE;
409#endif //EXTRA_CHECK
410 Drawing_t *drawing = control_flow_data->drawing;
411 guint width = drawing->width;
412 guint x;
413 convert_time_to_pixels(
414 time_window,
415 evtime,
416 width,
417 &x);
418
419
420 /* Jump over draw if we are at the same x position */
421 if(x == hashed_process_data->x.middle &&
422 hashed_process_data->x.middle_used)
423 {
424 if(hashed_process_data->x.middle_marked == FALSE) {
425 /* Draw collision indicator */
426 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
427 gdk_draw_point(hashed_process_data->pixmap,
428 drawing->gc,
429 x,
430 COLLISION_POSITION(hashed_process_data->height));
431 hashed_process_data->x.middle_marked = TRUE;
432 }
433 /* jump */
434 } else {
435 DrawContext draw_context;
436
437 /* Now create the drawing context that will be used to draw
438 * items related to the last state. */
439 draw_context.drawable = hashed_process_data->pixmap;
440 draw_context.gc = drawing->gc;
441 draw_context.pango_layout = drawing->pango_layout;
442 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
443 draw_context.drawinfo.end.x = x;
444
445 draw_context.drawinfo.y.over = 1;
446 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
447 draw_context.drawinfo.y.under = hashed_process_data->height;
448
449 draw_context.drawinfo.start.offset.over = 0;
450 draw_context.drawinfo.start.offset.middle = 0;
451 draw_context.drawinfo.start.offset.under = 0;
452 draw_context.drawinfo.end.offset.over = 0;
453 draw_context.drawinfo.end.offset.middle = 0;
454 draw_context.drawinfo.end.offset.under = 0;
455
456 {
457 /* Draw the line */
458 PropertiesLine prop_line = prepare_s_e_line(process);
459 draw_line((void*)&prop_line, (void*)&draw_context);
460
461 }
462 /* become the last x position */
463 hashed_process_data->x.middle = x;
464 hashed_process_data->x.middle_used = TRUE;
465 hashed_process_data->x.middle_marked = FALSE;
466
467 /* Calculate the next good time */
468 convert_pixels_to_time(width, x+1, time_window,
469 &hashed_process_data->next_good_time);
470 }
471 }
472 }
473 }
474
068572ab 475
7b20eed1
YB
476
477
10599fb9 478 return 0;
068572ab
CS
479
480}
c8bba5fa 481
e92eabaf 482/* before_schedchange_hook
b9a010a2 483 *
f0d936c0 484 * This function basically draw lines and icons. Two types of lines are drawn :
485 * one small (3 pixels?) representing the state of the process and the second
486 * type is thicker (10 pixels?) representing on which CPU a process is running
487 * (and this only in running state).
488 *
489 * Extremums of the lines :
490 * x_min : time of the last event context for this process kept in memory.
491 * x_max : time of the current event.
492 * y : middle of the process in the process list. The process is found in the
493 * list, therefore is it's position in pixels.
494 *
495 * The choice of lines'color is defined by the context of the last event for this
496 * process.
497 */
b9a010a2 498
499
e92eabaf 500int before_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 501{
88bf15f0
FD
502 LttvEvent *event;
503 guint cpu;
504 LttvTraceState *ts;
505 LttvProcessState *process;
506
507 //LttvProcessState *old_process = ts->running_process[cpu];
508
509 guint pid_in, pid_out;
510 gint64 state_out;
511 LttTime timestamp;
512 event = (LttvEvent *) call_data;
8924e3e4
FD
513 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_switch") != 0)
514 return FALSE;
515
88bf15f0 516 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
b9a010a2 517
fd22065b 518
10a1069a 519 /* we are in a schedchange, before the state update. We must draw the
520 * items corresponding to the state before it changes : now is the right
521 * time to do it.
522 */
88bf15f0
FD
523 cpu = lttv_traceset_get_cpuid_from_event(event);
524 ts = event->state;
8924e3e4 525
88bf15f0
FD
526 pid_out = lttv_event_get_long(event, "prev_tid");
527 pid_in = lttv_event_get_long(event, "next_tid");
528 state_out = lttv_event_get_long(event, "prev_state");
8924e3e4 529 guint trace_number = 0;//TODO fdeslauriers 2012-07-17: // Use trace handle to know trace number
88bf15f0 530
8924e3e4 531 process = lttv_state_find_process(ts,cpu,pid_out);
88bf15f0 532 timestamp = lttv_event_get_timestamp(event);
10a1069a 533 /* For the pid_out */
534 /* First, check if the current process is in the state computation
535 * process list. If it is there, that means we must add it right now and
536 * draw items from the beginning of the read for it. If it is not
537 * present, it's a new process and it was not present : it will
538 * be added after the state update. */
b9a010a2 539
88bf15f0
FD
540 /* unknown state, bad current pid */
541
10a1069a 542 if(process != NULL) {
543 /* Well, the process_out existed : we must get it in the process hash
544 * or add it, and draw its items.
545 */
546 /* Add process to process list (if not present) */
1c736ed5 547 guint pl_height = 0;
10a1069a 548 HashedProcessData *hashed_process_data = NULL;
5c230fc4 549 ProcessList *process_list = control_flow_data->process_list;
10a1069a 550 LttTime birth = process->creation_time;
b9a010a2 551
ac4e21cf 552 hashed_process_data = processlist_get_process_data(process_list,
10a1069a 553 pid_out,
348c6ba8 554 process->cpu,
10a1069a 555 &birth,
8924e3e4 556 trace_number);
ac4e21cf 557 if(hashed_process_data == NULL)
10a1069a 558 {
559 g_assert(pid_out == 0 || pid_out != process->ppid);
560 /* Process not present */
4e86ae2e 561 ProcessInfo *process_info;
1c736ed5 562 Drawing_t *drawing = control_flow_data->drawing;
10a1069a 563 processlist_add(process_list,
1c736ed5 564 drawing,
10a1069a 565 pid_out,
fcc08e1e 566 process->tgid,
348c6ba8 567 process->cpu,
10a1069a 568 process->ppid,
569 &birth,
8924e3e4 570 trace_number,
f4b88a7d 571 process->name,
7b5f6cf1 572 process->brand,
10a1069a 573 &pl_height,
4e86ae2e 574 &process_info,
10a1069a 575 &hashed_process_data);
1c736ed5 576 gtk_widget_set_size_request(drawing->drawing_area,
577 -1,
578 pl_height);
579 gtk_widget_queue_draw(drawing->drawing_area);
580
10a1069a 581 }
10a1069a 582 /* Now, the process is in the state hash and our own process hash.
583 * We definitely can draw the items related to the ending state.
584 */
e800cf84 585
b2743953 586 if(ltt_time_compare(hashed_process_data->next_good_time,
88bf15f0 587 timestamp) > 0)
10a1069a 588 {
b2743953 589 if(hashed_process_data->x.middle_marked == FALSE) {
ac4e21cf 590
fd22065b 591 TimeWindow time_window =
592 lttvwindow_get_time_window(control_flow_data->tab);
593#ifdef EXTRA_CHECK
594 if(ltt_time_compare(evtime, time_window.start_time) == -1
595 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 596 return FALSE;
fd22065b 597#endif //EXTRA_CHECK
d6fef890 598 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 599 guint width = drawing->width;
b2743953 600 guint x;
601 convert_time_to_pixels(
602 time_window,
88bf15f0 603 timestamp,
b2743953 604 width,
605 &x);
606
607 /* Draw collision indicator */
608 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 609 gdk_draw_point(hashed_process_data->pixmap,
b2743953 610 drawing->gc,
611 x,
5bb606ce 612 COLLISION_POSITION(hashed_process_data->height));
b2743953 613 hashed_process_data->x.middle_marked = TRUE;
614 }
615 } else {
ac4e21cf 616 TimeWindow time_window =
617 lttvwindow_get_time_window(control_flow_data->tab);
fd22065b 618#ifdef EXTRA_CHECK
ac4e21cf 619 if(ltt_time_compare(evtime, time_window.start_time) == -1
620 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 621 return FALSE;
fd22065b 622#endif //EXTRA_CHECK
d6fef890 623 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 624 guint width = drawing->width;
10a1069a 625 guint x;
10a1069a 626 convert_time_to_pixels(
a18124ff 627 time_window,
88bf15f0 628 timestamp,
4b7dc462 629 width,
630 &x);
10a1069a 631
10a1069a 632
4b7dc462 633 /* Jump over draw if we are at the same x position */
e72908ed 634 if(x == hashed_process_data->x.middle &&
635 hashed_process_data->x.middle_used)
e800cf84 636 {
e72908ed 637 if(hashed_process_data->x.middle_marked == FALSE) {
638 /* Draw collision indicator */
639 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 640 gdk_draw_point(hashed_process_data->pixmap,
e72908ed 641 drawing->gc,
642 x,
5bb606ce 643 COLLISION_POSITION(hashed_process_data->height));
de4ea1ad 644 hashed_process_data->x.middle_marked = TRUE;
e72908ed 645 }
4b7dc462 646 /* jump */
647 } else {
648 DrawContext draw_context;
10a1069a 649
4b7dc462 650 /* Now create the drawing context that will be used to draw
651 * items related to the last state. */
1c736ed5 652 draw_context.drawable = hashed_process_data->pixmap;
4b7dc462 653 draw_context.gc = drawing->gc;
654 draw_context.pango_layout = drawing->pango_layout;
655 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
656 draw_context.drawinfo.end.x = x;
657
1c736ed5 658 draw_context.drawinfo.y.over = 1;
659 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
660 draw_context.drawinfo.y.under = hashed_process_data->height;
4b7dc462 661
662 draw_context.drawinfo.start.offset.over = 0;
663 draw_context.drawinfo.start.offset.middle = 0;
664 draw_context.drawinfo.start.offset.under = 0;
665 draw_context.drawinfo.end.offset.over = 0;
666 draw_context.drawinfo.end.offset.middle = 0;
667 draw_context.drawinfo.end.offset.under = 0;
668
669 {
670 /* Draw the line */
9a1ec01b 671 PropertiesLine prop_line = prepare_s_e_line(process);
4b7dc462 672 draw_line((void*)&prop_line, (void*)&draw_context);
673
674 }
675 /* become the last x position */
676 hashed_process_data->x.middle = x;
e72908ed 677 hashed_process_data->x.middle_used = TRUE;
678 hashed_process_data->x.middle_marked = FALSE;
b2743953 679
680 /* Calculate the next good time */
681 convert_pixels_to_time(width, x+1, time_window,
682 &hashed_process_data->next_good_time);
e800cf84 683 }
684 }
685 }
686
10a1069a 687 /* For the pid_in */
688 /* First, check if the current process is in the state computation
689 * process list. If it is there, that means we must add it right now and
690 * draw items from the beginning of the read for it. If it is not
691 * present, it's a new process and it was not present : it will
692 * be added after the state update. */
8924e3e4 693 process = lttv_state_find_process(ts,cpu,pid_in);
10a1069a 694
695 if(process != NULL) {
800aa029 696 /* Well, the process existed : we must get it in the process hash
10a1069a 697 * or add it, and draw its items.
698 */
699 /* Add process to process list (if not present) */
1c736ed5 700 guint pl_height = 0;
10a1069a 701 HashedProcessData *hashed_process_data = NULL;
5c230fc4 702 ProcessList *process_list = control_flow_data->process_list;
10a1069a 703 LttTime birth = process->creation_time;
e800cf84 704
ac4e21cf 705 hashed_process_data = processlist_get_process_data(process_list,
10a1069a 706 pid_in,
88bf15f0 707 cpu,
10a1069a 708 &birth,
8924e3e4 709 trace_number);//TODO "use the right value or delete"
ac4e21cf 710 if(hashed_process_data == NULL)
10a1069a 711 {
712 g_assert(pid_in == 0 || pid_in != process->ppid);
713 /* Process not present */
4e86ae2e 714 ProcessInfo *process_info;
1c736ed5 715 Drawing_t *drawing = control_flow_data->drawing;
10a1069a 716 processlist_add(process_list,
1c736ed5 717 drawing,
10a1069a 718 pid_in,
fcc08e1e 719 process->tgid,
88bf15f0 720 cpu,
10a1069a 721 process->ppid,
722 &birth,
8924e3e4 723 trace_number,
f4b88a7d 724 process->name,
7b5f6cf1 725 process->brand,
10a1069a 726 &pl_height,
4e86ae2e 727 &process_info,
10a1069a 728 &hashed_process_data);
1c736ed5 729 gtk_widget_set_size_request(drawing->drawing_area,
730 -1,
731 pl_height);
732 gtk_widget_queue_draw(drawing->drawing_area);
733
10a1069a 734 }
40debf7b 735 //We could set the current process and hash here, but will be done
736 //by after schedchange hook
10a1069a 737
738 /* Now, the process is in the state hash and our own process hash.
739 * We definitely can draw the items related to the ending state.
740 */
b9a010a2 741
b2743953 742 if(ltt_time_compare(hashed_process_data->next_good_time,
88bf15f0 743 timestamp) > 0)
10a1069a 744 {
b2743953 745 if(hashed_process_data->x.middle_marked == FALSE) {
ac4e21cf 746
fd22065b 747 TimeWindow time_window =
748 lttvwindow_get_time_window(control_flow_data->tab);
749#ifdef EXTRA_CHECK
750 if(ltt_time_compare(evtime, time_window.start_time) == -1
751 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 752 return FALSE;
fd22065b 753#endif //EXTRA_CHECK
d6fef890 754 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 755 guint width = drawing->width;
b2743953 756 guint x;
757 convert_time_to_pixels(
758 time_window,
88bf15f0 759 timestamp,
b2743953 760 width,
761 &x);
762
763 /* Draw collision indicator */
764 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 765 gdk_draw_point(hashed_process_data->pixmap,
b2743953 766 drawing->gc,
767 x,
5bb606ce 768 COLLISION_POSITION(hashed_process_data->height));
b2743953 769 hashed_process_data->x.middle_marked = TRUE;
770 }
771 } else {
fd22065b 772 TimeWindow time_window =
773 lttvwindow_get_time_window(control_flow_data->tab);
774#ifdef EXTRA_CHECK
775 if(ltt_time_compare(evtime, time_window.start_time) == -1
776 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 777 return FALSE;
fd22065b 778#endif //EXTRA_CHECK
d6fef890 779 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 780 guint width = drawing->width;
10a1069a 781 guint x;
10a1069a 782
783 convert_time_to_pixels(
a18124ff 784 time_window,
88bf15f0 785 timestamp,
4b7dc462 786 width,
787 &x);
10a1069a 788
10a1069a 789
4b7dc462 790 /* Jump over draw if we are at the same x position */
e72908ed 791 if(x == hashed_process_data->x.middle &&
792 hashed_process_data->x.middle_used)
4b7dc462 793 {
e72908ed 794 if(hashed_process_data->x.middle_marked == FALSE) {
795 /* Draw collision indicator */
796 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 797 gdk_draw_point(hashed_process_data->pixmap,
e72908ed 798 drawing->gc,
799 x,
5bb606ce 800 COLLISION_POSITION(hashed_process_data->height));
de4ea1ad 801 hashed_process_data->x.middle_marked = TRUE;
e72908ed 802 }
4b7dc462 803 /* jump */
804 } else {
805 DrawContext draw_context;
10a1069a 806
4b7dc462 807 /* Now create the drawing context that will be used to draw
808 * items related to the last state. */
1c736ed5 809 draw_context.drawable = hashed_process_data->pixmap;
4b7dc462 810 draw_context.gc = drawing->gc;
811 draw_context.pango_layout = drawing->pango_layout;
812 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
813 draw_context.drawinfo.end.x = x;
10a1069a 814
1c736ed5 815 draw_context.drawinfo.y.over = 1;
816 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
817 draw_context.drawinfo.y.under = hashed_process_data->height;
10a1069a 818
4b7dc462 819 draw_context.drawinfo.start.offset.over = 0;
820 draw_context.drawinfo.start.offset.middle = 0;
821 draw_context.drawinfo.start.offset.under = 0;
822 draw_context.drawinfo.end.offset.over = 0;
823 draw_context.drawinfo.end.offset.middle = 0;
824 draw_context.drawinfo.end.offset.under = 0;
825
826 {
827 /* Draw the line */
9a1ec01b 828 PropertiesLine prop_line = prepare_s_e_line(process);
4b7dc462 829 draw_line((void*)&prop_line, (void*)&draw_context);
830 }
831
832
833 /* become the last x position */
834 hashed_process_data->x.middle = x;
e72908ed 835 hashed_process_data->x.middle_used = TRUE;
836 hashed_process_data->x.middle_marked = FALSE;
b2743953 837
838 /* Calculate the next good time */
839 convert_pixels_to_time(width, x+1, time_window,
840 &hashed_process_data->next_good_time);
4b7dc462 841 }
c8bba5fa 842 }
8e680509 843 } else
844 g_warning("Cannot find pin_in in schedchange %u", pid_in);
88bf15f0 845#ifdef BABEL_CLEANUP
e38d9ea0 846 tfc->target_pid = target_pid_saved;
88bf15f0 847#endif //babel_cleanup
b9a010a2 848 return 0;
849
850
b9a010a2 851
a56a1ba4 852
51705146 853 /* Text dump */
80a52ff8 854#ifdef DONTSHOW
a56a1ba4 855 GString *string = g_string_new("");;
856 gboolean field_names = TRUE, state = TRUE;
80a52ff8 857
e9a9c513 858 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
859 g_string_append_printf(string,"\n");
860
861 if(state) {
862 g_string_append_printf(string, " %s",
863 g_quark_to_string(tfs->process->state->s));
864 }
865
866 g_info("%s",string->str);
867
a56a1ba4 868 g_string_free(string, TRUE);
869
870 /* End of text dump */
80a52ff8 871#endif //DONTSHOW
50439712 872
f0d936c0 873}
874
e92eabaf 875/* after_schedchange_hook
b9a010a2 876 *
877 * The draw after hook is called by the reading API to have a
878 * particular event drawn on the screen.
879 * @param hook_data ControlFlowData structure of the viewer.
880 * @param call_data Event context.
881 *
882 * This function adds items to be drawn in a queue for each process.
883 *
884 */
e92eabaf 885int after_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 886{
7b20eed1 887 LttvEvent *event;
50439712 888
7b20eed1
YB
889 event = (LttvEvent *) call_data;
890
891 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_switch") != 0)
892 return FALSE;
50439712 893
7b20eed1 894 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
50439712 895
348c6ba8 896
7b20eed1 897 LttvTraceState *ts = event->state;
b9a010a2 898
7b20eed1 899#ifdef BABEL_CLEANUP
e38d9ea0 900 LttvFilter *filter = control_flow_data->filter;
7b20eed1
YB
901#endif
902 LttTime evtime = lttv_event_get_timestamp(event);
b9a010a2 903
10a1069a 904 /* Add process to process list (if not present) */
2eef04b5 905 LttvProcessState *process_in;
10a1069a 906 LttTime birth;
1c736ed5 907 guint pl_height = 0;
10a1069a 908 HashedProcessData *hashed_process_data_in = NULL;
b9a010a2 909
5c230fc4 910 ProcessList *process_list = control_flow_data->process_list;
10a1069a 911
912 guint pid_in;
913 {
7b20eed1 914 pid_in = lttv_event_get_long(event, "next_tid");
10a1069a 915 }
b9a010a2 916
7b20eed1 917#ifdef BABEL_CLEANUP
c7620c79 918 if(!filter || !filter->head ||
919 lttv_filter_tree_parse(filter->head,e,tfc->tf,
920 tfc->t_context->t,tfc,NULL,NULL)) {
7b20eed1
YB
921#else
922 {
923#endif
c7620c79 924 /* Find process pid_in in the list... */
925 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
926 //process_in = tfs->process;
7b20eed1
YB
927 guint cpu = lttv_traceset_get_cpuid_from_event(event);
928 guint trace_num = 0; /* TODO set right trace number */
c7620c79 929 process_in = ts->running_process[cpu];
930 /* It should exist, because we are after the state update. */
96947fcf 931#ifdef EXTRA_CHECK
c7620c79 932 g_assert(process_in != NULL);
96947fcf 933#endif //EXTRA_CHECK
c7620c79 934 birth = process_in->creation_time;
935
936 hashed_process_data_in = processlist_get_process_data(process_list,
937 pid_in,
938 process_in->cpu,
939 &birth,
940 trace_num);
941 if(hashed_process_data_in == NULL)
942 {
943 g_assert(pid_in == 0 || pid_in != process_in->ppid);
944 ProcessInfo *process_info;
945 Drawing_t *drawing = control_flow_data->drawing;
946 /* Process not present */
947 processlist_add(process_list,
948 drawing,
10a1069a 949 pid_in,
c7620c79 950 process_in->tgid,
348c6ba8 951 process_in->cpu,
c7620c79 952 process_in->ppid,
10a1069a 953 &birth,
c7620c79 954 trace_num,
955 process_in->name,
956 process_in->brand,
957 &pl_height,
958 &process_info,
959 &hashed_process_data_in);
960 gtk_widget_set_size_request(drawing->drawing_area,
961 -1,
962 pl_height);
963 gtk_widget_queue_draw(drawing->drawing_area);
964 }
965 /* Set the current process */
966 process_list->current_hash_data[trace_num][process_in->cpu] =
967 hashed_process_data_in;
968
969 if(ltt_time_compare(hashed_process_data_in->next_good_time,
970 evtime) <= 0)
971 {
972 TimeWindow time_window =
973 lttvwindow_get_time_window(control_flow_data->tab);
974
fd22065b 975#ifdef EXTRA_CHECK
c7620c79 976 if(ltt_time_compare(evtime, time_window.start_time) == -1
977 || ltt_time_compare(evtime, time_window.end_time) == 1)
978 return FALSE;
fd22065b 979#endif //EXTRA_CHECK
c7620c79 980 Drawing_t *drawing = control_flow_data->drawing;
981 guint width = drawing->width;
982 guint new_x;
983
984 convert_time_to_pixels(
985 time_window,
986 evtime,
987 width,
988 &new_x);
989
990 if(hashed_process_data_in->x.middle != new_x) {
991 hashed_process_data_in->x.middle = new_x;
992 hashed_process_data_in->x.middle_used = FALSE;
993 hashed_process_data_in->x.middle_marked = FALSE;
994 }
b2743953 995 }
996 }
c7620c79 997
10599fb9 998 return 0;
4a24fa1f 999}
b9a010a2 1000
1001
1002
e72908ed 1003
4a24fa1f 1004/* before_execmode_hook
1005 *
1006 * This function basically draw lines and icons. Two types of lines are drawn :
1007 * one small (3 pixels?) representing the state of the process and the second
1008 * type is thicker (10 pixels?) representing on which CPU a process is running
1009 * (and this only in running state).
1010 *
1011 * Extremums of the lines :
1012 * x_min : time of the last event context for this process kept in memory.
1013 * x_max : time of the current event.
1014 * y : middle of the process in the process list. The process is found in the
1015 * list, therefore is it's position in pixels.
1016 *
1017 * The choice of lines'color is defined by the context of the last event for this
1018 * process.
1019 */
1020
e72908ed 1021
4a24fa1f 1022int before_execmode_hook(void *hook_data, void *call_data)
1023{
88bf15f0
FD
1024 LttvEvent *event;
1025 guint cpu;
10599fb9 1026 guint pid = 0;
88bf15f0
FD
1027 LttvTraceState *ts;
1028 LttvProcessState *process;
1029
4a24fa1f 1030 /* we are in a execmode, before the state update. We must draw the
1031 * items corresponding to the state before it changes : now is the right
1032 * time to do it.
1033 */
88bf15f0
FD
1034
1035 event = (LttvEvent *) call_data;
8924e3e4
FD
1036 if ((strncmp(lttv_traceset_get_name_from_event(event),"sys_", sizeof("sys_") - 1) == 0)
1037 ||(strcmp(lttv_traceset_get_name_from_event(event),"exit_syscall") == 0)
1038 ||(strncmp(lttv_traceset_get_name_from_event(event),"irq_handler_",sizeof("irq_handler_")) == 0)
1039 ||(strncmp(lttv_traceset_get_name_from_event(event),"softirq_", sizeof("softirq_")) == 0)){
1040
88bf15f0
FD
1041 LttTime evtime = lttv_event_get_timestamp(event);
1042 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
4a24fa1f 1043 /* For the pid */
88bf15f0
FD
1044 LttvTraceset *traceSet = lttvwindow_get_traceset(control_flow_data->tab);
1045
1046 cpu = lttv_traceset_get_cpuid_from_event(event);
1047 ts = event->state;
1048
1049 guint trace_number = 0;//TODO fdeslauriers 2012-07-17: // Use trace handle to know trace number
8924e3e4 1050 process = lttv_state_find_process(ts ,cpu ,pid);
4a24fa1f 1051 g_assert(process != NULL);
23093869 1052
10a1069a 1053 guint pid = process->pid;
23093869 1054
10a1069a 1055 /* Well, the process_out existed : we must get it in the process hash
1056 * or add it, and draw its items.
1057 */
1058 /* Add process to process list (if not present) */
1c736ed5 1059 guint pl_height = 0;
10a1069a 1060 HashedProcessData *hashed_process_data = NULL;
5c230fc4 1061 ProcessList *process_list = control_flow_data->process_list;
88bf15f0
FD
1062 if(process_list->current_hash_data == NULL){//TODO fdeslauriers 2012-07-17 : should not be necessary
1063 return 0;
1064 }
1065
10a1069a 1066 LttTime birth = process->creation_time;
40debf7b 1067
88bf15f0
FD
1068 if(likely(process_list->current_hash_data[trace_number][cpu] != NULL)) {
1069 hashed_process_data = process_list->current_hash_data[trace_number][cpu];
40debf7b 1070 } else {
ac4e21cf 1071 hashed_process_data = processlist_get_process_data(process_list,
40debf7b 1072 pid,
348c6ba8 1073 process->cpu,
40debf7b 1074 &birth,
88bf15f0 1075 trace_number);
1d1df11d 1076 if(unlikely(hashed_process_data == NULL))
40debf7b 1077 {
1078 g_assert(pid == 0 || pid != process->ppid);
1079 ProcessInfo *process_info;
1080 /* Process not present */
1c736ed5 1081 Drawing_t *drawing = control_flow_data->drawing;
40debf7b 1082 processlist_add(process_list,
1c736ed5 1083 drawing,
40debf7b 1084 pid,
fcc08e1e 1085 process->tgid,
348c6ba8 1086 process->cpu,
40debf7b 1087 process->ppid,
1088 &birth,
88bf15f0 1089 trace_number,
f4b88a7d 1090 process->name,
7b5f6cf1 1091 process->brand,
40debf7b 1092 &pl_height,
1093 &process_info,
1094 &hashed_process_data);
1c736ed5 1095 gtk_widget_set_size_request(drawing->drawing_area,
1096 -1,
1097 pl_height);
1098 gtk_widget_queue_draw(drawing->drawing_area);
40debf7b 1099 }
1100 /* Set the current process */
88bf15f0 1101 process_list->current_hash_data[trace_number][process->cpu] =
40debf7b 1102 hashed_process_data;
10a1069a 1103 }
23093869 1104
10a1069a 1105 /* Now, the process is in the state hash and our own process hash.
1106 * We definitely can draw the items related to the ending state.
1107 */
b2743953 1108
1d1df11d 1109 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1110 evtime) > 0))
10a1069a 1111 {
1d1df11d 1112 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
fd22065b 1113 TimeWindow time_window =
1114 lttvwindow_get_time_window(control_flow_data->tab);
1115
1116#ifdef EXTRA_CHECK
1117 if(ltt_time_compare(evtime, time_window.start_time) == -1
1118 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1119 return FALSE;
fd22065b 1120#endif //EXTRA_CHECK
d6fef890 1121 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 1122 guint width = drawing->width;
b2743953 1123 guint x;
1124 convert_time_to_pixels(
1125 time_window,
1126 evtime,
1127 width,
1128 &x);
1129
1130 /* Draw collision indicator */
1131 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 1132 gdk_draw_point(hashed_process_data->pixmap,
b2743953 1133 drawing->gc,
1134 x,
5bb606ce 1135 COLLISION_POSITION(hashed_process_data->height));
b2743953 1136 hashed_process_data->x.middle_marked = TRUE;
1137 }
1138 } else {
fd22065b 1139 TimeWindow time_window =
1140 lttvwindow_get_time_window(control_flow_data->tab);
1141
1142#ifdef EXTRA_CHECK
1143 if(ltt_time_compare(evtime, time_window.start_time) == -1
1144 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1145 return FALSE;
fd22065b 1146#endif //EXTRA_CHECK
d6fef890 1147 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 1148 guint width = drawing->width;
10a1069a 1149 guint x;
dbd243b1 1150
10a1069a 1151 convert_time_to_pixels(
a18124ff 1152 time_window,
10a1069a 1153 evtime,
1154 width,
1155 &x);
dbd243b1 1156
23093869 1157
4b7dc462 1158 /* Jump over draw if we are at the same x position */
1d1df11d 1159 if(unlikely(x == hashed_process_data->x.middle &&
1160 hashed_process_data->x.middle_used))
10a1069a 1161 {
1d1df11d 1162 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
e72908ed 1163 /* Draw collision indicator */
1164 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 1165 gdk_draw_point(hashed_process_data->pixmap,
e72908ed 1166 drawing->gc,
1167 x,
5bb606ce 1168 COLLISION_POSITION(hashed_process_data->height));
de4ea1ad 1169 hashed_process_data->x.middle_marked = TRUE;
e72908ed 1170 }
4b7dc462 1171 /* jump */
1172 } else {
1173
1174 DrawContext draw_context;
1175 /* Now create the drawing context that will be used to draw
1176 * items related to the last state. */
1c736ed5 1177 draw_context.drawable = hashed_process_data->pixmap;
4b7dc462 1178 draw_context.gc = drawing->gc;
1179 draw_context.pango_layout = drawing->pango_layout;
9a1ec01b 1180 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
4b7dc462 1181 draw_context.drawinfo.end.x = x;
1182
1c736ed5 1183 draw_context.drawinfo.y.over = 1;
1184 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1185 draw_context.drawinfo.y.under = hashed_process_data->height;
4b7dc462 1186
1187 draw_context.drawinfo.start.offset.over = 0;
1188 draw_context.drawinfo.start.offset.middle = 0;
1189 draw_context.drawinfo.start.offset.under = 0;
1190 draw_context.drawinfo.end.offset.over = 0;
1191 draw_context.drawinfo.end.offset.middle = 0;
1192 draw_context.drawinfo.end.offset.under = 0;
1193
1194 {
1195 /* Draw the line */
9a1ec01b 1196 PropertiesLine prop_line = prepare_s_e_line(process);
4b7dc462 1197 draw_line((void*)&prop_line, (void*)&draw_context);
23093869 1198
4b7dc462 1199 }
1200 /* become the last x position */
9a1ec01b 1201 hashed_process_data->x.middle = x;
e72908ed 1202 hashed_process_data->x.middle_used = TRUE;
1203 hashed_process_data->x.middle_marked = FALSE;
b2743953 1204
1205 /* Calculate the next good time */
1206 convert_pixels_to_time(width, x+1, time_window,
1207 &hashed_process_data->next_good_time);
23093869 1208 }
1209 }
8924e3e4 1210 }
23093869 1211 return 0;
1212}
1213
4a24fa1f 1214/* before_process_exit_hook
23093869 1215 *
4a24fa1f 1216 * Draw lines for process event.
1217 *
23093869 1218 * @param hook_data ControlFlowData structure of the viewer.
1219 * @param call_data Event context.
1220 *
1221 * This function adds items to be drawn in a queue for each process.
1222 *
1223 */
8869ac08 1224
1225
4a24fa1f 1226int before_process_exit_hook(void *hook_data, void *call_data)
1227{
23093869 1228
7b20eed1 1229 LttvEvent *event;
23093869 1230
7b20eed1
YB
1231 event = (LttvEvent *) call_data;
1232 if (strcmp(lttv_traceset_get_name_from_event(event),
1233 "sched_process_exit") != 0)
1234 return FALSE;
4a24fa1f 1235
7b20eed1
YB
1236
1237 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1238 LttvTraceState *ts = event->state;
23093869 1239
7b20eed1 1240#ifdef BABEL_CLEANUP
e38d9ea0 1241 LttvFilter *filter = control_flow_data->filter;
1242 if(filter != NULL && filter->head != NULL)
1243 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1244 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1245 return FALSE;
7b20eed1 1246#endif
e38d9ea0 1247
7b20eed1 1248 LttTime evtime = lttv_event_get_timestamp(event);
23093869 1249
10a1069a 1250 /* Add process to process list (if not present) */
4a24fa1f 1251 //LttvProcessState *process = tfs->process;
7b20eed1
YB
1252 guint cpu = lttv_traceset_get_cpuid_from_event(event);
1253 guint trace_num = 0; /* TODO set right trace number */
1254
4a24fa1f 1255 LttvProcessState *process = ts->running_process[cpu];
1256 guint pid = process->pid;
10a1069a 1257 LttTime birth;
1c736ed5 1258 guint pl_height = 0;
10a1069a 1259 HashedProcessData *hashed_process_data = NULL;
23093869 1260
5c230fc4 1261 ProcessList *process_list = control_flow_data->process_list;
4a24fa1f 1262
10a1069a 1263 g_assert(process != NULL);
23093869 1264
10a1069a 1265 birth = process->creation_time;
23093869 1266
0f090e21 1267 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1268 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
40debf7b 1269 } else {
ac4e21cf 1270 hashed_process_data = processlist_get_process_data(process_list,
4a24fa1f 1271 pid,
1272 process->cpu,
1273 &birth,
0f090e21 1274 trace_num);
1d1df11d 1275 if(unlikely(hashed_process_data == NULL))
40debf7b 1276 {
1277 g_assert(pid == 0 || pid != process->ppid);
1278 /* Process not present */
1c736ed5 1279 Drawing_t *drawing = control_flow_data->drawing;
40debf7b 1280 ProcessInfo *process_info;
1281 processlist_add(process_list,
1c736ed5 1282 drawing,
40debf7b 1283 pid,
fcc08e1e 1284 process->tgid,
4a24fa1f 1285 process->cpu,
40debf7b 1286 process->ppid,
1287 &birth,
0f090e21 1288 trace_num,
4a24fa1f 1289 process->name,
7b5f6cf1 1290 process->brand,
40debf7b 1291 &pl_height,
1292 &process_info,
1293 &hashed_process_data);
4a24fa1f 1294 gtk_widget_set_size_request(drawing->drawing_area,
1295 -1,
1296 pl_height);
1297 gtk_widget_queue_draw(drawing->drawing_area);
40debf7b 1298 }
23093869 1299 }
40debf7b 1300
4a24fa1f 1301 /* Now, the process is in the state hash and our own process hash.
1302 * We definitely can draw the items related to the ending state.
1303 */
1304
1305 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1306 evtime) > 0))
b2743953 1307 {
4a24fa1f 1308 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1309 TimeWindow time_window =
1310 lttvwindow_get_time_window(control_flow_data->tab);
1311
1312#ifdef EXTRA_CHECK
1313 if(ltt_time_compare(evtime, time_window.start_time) == -1
1314 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1315 return FALSE;
4a24fa1f 1316#endif //EXTRA_CHECK
1317 Drawing_t *drawing = control_flow_data->drawing;
1318 guint width = drawing->width;
1319 guint x;
1320 convert_time_to_pixels(
1321 time_window,
1322 evtime,
1323 width,
1324 &x);
1325
1326 /* Draw collision indicator */
1327 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1328 gdk_draw_point(hashed_process_data->pixmap,
1329 drawing->gc,
1330 x,
5bb606ce 1331 COLLISION_POSITION(hashed_process_data->height));
4a24fa1f 1332 hashed_process_data->x.middle_marked = TRUE;
1333 }
1334 } else {
fd22065b 1335 TimeWindow time_window =
1336 lttvwindow_get_time_window(control_flow_data->tab);
1337
1338#ifdef EXTRA_CHECK
1339 if(ltt_time_compare(evtime, time_window.start_time) == -1
1340 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1341 return FALSE;
fd22065b 1342#endif //EXTRA_CHECK
d6fef890 1343 Drawing_t *drawing = control_flow_data->drawing;
1344 guint width = drawing->width;
4a24fa1f 1345 guint x;
1346
2c82c4dc 1347 convert_time_to_pixels(
1348 time_window,
1349 evtime,
1350 width,
1351 &x);
1352
b2743953 1353
2c82c4dc 1354 /* Jump over draw if we are at the same x position */
1355 if(unlikely(x == hashed_process_data->x.middle &&
1356 hashed_process_data->x.middle_used))
1357 {
1358 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
b2743953 1359 /* Draw collision indicator */
1360 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 1361 gdk_draw_point(hashed_process_data->pixmap,
b2743953 1362 drawing->gc,
1363 x,
5bb606ce 1364 COLLISION_POSITION(hashed_process_data->height));
b2743953 1365 hashed_process_data->x.middle_marked = TRUE;
1366 }
2c82c4dc 1367 /* jump */
b2743953 1368 } else {
2c82c4dc 1369 DrawContext draw_context;
fd22065b 1370
2c82c4dc 1371 /* Now create the drawing context that will be used to draw
1372 * items related to the last state. */
1373 draw_context.drawable = hashed_process_data->pixmap;
1374 draw_context.gc = drawing->gc;
1375 draw_context.pango_layout = drawing->pango_layout;
1376 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1377 draw_context.drawinfo.end.x = x;
dbd243b1 1378
2c82c4dc 1379 draw_context.drawinfo.y.over = 1;
1380 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1381 draw_context.drawinfo.y.under = hashed_process_data->height;
dbd243b1 1382
2c82c4dc 1383 draw_context.drawinfo.start.offset.over = 0;
1384 draw_context.drawinfo.start.offset.middle = 0;
1385 draw_context.drawinfo.start.offset.under = 0;
1386 draw_context.drawinfo.end.offset.over = 0;
1387 draw_context.drawinfo.end.offset.middle = 0;
1388 draw_context.drawinfo.end.offset.under = 0;
dbd243b1 1389
2c82c4dc 1390 {
1391 /* Draw the line */
1392 PropertiesLine prop_line = prepare_s_e_line(process);
1393 draw_line((void*)&prop_line, (void*)&draw_context);
dbd243b1 1394
2c82c4dc 1395 }
1396 /* become the last x position */
1397 hashed_process_data->x.middle = x;
1398 hashed_process_data->x.middle_used = TRUE;
1399 hashed_process_data->x.middle_marked = FALSE;
dbd243b1 1400
2c82c4dc 1401 /* Calculate the next good time */
1402 convert_pixels_to_time(width, x+1, time_window,
1403 &hashed_process_data->next_good_time);
1404 }
1405 }
7b20eed1 1406
10599fb9 1407 return 0;
2c82c4dc 1408
1409}
1410
1411
1412
1413/* before_process_release_hook
1414 *
1415 * Draw lines for process event.
1416 *
1417 * @param hook_data ControlFlowData structure of the viewer.
1418 * @param call_data Event context.
1419 *
1420 * This function adds items to be drawn in a queue for each process.
1421 *
1422 */
1423
1424
1425int before_process_release_hook(void *hook_data, void *call_data)
1426{
2c82c4dc 1427
7b20eed1 1428 LttvEvent *event;
2c82c4dc 1429
7b20eed1
YB
1430 event = (LttvEvent *) call_data;
1431
1432 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_free") != 0)
1433 return FALSE;
2c82c4dc 1434
7b20eed1 1435 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 1436
2c82c4dc 1437
7b20eed1
YB
1438 LttvTraceState *ts = event->state;
1439
1440#ifdef BABEL_CLEANUP
e38d9ea0 1441 LttvFilter *filter = control_flow_data->filter;
1442 if(filter != NULL && filter->head != NULL)
1443 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1444 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1445 return FALSE;
7b20eed1
YB
1446#endif
1447 LttTime evtime = lttv_event_get_timestamp(event);
e38d9ea0 1448
2c82c4dc 1449
7b20eed1 1450 guint trace_num = 0; /* TODO set right trace number */
2c82c4dc 1451
1452 guint pid;
1453 {
7b20eed1 1454 pid = lttv_event_get_long(event, "tid");
2c82c4dc 1455 }
1456
1457 /* Add process to process list (if not present) */
1458 /* Don't care about the process if it's not in the state hash already :
1459 * that means a process that has never done anything in the trace and
1460 * unknown suddently gets destroyed : no state meaningful to show. */
348c6ba8 1461 LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
2c82c4dc 1462
1463 if(process != NULL) {
1464 LttTime birth;
2c82c4dc 1465 HashedProcessData *hashed_process_data = NULL;
1466
1467 ProcessList *process_list = control_flow_data->process_list;
1468
1469 birth = process->creation_time;
1470
1471 /* Cannot use current process : this event happens on another process,
1472 * action done by the parent. */
1473 hashed_process_data = processlist_get_process_data(process_list,
1474 pid,
348c6ba8 1475 process->cpu,
2c82c4dc 1476 &birth,
0f090e21 1477 trace_num);
2c82c4dc 1478 if(unlikely(hashed_process_data == NULL))
3311444c 1479 /*
1480 * Process already been scheduled out EXIT_DEAD, not in the process list
1481 * anymore. Just return.
1482 */
1483 return FALSE;
2c82c4dc 1484
1485 /* Now, the process is in the state hash and our own process hash.
1486 * We definitely can draw the items related to the ending state.
1487 */
1488
1489 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1490 evtime) > 0))
1491 {
1492 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1493 TimeWindow time_window =
1494 lttvwindow_get_time_window(control_flow_data->tab);
1495
1496#ifdef EXTRA_CHECK
1497 if(ltt_time_compare(evtime, time_window.start_time) == -1
1498 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1499 return FALSE;
2c82c4dc 1500#endif //EXTRA_CHECK
1501 Drawing_t *drawing = control_flow_data->drawing;
1502 guint width = drawing->width;
1503 guint x;
1504 convert_time_to_pixels(
1505 time_window,
1506 evtime,
1507 width,
1508 &x);
1509
1510 /* Draw collision indicator */
1511 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1512 gdk_draw_point(hashed_process_data->pixmap,
1513 drawing->gc,
1514 x,
5bb606ce 1515 COLLISION_POSITION(hashed_process_data->height));
2c82c4dc 1516 hashed_process_data->x.middle_marked = TRUE;
1517 }
1518 } else {
1519 TimeWindow time_window =
1520 lttvwindow_get_time_window(control_flow_data->tab);
1521
1522#ifdef EXTRA_CHECK
1523 if(ltt_time_compare(evtime, time_window.start_time) == -1
4a24fa1f 1524 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1525 return FALSE;
2da61677 1526#endif //EXTRA_CHECK
4a24fa1f 1527 Drawing_t *drawing = control_flow_data->drawing;
1528 guint width = drawing->width;
1529 guint x;
1530
1531 convert_time_to_pixels(
1532 time_window,
1533 evtime,
1534 width,
1535 &x);
1536
2da61677 1537
4a24fa1f 1538 /* Jump over draw if we are at the same x position */
1539 if(unlikely(x == hashed_process_data->x.middle &&
1540 hashed_process_data->x.middle_used))
1541 {
1542 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2da61677 1543 /* Draw collision indicator */
1544 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1545 gdk_draw_point(hashed_process_data->pixmap,
1546 drawing->gc,
1547 x,
5bb606ce 1548 COLLISION_POSITION(hashed_process_data->height));
2da61677 1549 hashed_process_data->x.middle_marked = TRUE;
1550 }
4a24fa1f 1551 /* jump */
2da61677 1552 } else {
4a24fa1f 1553 DrawContext draw_context;
2da61677 1554
4a24fa1f 1555 /* Now create the drawing context that will be used to draw
1556 * items related to the last state. */
1557 draw_context.drawable = hashed_process_data->pixmap;
1558 draw_context.gc = drawing->gc;
1559 draw_context.pango_layout = drawing->pango_layout;
1560 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1561 draw_context.drawinfo.end.x = x;
2da61677 1562
4a24fa1f 1563 draw_context.drawinfo.y.over = 1;
1564 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1565 draw_context.drawinfo.y.under = hashed_process_data->height;
2da61677 1566
4a24fa1f 1567 draw_context.drawinfo.start.offset.over = 0;
1568 draw_context.drawinfo.start.offset.middle = 0;
1569 draw_context.drawinfo.start.offset.under = 0;
1570 draw_context.drawinfo.end.offset.over = 0;
1571 draw_context.drawinfo.end.offset.middle = 0;
1572 draw_context.drawinfo.end.offset.under = 0;
2da61677 1573
4a24fa1f 1574 {
1575 /* Draw the line */
1576 PropertiesLine prop_line = prepare_s_e_line(process);
1577 draw_line((void*)&prop_line, (void*)&draw_context);
2da61677 1578
2da61677 1579 }
4a24fa1f 1580 /* become the last x position */
1581 hashed_process_data->x.middle = x;
1582 hashed_process_data->x.middle_used = TRUE;
1583 hashed_process_data->x.middle_marked = FALSE;
1584
1585 /* Calculate the next good time */
1586 convert_pixels_to_time(width, x+1, time_window,
1587 &hashed_process_data->next_good_time);
2da61677 1588 }
1589 }
dbd243b1 1590 }
dbd243b1 1591
10599fb9 1592 return 0;
dbd243b1 1593}
1594
4a24fa1f 1595
2c82c4dc 1596
1597
1598
1599/* after_process_fork_hook
1600 *
1601 * Create the processlist entry for the child process. Put the last
1602 * position in x at the current time value.
1603 *
1604 * @param hook_data ControlFlowData structure of the viewer.
1605 * @param call_data Event context.
1606 *
1607 * This function adds items to be drawn in a queue for each process.
1608 *
1609 */
1610int after_process_fork_hook(void *hook_data, void *call_data)
1611{
7b20eed1 1612 LttvEvent *event;
2c82c4dc 1613
7b20eed1
YB
1614 event = (LttvEvent *) call_data;
1615
1616 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_fork") != 0)
1617 return FALSE;
2c82c4dc 1618
7b20eed1 1619 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 1620
2c82c4dc 1621
7b20eed1
YB
1622 LttvTraceState *ts = event->state;
1623
1624#ifdef BABEL_CLEANUP
e38d9ea0 1625 LttvFilter *filter = control_flow_data->filter;
1626 if(filter != NULL && filter->head != NULL)
1627 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1628 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1629 return FALSE;
7b20eed1 1630#endif
e38d9ea0 1631
7b20eed1 1632 LttTime evtime = lttv_event_get_timestamp(event);
2c82c4dc 1633
1634 guint child_pid;
1635 {
7b20eed1 1636 child_pid = lttv_event_get_long(event, "child_tid");
2c82c4dc 1637 }
1638
1639 /* Add process to process list (if not present) */
1640 LttvProcessState *process_child;
1641 LttTime birth;
1642 guint pl_height = 0;
1643 HashedProcessData *hashed_process_data_child = NULL;
1644
1645 ProcessList *process_list = control_flow_data->process_list;
1646
1647 /* Find child in the list... */
348c6ba8 1648 process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
2c82c4dc 1649 /* It should exist, because we are after the state update. */
1650 g_assert(process_child != NULL);
1651
1652 birth = process_child->creation_time;
7b20eed1 1653 guint trace_num = 0; /* TODO put right */
2c82c4dc 1654
1655 /* Cannot use current process, because this action is done by the parent
1656 * on its child. */
1657 hashed_process_data_child = processlist_get_process_data(process_list,
1658 child_pid,
348c6ba8 1659 process_child->cpu,
2c82c4dc 1660 &birth,
0f090e21 1661 trace_num);
2c82c4dc 1662 if(likely(hashed_process_data_child == NULL))
1663 {
1664 g_assert(child_pid == 0 || child_pid != process_child->ppid);
1665 /* Process not present */
1666 Drawing_t *drawing = control_flow_data->drawing;
2c82c4dc 1667 ProcessInfo *process_info;
1668 processlist_add(process_list,
1669 drawing,
1670 child_pid,
fcc08e1e 1671 process_child->tgid,
348c6ba8 1672 process_child->cpu,
2c82c4dc 1673 process_child->ppid,
1674 &birth,
0f090e21 1675 trace_num,
f4b88a7d 1676 process_child->name,
7b5f6cf1 1677 process_child->brand,
2c82c4dc 1678 &pl_height,
1679 &process_info,
1680 &hashed_process_data_child);
1681 gtk_widget_set_size_request(drawing->drawing_area,
1682 -1,
1683 pl_height);
1684 gtk_widget_queue_draw(drawing->drawing_area);
fcc08e1e 1685 } else {
1686 processlist_set_ppid(process_list, process_child->ppid,
1687 hashed_process_data_child);
1688 processlist_set_tgid(process_list, process_child->tgid,
1689 hashed_process_data_child);
2c82c4dc 1690 }
1691
1692
1693 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
1694 evtime) <= 0))
1695 {
1696 TimeWindow time_window =
1697 lttvwindow_get_time_window(control_flow_data->tab);
1698
1699#ifdef EXTRA_CHECK
1700 if(ltt_time_compare(evtime, time_window.start_time) == -1
1701 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1702 return FALSE;
2c82c4dc 1703#endif //EXTRA_CHECK
1704 Drawing_t *drawing = control_flow_data->drawing;
1705 guint width = drawing->width;
1706 guint new_x;
1707 convert_time_to_pixels(
1708 time_window,
1709 evtime,
1710 width,
1711 &new_x);
1712
1713 if(likely(hashed_process_data_child->x.over != new_x)) {
1714 hashed_process_data_child->x.over = new_x;
1715 hashed_process_data_child->x.over_used = FALSE;
1716 hashed_process_data_child->x.over_marked = FALSE;
1717 }
1718 if(likely(hashed_process_data_child->x.middle != new_x)) {
1719 hashed_process_data_child->x.middle = new_x;
1720 hashed_process_data_child->x.middle_used = FALSE;
1721 hashed_process_data_child->x.middle_marked = FALSE;
1722 }
1723 if(likely(hashed_process_data_child->x.under != new_x)) {
1724 hashed_process_data_child->x.under = new_x;
1725 hashed_process_data_child->x.under_used = FALSE;
1726 hashed_process_data_child->x.under_marked = FALSE;
1727 }
1728 }
10599fb9 1729 return FALSE;
2c82c4dc 1730}
1731
1732
1733
1734/* after_process_exit_hook
1735 *
1736 * Create the processlist entry for the child process. Put the last
1737 * position in x at the current time value.
1738 *
1739 * @param hook_data ControlFlowData structure of the viewer.
1740 * @param call_data Event context.
1741 *
1742 * This function adds items to be drawn in a queue for each process.
1743 *
1744 */
1745int after_process_exit_hook(void *hook_data, void *call_data)
1746{
7b20eed1
YB
1747#if 0
1748 LttvEvent *event;
2c82c4dc 1749
7b20eed1
YB
1750 event = (LttvEvent *) call_data;
1751
1752 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_exit") != 0)
1753 return FALSE;
2c82c4dc 1754
7b20eed1 1755 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 1756
7b20eed1 1757 LttvTraceState *ts = event->state;
2c82c4dc 1758
7b20eed1 1759#ifdef BABEL_CLEANUP
e38d9ea0 1760 LttvFilter *filter = control_flow_data->filter;
1761 if(filter != NULL && filter->head != NULL)
1762 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1763 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1764 return FALSE;
7b20eed1 1765#endif
e38d9ea0 1766
7b20eed1 1767 LttTime evtime = lttv_event_get_timestamp(event);
2c82c4dc 1768
1769 /* Add process to process list (if not present) */
348c6ba8 1770 //LttvProcessState *process = tfs->process;
7b20eed1
YB
1771 guint cpu = lttv_traceset_get_cpuid_from_event(event);
1772 guint trace_num = 0; /* TODO set right trace number */
348c6ba8 1773 LttvProcessState *process = ts->running_process[cpu];
1774
1775 /* It should exist, because we are after the state update. */
1776 g_assert(process != NULL);
1777
2c82c4dc 1778 guint pid = process->pid;
1779 LttTime birth;
1780 guint pl_height = 0;
1781 HashedProcessData *hashed_process_data = NULL;
1782
1783 ProcessList *process_list = control_flow_data->process_list;
1784
2c82c4dc 1785 birth = process->creation_time;
1786
0f090e21 1787 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){
1788 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
2c82c4dc 1789 } else {
1790 hashed_process_data = processlist_get_process_data(process_list,
1791 pid,
348c6ba8 1792 process->cpu,
2c82c4dc 1793 &birth,
0f090e21 1794 trace_num);
2c82c4dc 1795 if(unlikely(hashed_process_data == NULL))
1796 {
1797 g_assert(pid == 0 || pid != process->ppid);
1798 /* Process not present */
1799 Drawing_t *drawing = control_flow_data->drawing;
2c82c4dc 1800 ProcessInfo *process_info;
1801 processlist_add(process_list,
1802 drawing,
1803 pid,
fcc08e1e 1804 process->tgid,
348c6ba8 1805 process->cpu,
2c82c4dc 1806 process->ppid,
1807 &birth,
0f090e21 1808 trace_num,
f4b88a7d 1809 process->name,
7b5f6cf1 1810 process->brand,
2c82c4dc 1811 &pl_height,
1812 &process_info,
1813 &hashed_process_data);
1814 gtk_widget_set_size_request(drawing->drawing_area,
1815 -1,
1816 pl_height);
1817 gtk_widget_queue_draw(drawing->drawing_area);
1818 }
1819
1820 /* Set the current process */
0f090e21 1821 process_list->current_hash_data[trace_num][process->cpu] =
2c82c4dc 1822 hashed_process_data;
1823 }
1824
1825 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1826 evtime) <= 0))
1827 {
1828 TimeWindow time_window =
1829 lttvwindow_get_time_window(control_flow_data->tab);
dbd243b1 1830
2c82c4dc 1831#ifdef EXTRA_CHECK
1832 if(ltt_time_compare(evtime, time_window.start_time) == -1
1833 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1834 return FALSE;
2c82c4dc 1835#endif //EXTRA_CHECK
1836 Drawing_t *drawing = control_flow_data->drawing;
1837 guint width = drawing->width;
1838 guint new_x;
1839 convert_time_to_pixels(
1840 time_window,
1841 evtime,
1842 width,
1843 &new_x);
1844 if(unlikely(hashed_process_data->x.middle != new_x)) {
1845 hashed_process_data->x.middle = new_x;
1846 hashed_process_data->x.middle_used = FALSE;
1847 hashed_process_data->x.middle_marked = FALSE;
1848 }
1849 }
7b20eed1 1850#endif
10599fb9 1851 return FALSE;
2c82c4dc 1852}
dbd243b1 1853
1854
f4b88a7d 1855/* Get the filename of the process to print */
1856int after_fs_exec_hook(void *hook_data, void *call_data)
1857{
88bf15f0 1858#ifdef BABEL_CLEANUP
dd455fb8 1859 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1860 EventsRequest *events_request = (EventsRequest*)th->hook_data;
f4b88a7d 1861 ControlFlowData *control_flow_data = events_request->viewer_data;
1862
1863 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1864
1865 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1866
1867 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1868
e38d9ea0 1869 LttEvent *e;
1870 e = ltt_tracefile_get_event(tfc->tf);
1871
1872 LttvFilter *filter = control_flow_data->filter;
1873 if(filter != NULL && filter->head != NULL)
1874 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1875 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1876 return FALSE;
1877
ae3d0f50 1878 guint cpu = tfs->cpu;
0f090e21 1879 guint trace_num = ts->parent.index;
f4b88a7d 1880 LttvProcessState *process = ts->running_process[cpu];
1881 g_assert(process != NULL);
1882
1883 guint pid = process->pid;
1884
1885 /* Well, the process_out existed : we must get it in the process hash
1886 * or add it, and draw its items.
1887 */
1888 /* Add process to process list (if not present) */
1889 guint pl_height = 0;
1890 HashedProcessData *hashed_process_data = NULL;
1891 ProcessList *process_list = control_flow_data->process_list;
1892 LttTime birth = process->creation_time;
1893
0f090e21 1894 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1895 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
f4b88a7d 1896 } else {
1897 hashed_process_data = processlist_get_process_data(process_list,
1898 pid,
1899 process->cpu,
1900 &birth,
0f090e21 1901 trace_num);
f4b88a7d 1902 if(unlikely(hashed_process_data == NULL))
1903 {
1904 g_assert(pid == 0 || pid != process->ppid);
1905 ProcessInfo *process_info;
1906 /* Process not present */
1907 Drawing_t *drawing = control_flow_data->drawing;
1908 processlist_add(process_list,
1909 drawing,
1910 pid,
fcc08e1e 1911 process->tgid,
f4b88a7d 1912 process->cpu,
1913 process->ppid,
1914 &birth,
0f090e21 1915 trace_num,
f4b88a7d 1916 process->name,
7b5f6cf1 1917 process->brand,
f4b88a7d 1918 &pl_height,
1919 &process_info,
1920 &hashed_process_data);
1921 gtk_widget_set_size_request(drawing->drawing_area,
1922 -1,
1923 pl_height);
1924 gtk_widget_queue_draw(drawing->drawing_area);
1925 }
1926 /* Set the current process */
0f090e21 1927 process_list->current_hash_data[trace_num][process->cpu] =
f4b88a7d 1928 hashed_process_data;
1929 }
1930
1931 processlist_set_name(process_list, process->name, hashed_process_data);
1932
88bf15f0 1933#endif //babel_cleanup
10599fb9 1934 return 0;
f4b88a7d 1935
1936}
1937
7b5f6cf1 1938/* Get the filename of the process to print */
1939int after_user_generic_thread_brand_hook(void *hook_data, void *call_data)
1940{
88bf15f0 1941#ifdef BABEL_CLEANUP
dd455fb8 1942 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1943 EventsRequest *events_request = (EventsRequest*)th->hook_data;
7b5f6cf1 1944 ControlFlowData *control_flow_data = events_request->viewer_data;
1945
1946 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1947
1948 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1949
1950 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1951
e38d9ea0 1952 LttEvent *e;
1953 e = ltt_tracefile_get_event(tfc->tf);
1954
1955 LttvFilter *filter = control_flow_data->filter;
1956 if(filter != NULL && filter->head != NULL)
1957 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1958 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1959 return FALSE;
1960
7b5f6cf1 1961 guint cpu = tfs->cpu;
0f090e21 1962 guint trace_num = ts->parent.index;
7b5f6cf1 1963 LttvProcessState *process = ts->running_process[cpu];
1964 g_assert(process != NULL);
1965
1966 guint pid = process->pid;
1967
1968 /* Well, the process_out existed : we must get it in the process hash
1969 * or add it, and draw its items.
1970 */
1971 /* Add process to process list (if not present) */
1972 guint pl_height = 0;
1973 HashedProcessData *hashed_process_data = NULL;
1974 ProcessList *process_list = control_flow_data->process_list;
1975 LttTime birth = process->creation_time;
1976
0f090e21 1977 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1978 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
7b5f6cf1 1979 } else {
1980 hashed_process_data = processlist_get_process_data(process_list,
1981 pid,
1982 process->cpu,
1983 &birth,
0f090e21 1984 trace_num);
7b5f6cf1 1985 if(unlikely(hashed_process_data == NULL))
1986 {
1987 g_assert(pid == 0 || pid != process->ppid);
1988 ProcessInfo *process_info;
1989 /* Process not present */
1990 Drawing_t *drawing = control_flow_data->drawing;
1991 processlist_add(process_list,
1992 drawing,
1993 pid,
fcc08e1e 1994 process->tgid,
7b5f6cf1 1995 process->cpu,
1996 process->ppid,
1997 &birth,
0f090e21 1998 trace_num,
7b5f6cf1 1999 process->name,
2000 process->brand,
2001 &pl_height,
2002 &process_info,
2003 &hashed_process_data);
2004 gtk_widget_set_size_request(drawing->drawing_area,
2005 -1,
2006 pl_height);
2007 gtk_widget_queue_draw(drawing->drawing_area);
2008 }
2009 /* Set the current process */
0f090e21 2010 process_list->current_hash_data[trace_num][process->cpu] =
7b5f6cf1 2011 hashed_process_data;
2012 }
2013
2014 processlist_set_brand(process_list, process->brand, hashed_process_data);
2015
88bf15f0 2016#endif //babel_cleanup
10599fb9 2017 return 0;
7b5f6cf1 2018}
2019
2020
b3fd4c02 2021/* after_event_enum_process_hook
2022 *
b3fd4c02 2023 * Create the processlist entry for the child process. Put the last
2024 * position in x at the current time value.
2025 *
2026 * @param hook_data ControlFlowData structure of the viewer.
2027 * @param call_data Event context.
2028 *
2029 * This function adds items to be drawn in a queue for each process.
2030 *
2031 */
2032int after_event_enum_process_hook(void *hook_data, void *call_data)
2033{
7b20eed1 2034 LttvEvent *event;
b3fd4c02 2035
7b20eed1
YB
2036 event = (LttvEvent *) call_data;
2037
2038 if (strcmp(lttv_traceset_get_name_from_event(event),"lttng_statedump_process_state") != 0)
2039 return FALSE;
b3fd4c02 2040
7b20eed1 2041 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
b3fd4c02 2042
c4a72569 2043
7b20eed1 2044 LttvTraceState *ts = event->state;
b3fd4c02 2045
7b20eed1
YB
2046 guint first_cpu, nb_cpus, cpu;
2047
2048#ifdef BABEL_CLEANUP
e38d9ea0 2049 LttvFilter *filter = control_flow_data->filter;
2050 if(filter != NULL && filter->head != NULL)
2051 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 2052 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 2053 return FALSE;
7b20eed1 2054#endif
b3fd4c02 2055 /* Add process to process list (if not present) */
2056 LttvProcessState *process_in;
2057 LttTime birth;
2058 guint pl_height = 0;
2059 HashedProcessData *hashed_process_data_in = NULL;
2060
2061 ProcessList *process_list = control_flow_data->process_list;
7b20eed1 2062 guint trace_num = 0; /* TODO put right trace number */
b3fd4c02 2063
2064 guint pid_in;
2065 {
7b20eed1 2066 pid_in = lttv_event_get_long(event, "tid");
b3fd4c02 2067 }
c4a72569 2068
2069 if(pid_in == 0) {
2070 first_cpu = 0;
7b20eed1 2071 nb_cpus = lttv_trace_get_num_cpu(ts->trace);
c4a72569 2072 } else {
2073 first_cpu = ANY_CPU;
2074 nb_cpus = ANY_CPU+1;
2075 }
b3fd4c02 2076
c4a72569 2077 for(cpu = first_cpu; cpu < nb_cpus; cpu++) {
2078 /* Find process pid_in in the list... */
2079 process_in = lttv_state_find_process(ts, cpu, pid_in);
2080 //process_in = tfs->process;
2081 //guint cpu = tfs->cpu;
2082 //guint trace_num = ts->parent.index;
2083 //process_in = ts->running_process[cpu];
2084 /* It should exist, because we are after the state update. */
2085 #ifdef EXTRA_CHECK
2086 //g_assert(process_in != NULL);
2087 #endif //EXTRA_CHECK
2088 birth = process_in->creation_time;
2089
2090 hashed_process_data_in = processlist_get_process_data(process_list,
2091 pid_in,
2092 process_in->cpu,
2093 &birth,
2094 trace_num);
2095 if(hashed_process_data_in == NULL)
2096 {
2097 if(pid_in != 0 && pid_in == process_in->ppid)
2098 g_critical("TEST %u , %u", pid_in, process_in->ppid);
2099 g_assert(pid_in == 0 || pid_in != process_in->ppid);
2100 ProcessInfo *process_info;
2101 Drawing_t *drawing = control_flow_data->drawing;
2102 /* Process not present */
2103 processlist_add(process_list,
2104 drawing,
b3fd4c02 2105 pid_in,
c4a72569 2106 process_in->tgid,
b3fd4c02 2107 process_in->cpu,
c4a72569 2108 process_in->ppid,
b3fd4c02 2109 &birth,
c4a72569 2110 trace_num,
2111 process_in->name,
2112 process_in->brand,
2113 &pl_height,
2114 &process_info,
2115 &hashed_process_data_in);
2116 gtk_widget_set_size_request(drawing->drawing_area,
2117 -1,
2118 pl_height);
2119 gtk_widget_queue_draw(drawing->drawing_area);
2120 } else {
2121 processlist_set_name(process_list, process_in->name,
2122 hashed_process_data_in);
2123 processlist_set_ppid(process_list, process_in->ppid,
2124 hashed_process_data_in);
2125 processlist_set_tgid(process_list, process_in->tgid,
2126 hashed_process_data_in);
2127 }
2128 }
10599fb9 2129 return 0;
b3fd4c02 2130}
f4b88a7d 2131
2132
1b238973 2133gint update_time_window_hook(void *hook_data, void *call_data)
f7afe191 2134{
a56a1ba4 2135 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
a43d67ba 2136 Drawing_t *drawing = control_flow_data->drawing;
1c736ed5 2137 ProcessList *process_list = control_flow_data->process_list;
a43d67ba 2138
224446ce 2139 const TimeWindowNotifyData *time_window_nofify_data =
2140 ((const TimeWindowNotifyData *)call_data);
2141
14963be0 2142 TimeWindow *old_time_window =
224446ce 2143 time_window_nofify_data->old_time_window;
2144 TimeWindow *new_time_window =
2145 time_window_nofify_data->new_time_window;
a56a1ba4 2146
3cb8b205 2147 /* Update the ruler */
2148 drawing_update_ruler(control_flow_data->drawing,
2149 new_time_window);
2150
2151
a56a1ba4 2152 /* Two cases : zoom in/out or scrolling */
2153
2154 /* In order to make sure we can reuse the old drawing, the scale must
2155 * be the same and the new time interval being partly located in the
2156 * currently shown time interval. (reuse is only for scrolling)
2157 */
2158
2eef04b5 2159 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
14963be0 2160 old_time_window->start_time.tv_sec,
2161 old_time_window->start_time.tv_nsec,
2162 old_time_window->time_width.tv_sec,
2163 old_time_window->time_width.tv_nsec);
a56a1ba4 2164
2eef04b5 2165 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
14963be0 2166 new_time_window->start_time.tv_sec,
2167 new_time_window->start_time.tv_nsec,
2168 new_time_window->time_width.tv_sec,
2169 new_time_window->time_width.tv_nsec);
a56a1ba4 2170
14963be0 2171 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
2172 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
a56a1ba4 2173 {
2174 /* Same scale (scrolling) */
2175 g_info("scrolling");
14963be0 2176 LttTime *ns = &new_time_window->start_time;
2177 LttTime *os = &old_time_window->start_time;
6f26fc38 2178 LttTime old_end = old_time_window->end_time;
2179 LttTime new_end = new_time_window->end_time;
a56a1ba4 2180 //if(ns<os+w<ns+w)
2181 //if(ns<os+w && os+w<ns+w)
2182 //if(ns<old_end && os<ns)
2183 if(ltt_time_compare(*ns, old_end) == -1
2184 && ltt_time_compare(*os, *ns) == -1)
2185 {
2186 g_info("scrolling near right");
2187 /* Scroll right, keep right part of the screen */
2188 guint x = 0;
51705146 2189 guint width = control_flow_data->drawing->width;
a56a1ba4 2190 convert_time_to_pixels(
a18124ff 2191 *old_time_window,
a56a1ba4 2192 *ns,
2193 width,
2194 &x);
2195
2196 /* Copy old data to new location */
1c736ed5 2197 copy_pixmap_region(process_list,
2198 NULL,
2199 control_flow_data->drawing->drawing_area->style->black_gc,
2200 NULL,
2201 x, 0,
2202 0, 0,
2203 control_flow_data->drawing->width-x+SAFETY, -1);
2204
6395d57c 2205 if(drawing->damage_begin == drawing->damage_end)
2206 drawing->damage_begin = control_flow_data->drawing->width-x;
2207 else
2208 drawing->damage_begin = 0;
2209
2210 drawing->damage_end = control_flow_data->drawing->width;
2211
a56a1ba4 2212 /* Clear the data request background, but not SAFETY */
1c736ed5 2213 rectangle_pixmap(process_list,
cfe526b1 2214 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2215 TRUE,
6395d57c 2216 drawing->damage_begin+SAFETY, 0,
2217 drawing->damage_end - drawing->damage_begin, // do not overlap
1c736ed5 2218 -1);
7abb23ad 2219 gtk_widget_queue_draw(drawing->drawing_area);
2220 //gtk_widget_queue_draw_area (drawing->drawing_area,
2221 // 0,0,
2222 // control_flow_data->drawing->width,
2223 // control_flow_data->drawing->height);
a43d67ba 2224
a56a1ba4 2225 /* Get new data for the rest. */
501d5405 2226 drawing_data_request(control_flow_data->drawing,
6395d57c 2227 drawing->damage_begin, 0,
2228 drawing->damage_end - drawing->damage_begin,
501d5405 2229 control_flow_data->drawing->height);
a56a1ba4 2230 } else {
2231 //if(ns<os<ns+w)
2232 //if(ns<os && os<ns+w)
2233 //if(ns<os && os<new_end)
2234 if(ltt_time_compare(*ns,*os) == -1
2235 && ltt_time_compare(*os,new_end) == -1)
2236 {
2237 g_info("scrolling near left");
2238 /* Scroll left, keep left part of the screen */
2239 guint x = 0;
51705146 2240 guint width = control_flow_data->drawing->width;
a56a1ba4 2241 convert_time_to_pixels(
a18124ff 2242 *new_time_window,
a56a1ba4 2243 *os,
2244 width,
2245 &x);
6395d57c 2246
a56a1ba4 2247 /* Copy old data to new location */
1c736ed5 2248 copy_pixmap_region (process_list,
2249 NULL,
cfe526b1 2250 control_flow_data->drawing->drawing_area->style->black_gc,
1c736ed5 2251 NULL,
a56a1ba4 2252 0, 0,
2253 x, 0,
2254 -1, -1);
2255
6395d57c 2256 if(drawing->damage_begin == drawing->damage_end)
2257 drawing->damage_end = x;
2258 else
2259 drawing->damage_end =
51705146 2260 control_flow_data->drawing->width;
6395d57c 2261
2262 drawing->damage_begin = 0;
2263
1c736ed5 2264 rectangle_pixmap (process_list,
cfe526b1 2265 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2266 TRUE,
6395d57c 2267 drawing->damage_begin, 0,
2268 drawing->damage_end - drawing->damage_begin, // do not overlap
1c736ed5 2269 -1);
a43d67ba 2270
7abb23ad 2271 gtk_widget_queue_draw(drawing->drawing_area);
2272 //gtk_widget_queue_draw_area (drawing->drawing_area,
2273 // 0,0,
2274 // control_flow_data->drawing->width,
2275 // control_flow_data->drawing->height);
a43d67ba 2276
6395d57c 2277
a56a1ba4 2278 /* Get new data for the rest. */
501d5405 2279 drawing_data_request(control_flow_data->drawing,
6395d57c 2280 drawing->damage_begin, 0,
2281 drawing->damage_end - drawing->damage_begin,
501d5405 2282 control_flow_data->drawing->height);
a56a1ba4 2283
a56a1ba4 2284 } else {
a43d67ba 2285 if(ltt_time_compare(*ns,*os) == 0)
2286 {
2287 g_info("not scrolling");
2288 } else {
2289 g_info("scrolling far");
2290 /* Cannot reuse any part of the screen : far jump */
2291
2292
1c736ed5 2293 rectangle_pixmap (process_list,
a43d67ba 2294 control_flow_data->drawing->drawing_area->style->black_gc,
2295 TRUE,
a56a1ba4 2296 0, 0,
a43d67ba 2297 control_flow_data->drawing->width+SAFETY, // do not overlap
1c736ed5 2298 -1);
a43d67ba 2299
7abb23ad 2300 //gtk_widget_queue_draw_area (drawing->drawing_area,
2301 // 0,0,
2302 // control_flow_data->drawing->width,
2303 // control_flow_data->drawing->height);
2304 gtk_widget_queue_draw(drawing->drawing_area);
a43d67ba 2305
6395d57c 2306 drawing->damage_begin = 0;
2307 drawing->damage_end = control_flow_data->drawing->width;
2308
a43d67ba 2309 drawing_data_request(control_flow_data->drawing,
a43d67ba 2310 0, 0,
2311 control_flow_data->drawing->width,
2312 control_flow_data->drawing->height);
2313
2314 }
a56a1ba4 2315 }
2316 }
2317 } else {
2318 /* Different scale (zoom) */
2319 g_info("zoom");
2320
1c736ed5 2321 rectangle_pixmap (process_list,
cfe526b1 2322 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2323 TRUE,
2324 0, 0,
501d5405 2325 control_flow_data->drawing->width+SAFETY, // do not overlap
1c736ed5 2326 -1);
a56a1ba4 2327
7abb23ad 2328 //gtk_widget_queue_draw_area (drawing->drawing_area,
2329 // 0,0,
2330 // control_flow_data->drawing->width,
2331 // control_flow_data->drawing->height);
2332 gtk_widget_queue_draw(drawing->drawing_area);
a56a1ba4 2333
6395d57c 2334 drawing->damage_begin = 0;
2335 drawing->damage_end = control_flow_data->drawing->width;
2336
501d5405 2337 drawing_data_request(control_flow_data->drawing,
a56a1ba4 2338 0, 0,
501d5405 2339 control_flow_data->drawing->width,
2340 control_flow_data->drawing->height);
a56a1ba4 2341 }
2342
15f77e3b 2343 /* Update directly when scrolling */
2344 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
2345 TRUE);
3cb8b205 2346
a56a1ba4 2347 return 0;
f7afe191 2348}
2349
6395d57c 2350gint traceset_notify(void *hook_data, void *call_data)
2351{
2352 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2353 Drawing_t *drawing = control_flow_data->drawing;
6395d57c 2354
6cec4cd2 2355 if(unlikely(drawing->gc == NULL)) {
2356 return FALSE;
2357 }
2358 if(drawing->dotted_gc == NULL) {
2359 return FALSE;
2360 }
6395d57c 2361
b9a010a2 2362 drawing_clear(control_flow_data->drawing);
2363 processlist_clear(control_flow_data->process_list);
07390ec1 2364 gtk_widget_set_size_request(
2365 control_flow_data->drawing->drawing_area,
2366 -1, processlist_get_height(control_flow_data->process_list));
d9267eec 2367 redraw_notify(control_flow_data, NULL);
6395d57c 2368
d9267eec 2369 request_background_data(control_flow_data);
6395d57c 2370
2371 return FALSE;
2372}
2373
ca0f8a8e 2374gint redraw_notify(void *hook_data, void *call_data)
2375{
2376 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2377 Drawing_t *drawing = control_flow_data->drawing;
2378 GtkWidget *widget = drawing->drawing_area;
2379
2380 drawing->damage_begin = 0;
51705146 2381 drawing->damage_end = drawing->width;
ca0f8a8e 2382
49217bd4 2383 /* fun feature, to be separated someday... */
2384 drawing_clear(control_flow_data->drawing);
2385 processlist_clear(control_flow_data->process_list);
07390ec1 2386 gtk_widget_set_size_request(
2387 control_flow_data->drawing->drawing_area,
2388 -1, processlist_get_height(control_flow_data->process_list));
1c736ed5 2389 // Clear the images
2390 rectangle_pixmap (control_flow_data->process_list,
ca0f8a8e 2391 widget->style->black_gc,
2392 TRUE,
2393 0, 0,
f3b7430d 2394 drawing->alloc_width,
1c736ed5 2395 -1);
ca0f8a8e 2396
f3b7430d 2397 gtk_widget_queue_draw(drawing->drawing_area);
4a24fa1f 2398
ca0f8a8e 2399 if(drawing->damage_begin < drawing->damage_end)
2400 {
2401 drawing_data_request(drawing,
ca0f8a8e 2402 drawing->damage_begin,
2403 0,
2404 drawing->damage_end-drawing->damage_begin,
51705146 2405 drawing->height);
ca0f8a8e 2406 }
2407
7abb23ad 2408 //gtk_widget_queue_draw_area(drawing->drawing_area,
2409 // 0,0,
2410 // drawing->width,
2411 // drawing->height);
ca0f8a8e 2412 return FALSE;
2413
2414}
2415
2416
2417gint continue_notify(void *hook_data, void *call_data)
a43d67ba 2418{
2419 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
ca0f8a8e 2420 Drawing_t *drawing = control_flow_data->drawing;
a43d67ba 2421
6395d57c 2422 //g_assert(widget->allocation.width == drawing->damage_end);
ca0f8a8e 2423
2424 if(drawing->damage_begin < drawing->damage_end)
2425 {
2426 drawing_data_request(drawing,
ca0f8a8e 2427 drawing->damage_begin,
2428 0,
2429 drawing->damage_end-drawing->damage_begin,
51705146 2430 drawing->height);
ca0f8a8e 2431 }
2432
2433 return FALSE;
2434}
2435
2436
1b238973 2437gint update_current_time_hook(void *hook_data, void *call_data)
f7afe191 2438{
88bf15f0 2439
14963be0 2440 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
a56a1ba4 2441
224446ce 2442 LttTime current_time = *((LttTime*)call_data);
88bf15f0 2443
ca0f8a8e 2444 TimeWindow time_window =
2445 lttvwindow_get_time_window(control_flow_data->tab);
a56a1ba4 2446
ca0f8a8e 2447 LttTime time_begin = time_window.start_time;
2448 LttTime width = time_window.time_width;
90ef7e4a 2449 LttTime half_width;
2450 {
2451 guint64 time_ll = ltt_time_to_uint64(width);
2452 time_ll = time_ll >> 1; /* divide by two */
2453 half_width = ltt_time_from_uint64(time_ll);
2454 }
a56a1ba4 2455 LttTime time_end = ltt_time_add(time_begin, width);
2456
88bf15f0 2457 LttvTraceset * ts = lttvwindow_get_traceset(control_flow_data->tab);
a56a1ba4 2458
88bf15f0
FD
2459 TimeInterval time_span = lttv_traceset_get_time_span_real(ts);
2460 LttTime trace_start = time_span.start_time;
2461 LttTime trace_end = time_span.end_time;
a56a1ba4 2462
2eef04b5 2463 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
224446ce 2464 current_time.tv_nsec);
a56a1ba4 2465
2466
2467
2468 /* If current time is inside time interval, just move the highlight
2469 * bar */
2470
2471 /* Else, we have to change the time interval. We have to tell it
2472 * to the main window. */
2473 /* The time interval change will take care of placing the current
2474 * time at the center of the visible area, or nearest possible if we are
2475 * at one end of the trace. */
2476
2477
dbc0ef8a 2478 if(ltt_time_compare(current_time, time_begin) < 0)
a56a1ba4 2479 {
224446ce 2480 TimeWindow new_time_window;
2481
2482 if(ltt_time_compare(current_time,
dbc0ef8a 2483 ltt_time_add(trace_start,half_width)) < 0)
a56a1ba4 2484 time_begin = trace_start;
2485 else
224446ce 2486 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 2487
224446ce 2488 new_time_window.start_time = time_begin;
2489 new_time_window.time_width = width;
a18124ff 2490 new_time_window.time_width_double = ltt_time_to_double(width);
6f26fc38 2491 new_time_window.end_time = ltt_time_add(time_begin, width);
a56a1ba4 2492
e800cf84 2493 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 2494 }
dbc0ef8a 2495 else if(ltt_time_compare(current_time, time_end) > 0)
a56a1ba4 2496 {
224446ce 2497 TimeWindow new_time_window;
2498
dbc0ef8a 2499 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
a56a1ba4 2500 time_begin = ltt_time_sub(trace_end,width);
2501 else
224446ce 2502 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 2503
224446ce 2504 new_time_window.start_time = time_begin;
2505 new_time_window.time_width = width;
a18124ff 2506 new_time_window.time_width_double = ltt_time_to_double(width);
6f26fc38 2507 new_time_window.end_time = ltt_time_add(time_begin, width);
a56a1ba4 2508
e800cf84 2509 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 2510
2511 }
7abb23ad 2512 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
a56a1ba4 2513
15f77e3b 2514 /* Update directly when scrolling */
2515 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
2516 TRUE);
2517
a56a1ba4 2518 return 0;
88bf15f0 2519
f7afe191 2520}
2521
8b90e648 2522typedef struct _ClosureData {
ca0f8a8e 2523 EventsRequest *events_request;
b9a010a2 2524 LttTime end_time;
bc8d270b 2525 guint x_end;
8b90e648 2526} ClosureData;
a56a1ba4 2527
8b90e648 2528
e800cf84 2529void draw_closure(gpointer key, gpointer value, gpointer user_data)
2530{
88bf15f0 2531
a56a1ba4 2532 ProcessInfo *process_info = (ProcessInfo*)key;
2533 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
2534 ClosureData *closure_data = (ClosureData*)user_data;
88bf15f0 2535
e800cf84 2536 EventsRequest *events_request = closure_data->events_request;
2537 ControlFlowData *control_flow_data = events_request->viewer_data;
88bf15f0 2538 LttvTraceset *ts = lttvwindow_get_traceset(control_flow_data->tab);
a56a1ba4 2539
a56a1ba4 2540
e800cf84 2541 LttTime evtime = closure_data->end_time;
d0cd7f09 2542
e3162168 2543 gboolean dodraw = TRUE;
2544
e800cf84 2545 {
2546 /* For the process */
2547 /* First, check if the current process is in the state computation
2548 * process list. If it is there, that means we must add it right now and
2549 * draw items from the beginning of the read for it. If it is not
2550 * present, it's a new process and it was not present : it will
2551 * be added after the state update. */
31b6868d 2552#ifdef EXTRA_CHECK
e800cf84 2553 g_assert(lttv_traceset_number(tsc->ts) > 0);
31b6868d 2554#endif //EXTRA_CHECK
88bf15f0
FD
2555 //TODO Fdeslauriers 2012-07-17: adapt for multiple traces
2556 LttvTrace *trace = lttv_traceset_get(ts,0);
2557 LttvTraceState *trace_state = trace->state;
2c82c4dc 2558
348c6ba8 2559#if 0
2c82c4dc 2560 //FIXME : optimize data structures.
2561 LttvTracefileState *tfs;
2562 LttvTracefileContext *tfc;
2563 guint i;
2564 for(i=0;i<tc->tracefiles->len;i++) {
2565 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
2566 if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
ae3d0f50 2567 && tfs->cpu == process_info->cpu)
2c82c4dc 2568 break;
2569
2570 }
2571 g_assert(i<tc->tracefiles->len);
2572 tfs = LTTV_TRACEFILE_STATE(tfc);
348c6ba8 2573#endif //0
88bf15f0 2574 // LttvTracefileState *tfs =ts
2c82c4dc 2575 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
2576 // tracefiles[process_info->cpu];
2da61677 2577
e800cf84 2578 LttvProcessState *process;
88bf15f0 2579 process = lttv_state_find_process(trace_state, process_info->cpu,
e025a729 2580 process_info->pid);
a56a1ba4 2581
1d1df11d 2582 if(unlikely(process != NULL)) {
88bf15f0 2583#ifdef BABEL_CLEANUP
b6ef18af 2584 LttvFilter *filter = control_flow_data->filter;
2585 if(filter != NULL && filter->head != NULL)
2586 if(!lttv_filter_tree_parse(filter->head,NULL,NULL,
2587 tc->t,NULL,process,tc))
e3162168 2588 dodraw = FALSE;
88bf15f0 2589#endif //babel_cleanup
e800cf84 2590 /* Only draw for processes that are currently in the trace states */
ad2e83ba 2591
1d1df11d 2592#ifdef EXTRA_CHECK
e800cf84 2593 /* Should be alike when background info is ready */
2594 if(control_flow_data->background_info_waiting==0)
2595 g_assert(ltt_time_compare(process->creation_time,
2596 process_info->birth) == 0);
1d1df11d 2597#endif //EXTRA_CHECK
e800cf84 2598
2599 /* Now, the process is in the state hash and our own process hash.
2600 * We definitely can draw the items related to the ending state.
2601 */
2602
1d1df11d 2603 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
2604 evtime) <= 0))
e800cf84 2605 {
fd22065b 2606 TimeWindow time_window =
2607 lttvwindow_get_time_window(control_flow_data->tab);
2608
2609#ifdef EXTRA_CHECK
2610 if(ltt_time_compare(evtime, time_window.start_time) == -1
2611 || ltt_time_compare(evtime, time_window.end_time) == 1)
2612 return;
2613#endif //EXTRA_CHECK
d6fef890 2614 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 2615 guint width = drawing->width;
a56a1ba4 2616
bc8d270b 2617 guint x = closure_data->x_end;
8b90e648 2618
4b7dc462 2619 DrawContext draw_context;
2620
e800cf84 2621 /* Now create the drawing context that will be used to draw
2622 * items related to the last state. */
1c736ed5 2623 draw_context.drawable = hashed_process_data->pixmap;
e800cf84 2624 draw_context.gc = drawing->gc;
2625 draw_context.pango_layout = drawing->pango_layout;
e800cf84 2626 draw_context.drawinfo.end.x = x;
2627
1c736ed5 2628 draw_context.drawinfo.y.over = 1;
2629 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2630 draw_context.drawinfo.y.under = hashed_process_data->height;
e800cf84 2631
2632 draw_context.drawinfo.start.offset.over = 0;
2633 draw_context.drawinfo.start.offset.middle = 0;
2634 draw_context.drawinfo.start.offset.under = 0;
2635 draw_context.drawinfo.end.offset.over = 0;
2636 draw_context.drawinfo.end.offset.middle = 0;
2637 draw_context.drawinfo.end.offset.under = 0;
9a1ec01b 2638#if 0
4b7dc462 2639 /* Jump over draw if we are at the same x position */
2640 if(x == hashed_process_data->x.over)
e800cf84 2641 {
4b7dc462 2642 /* jump */
2643 } else {
23093869 2644 draw_context.drawinfo.start.x = hashed_process_data->x.over;
2645 /* Draw the line */
2646 PropertiesLine prop_line = prepare_execmode_line(process);
2647 draw_line((void*)&prop_line, (void*)&draw_context);
2648
4b7dc462 2649 hashed_process_data->x.over = x;
23093869 2650 }
9a1ec01b 2651#endif //0
4b7dc462 2652
1d1df11d 2653 if(unlikely(x == hashed_process_data->x.middle &&
2654 hashed_process_data->x.middle_used)) {
b2743953 2655#if 0 /* do not mark closure : not missing information */
e72908ed 2656 if(hashed_process_data->x.middle_marked == FALSE) {
2657 /* Draw collision indicator */
2658 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2659 gdk_draw_point(drawing->pixmap,
2660 drawing->gc,
2661 x,
2c6618bc 2662 y+(height/2)-3);
de4ea1ad 2663 hashed_process_data->x.middle_marked = TRUE;
e72908ed 2664 }
b2743953 2665#endif //0
4b7dc462 2666 /* Jump */
2667 } else {
23093869 2668 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
e800cf84 2669 /* Draw the line */
c4a72569 2670 if(dodraw) {
2671 PropertiesLine prop_line = prepare_s_e_line(process);
2672 draw_line((void*)&prop_line, (void*)&draw_context);
2673 }
e800cf84 2674
4b7dc462 2675 /* become the last x position */
1d1df11d 2676 if(likely(x != hashed_process_data->x.middle)) {
e72908ed 2677 hashed_process_data->x.middle = x;
2678 /* but don't use the pixel */
2679 hashed_process_data->x.middle_used = FALSE;
b2743953 2680
2681 /* Calculate the next good time */
2682 convert_pixels_to_time(width, x+1, time_window,
2683 &hashed_process_data->next_good_time);
e72908ed 2684 }
e800cf84 2685 }
e800cf84 2686 }
2687 }
2688 }
2689 return;
8b90e648 2690}
2691
b9a010a2 2692int before_chunk(void *hook_data, void *call_data)
2693{
88bf15f0 2694
b9a010a2 2695 EventsRequest *events_request = (EventsRequest*)hook_data;
88bf15f0 2696 LttvTraceset *ts = (LttvTraceset*)call_data;
cd3892fe 2697#if 0
7c0125e0 2698 /* Desactivate sort */
2699 gtk_tree_sortable_set_sort_column_id(
2700 GTK_TREE_SORTABLE(cfd->process_list->list_store),
2701 TRACE_COLUMN,
2702 GTK_SORT_ASCENDING);
cd3892fe 2703#endif //0
88bf15f0 2704 drawing_chunk_begin(events_request, ts);
b9a010a2 2705
2706 return 0;
2707}
2708
2709int before_request(void *hook_data, void *call_data)
ca0f8a8e 2710{
88bf15f0 2711
ca0f8a8e 2712 EventsRequest *events_request = (EventsRequest*)hook_data;
7c0125e0 2713
88bf15f0 2714 drawing_data_request_begin(events_request);
ca0f8a8e 2715
2716 return 0;
88bf15f0 2717
ca0f8a8e 2718}
2719
2720
8b90e648 2721/*
b9a010a2 2722 * after request is necessary in addition of after chunk in order to draw
2723 * lines until the end of the screen. after chunk just draws lines until
2724 * the last event.
2725 *
8b90e648 2726 * for each process
a56a1ba4 2727 * draw closing line
b9a010a2 2728 * expose
8b90e648 2729 */
b9a010a2 2730int after_request(void *hook_data, void *call_data)
8b90e648 2731{
88bf15f0 2732
ca0f8a8e 2733 EventsRequest *events_request = (EventsRequest*)hook_data;
2734 ControlFlowData *control_flow_data = events_request->viewer_data;
a56a1ba4 2735
5c230fc4 2736 ProcessList *process_list = control_flow_data->process_list;
b9a010a2 2737 LttTime end_time = events_request->end_time;
2738
2739 ClosureData closure_data;
2740 closure_data.events_request = (EventsRequest*)hook_data;
b9a010a2 2741 closure_data.end_time = end_time;
2742
bc8d270b 2743 TimeWindow time_window =
2744 lttvwindow_get_time_window(control_flow_data->tab);
2745 guint width = control_flow_data->drawing->width;
2746 convert_time_to_pixels(
2747 time_window,
2748 end_time,
2749 width,
2750 &closure_data.x_end);
2751
2752
b9a010a2 2753 /* Draw last items */
2754 g_hash_table_foreach(process_list->process_hash, draw_closure,
2755 (void*)&closure_data);
7c0125e0 2756
b9a010a2 2757
2758 /* Request expose */
88bf15f0 2759 drawing_request_expose(events_request, end_time);
b9a010a2 2760 return 0;
2761}
2762
2763/*
2764 * for each process
2765 * draw closing line
e800cf84 2766 * expose
b9a010a2 2767 */
2768int after_chunk(void *hook_data, void *call_data)
2769{
88bf15f0 2770
b9a010a2 2771 EventsRequest *events_request = (EventsRequest*)hook_data;
2772 ControlFlowData *control_flow_data = events_request->viewer_data;
88bf15f0
FD
2773 LttvTraceset *ts = (LttvTraceset*)call_data;
2774
b9a010a2 2775 LttTime end_time;
2776
5c230fc4 2777 ProcessList *process_list = control_flow_data->process_list;
0f090e21 2778 guint i;
88bf15f0 2779 guint nb_trace = lttv_traceset_number(ts);
b9a010a2 2780
0f090e21 2781 /* Only execute when called for the first trace's events request */
43ed82b5 2782 if(!process_list->current_hash_data)
2783 return 0;
0f090e21 2784
2785 for(i = 0 ; i < nb_trace ; i++) {
2786 g_free(process_list->current_hash_data[i]);
2787 }
40debf7b 2788 g_free(process_list->current_hash_data);
2789 process_list->current_hash_data = NULL;
0f090e21 2790
0c5dbe3b 2791 end_time = events_request->end_time;
2792
a56a1ba4 2793 ClosureData closure_data;
ca0f8a8e 2794 closure_data.events_request = (EventsRequest*)hook_data;
b9a010a2 2795 closure_data.end_time = end_time;
a56a1ba4 2796
bc8d270b 2797 TimeWindow time_window =
2798 lttvwindow_get_time_window(control_flow_data->tab);
2799 guint width = control_flow_data->drawing->width;
2800 convert_time_to_pixels(
2801 time_window,
2802 end_time,
2803 width,
2804 &closure_data.x_end);
2805
b9a010a2 2806 /* Draw last items */
14963be0 2807 g_hash_table_foreach(process_list->process_hash, draw_closure,
a56a1ba4 2808 (void*)&closure_data);
cd3892fe 2809#if 0
7c0125e0 2810 /* Reactivate sort */
2811 gtk_tree_sortable_set_sort_column_id(
2812 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
2813 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2814 GTK_SORT_ASCENDING);
2815
2816 update_index_to_pixmap(control_flow_data->process_list);
cd3892fe 2817 /* Request a full expose : drawing scrambled */
2818 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2819#endif //0
2820 /* Request expose (updates damages zone also) */
ca0f8a8e 2821
88bf15f0 2822 drawing_request_expose(events_request, end_time);
ca0f8a8e 2823 return 0;
8b90e648 2824}
2825
b70ceef8 2826/* after_statedump_end
2827 *
2828 * @param hook_data ControlFlowData structure of the viewer.
2829 * @param call_data Event context.
2830 *
2831 * This function adds items to be drawn in a queue for each process.
2832 *
2833 */
2834int before_statedump_end(void *hook_data, void *call_data)
2835{
7b20eed1 2836 LttvEvent *event;
b70ceef8 2837
7b20eed1
YB
2838 event = (LttvEvent *) call_data;
2839
2840 if (strcmp(lttv_traceset_get_name_from_event(event),"lttng_statedump_end") != 0)
2841 return FALSE;
b70ceef8 2842
7b20eed1 2843 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
b70ceef8 2844
b70ceef8 2845
7b20eed1
YB
2846 LttvTraceState *ts = event->state;
2847
2848
2849 ProcessList *process_list = control_flow_data->process_list;
2850
2851#ifdef BABEL_CLEANUP
b70ceef8 2852 LttvFilter *filter = control_flow_data->filter;
2853 if(filter != NULL && filter->head != NULL)
2854 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 2855 tfc->t_context->t,tfc,NULL,NULL))
b70ceef8 2856 return FALSE;
7b20eed1 2857#endif
b70ceef8 2858
7b20eed1
YB
2859 LttTime evtime = lttv_event_get_timestamp(event);
2860#ifdef BABEL_CLEANUP
b70ceef8 2861 ClosureData closure_data;
2862 closure_data.events_request = events_request;
2863 closure_data.tss = tss;
2864 closure_data.end_time = evtime;
2865
2866 TimeWindow time_window =
2867 lttvwindow_get_time_window(control_flow_data->tab);
2868 guint width = control_flow_data->drawing->width;
2869 convert_time_to_pixels(
2870 time_window,
2871 evtime,
2872 width,
2873 &closure_data.x_end);
2874
2875 /* Draw last items */
2876 g_hash_table_foreach(process_list->process_hash, draw_closure,
2877 (void*)&closure_data);
7b20eed1 2878
b70ceef8 2879#if 0
2880 /* Reactivate sort */
2881 gtk_tree_sortable_set_sort_column_id(
2882 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
2883 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2884 GTK_SORT_ASCENDING);
2885
2886 update_index_to_pixmap(control_flow_data->process_list);
2887 /* Request a full expose : drawing scrambled */
2888 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2889#endif //0
2890 /* Request expose (updates damages zone also) */
2891 drawing_request_expose(events_request, tss, evtime);
7b20eed1 2892#endif
10599fb9 2893 return 0;
b70ceef8 2894}
This page took 0.25796 seconds and 4 git commands to generate.