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