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