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