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